博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【龙印】3D打印固件Marlin中限位开关相关代码解读
阅读量:2360 次
发布时间:2019-05-10

本文共 3668 字,大约阅读时间需要 12 分钟。

本文为在用龙芯1c做3D打印机过程中的笔记。龙芯1c做的3d打印机简称“龙印”.

以我手上的三角洲3D打印机为例,讨论一下限位开关在marlin中的几个应用场景,

3个导轨上方和挤出机各安装了一个限位开关。
在执行G28指令让电机xyz归零时,三个导轨上的电机带动滑块向上运动,直到碰到限位块后停止;
在自动调平时,会利用挤出机上的限位开关来探测是否接触到打印平面了;
在正常打印最下面的几层时,如果调平没有做的很好的话,可能出现打印头移动过程中会触碰到打印平面。marlin对于这种情况的处理是只要碰到打印平面则立即放弃当前gcode指令,转而执行下一条gcode指令。

现在来看marlin源码,读取限位开关状态的函数是update_endstops(),其中定义了一个宏UPDATE_ENDSTOP(AXIS,MINMAX),这是函数update_endstops()的要点,其它的是各种编译宏为了兼容各种3d打印机而设置的,这里重点分析宏UPDATE_ENDSTOP(AXIS,MINMAX),源码如下

// Check endstops - Called from ISR!inline void update_endstops() {  #if ENABLED(Z_DUAL_ENDSTOPS)    uint16_t  #else    byte  #endif      current_endstop_bits = 0;  #define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_## MINMAX ##_PIN  #define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_## MINMAX ##_ENDSTOP_INVERTING  #define _AXIS(AXIS) AXIS ##_AXIS  #define _ENDSTOP_HIT(AXIS) SBI(endstop_hit_bits, _ENDSTOP(AXIS, MIN))  #define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX  // SET_ENDSTOP_BIT: set the current endstop bits for an endstop to its status  #define SET_ENDSTOP_BIT(AXIS, MINMAX) SET_BIT(current_endstop_bits, _ENDSTOP(AXIS, MINMAX), (READ(_ENDSTOP_PIN(AXIS, MINMAX)) != _ENDSTOP_INVERTING(AXIS, MINMAX)))  // COPY_BIT: copy the value of COPY_BIT to BIT in bits  #define COPY_BIT(bits, COPY_BIT, BIT) SET_BIT(bits, BIT, TEST(bits, COPY_BIT))  // TEST_ENDSTOP: test the old and the current status of an endstop  #define TEST_ENDSTOP(ENDSTOP) (TEST(current_endstop_bits, ENDSTOP) && TEST(old_endstop_bits, ENDSTOP))  #if ENABLED(COREXY) || ENABLED(COREXZ)    #define _SET_TRIGSTEPS(AXIS) do { \        float axis_pos = count_position[_AXIS(AXIS)]; \        if (_AXIS(AXIS) == A_AXIS) \          axis_pos = (axis_pos + count_position[CORE_AXIS_2]) / 2; \        else if (_AXIS(AXIS) == CORE_AXIS_2) \          axis_pos = (count_position[A_AXIS] - axis_pos) / 2; \        endstops_trigsteps[_AXIS(AXIS)] = axis_pos; \      } while(0)  #else    #define _SET_TRIGSTEPS(AXIS) endstops_trigsteps[_AXIS(AXIS)] = count_position[_AXIS(AXIS)]  #endif // COREXY || COREXZ  #define UPDATE_ENDSTOP(AXIS,MINMAX) do { \      SET_ENDSTOP_BIT(AXIS, MINMAX); \      if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX)) && current_block->steps[_AXIS(AXIS)] > 0) { \        _SET_TRIGSTEPS(AXIS); \        _ENDSTOP_HIT(AXIS); \        step_events_completed = current_block->step_event_count; \      } \    } while(0)
要看懂宏UPDATE_ENDSTOP(AXIS,MINMAX),就必须了解宏中“##”的含义,“##”是宏定义连接符,这里就是把宏参数与宏参数或者字符串连接在一起组成为另一个宏。
比如:_ENDSTOP_PIN(X,MIN)为X_MIN__PIN,其中X_MIN__PIN是一个宏
      _ENDSTOP_HIT(X)为SBI(endstop_hit_bits, X_MIN__PIN)
      其它的类似
假设更新x轴上的限位开关的状态,x轴上限位开关是min型的(即把信号通过限位开关与地相连),那么宏UPDATE_ENDSTOP(X,MIN)为
    do { \
      SET_ENDSTOP_BIT(X, MIN); \
      if (TEST_ENDSTOP(_ENDSTOP(X, MIN)) && current_block->steps[_AXIS(X)] > 0) { \
        _SET_TRIGSTEPS(X); \
        _ENDSTOP_HIT(X); \
        step_events_completed = current_block->step_event_count; \
      } \
    } while(0)
每条语句额注释为
    do { \
      SET_ENDSTOP_BIT(X, MIN); \  读取X轴上限位开关状态,并设置current_endstop_bits
      if (TEST_ENDSTOP(_ENDSTOP(X, MIN)) && current_block->steps[_AXIS(X)] > 0) { \  如果上一个step和当前这一个step都碰到了限位开关,则说明真的碰到限位开关了
        _SET_TRIGSTEPS(X); \ 把当前的位置记录到endstops_trigsteps中
        _ENDSTOP_HIT(X); \ 记录当前是xyz中那个轴碰到了限位开关
        step_events_completed = current_block->step_event_count; \  结束当前gcode指令(可能当前这条gcode指令还未执行完),准备运行下一条
      } \
    } while(0)
函数checkHitEndstops()中会调用checkHitEndstops()检查endstop_hit_bits,一旦发现有碰到限位开关的,则打印相关信息
变量step_events_completed是步进电机定时器中断中用来记录已经执行的步数,据此可以判断一个block是否执行完成。

步进电机定时中断中调用update_endstops()的代码如下

if (current_block != NULL) {    // Update endstops state, if enabled    #if ENABLED(HAS_Z_MIN_PROBE)      if (check_endstops || z_probe_is_active) update_endstops();    #else      if (check_endstops) update_endstops();    #endif
好了,理解了这些,分析指令G28应该不成问题。

转载地址:http://cestb.baihongyu.com/

你可能感兴趣的文章
敏捷开发一千零一问系列之三十六:跨平台开发的人员和代码复用
查看>>
关于微软的VB和C#:为何Basic需要存在,为何VB如此像C#,为何两者不合并等
查看>>
度量分析之报告信息的四个层次:数据,信息,分析,措施
查看>>
如何将asp.net MVC2项目升级为MVC3项目(微软官方自动升级工具:ASP.NET MVC 3 Application Upgrader )
查看>>
怎样在Razor中使用HtmlHelper(MvcHtmlString)
查看>>
彼得定律与员工职业生涯规划(该提拔谁,职业规划,知人善用)
查看>>
敏捷开发一千零一问系列之十三:故事点好还是人天好?
查看>>
敏捷开发日常跟进系列之四:跟进表
查看>>
敏捷开发免费管理工具——火星人预览之一:需求与故事树
查看>>
敏捷开发免费管理工具——火星人预览之二:编辑故事,产品管理,组织结构
查看>>
敏捷开发免费管理工具——火星人预览之三:迭代,计划会,分配
查看>>
敏捷开发免费管理工具——火星人预览之四:故事板,燃尽图,我的工作项
查看>>
敏捷开发免费管理工具——火星人预览之五:常见问题问答
查看>>
CSDN10大博客栏目火热评选中
查看>>
敏捷开发团队管理系列之五:大型研发团队的切分(刚参加3.17 MDP团队管理场次的读者请看)
查看>>
敏捷开发免费管理工具——火星人预览之六:我的空间,我的通知
查看>>
敏捷开发一千零一问系列之十四:敏捷开发加班吗?
查看>>
jqueryui 1.8.19引用顺序(及var basePrototype = new base()错误)
查看>>
火星人敏捷开发手册2012-04-30新增敏捷日常跟进内容
查看>>
敏捷开发一千零一问系列之二十:怎样持续改进?(兼谈共振)
查看>>