对于入行一年的我来说,桌面级FDM打印机很多功能细节,我还没能仔细了解:藏在固件代码背后的信息内容,我也远没有完全消化。这正说明一个简单的道理:消化一段代码的最有效方法是对其移植或者重写。换言之,仅仅是走马观花的浏览一遍,除非自己曾经编写过类似程序,很难能透彻的领会固件代码的精髓。特别是对Marlin这个数百名(可能不准确)开源工程师贡献和维护的大型固件项目。

Marlin的步进电机驱动子系统,是由中断响应函数实现的。如果是恒定速度的步进电机驱动,实现就和这句话一样简单。不过对于3D打印机系统,x,y轴的运动往往速度变化非常频繁:不仅在每次更新位置的速度不同,而且每一段位移的速度也需要经历加速,恒速和减速阶段。这是由机械系统的惯性特征决定的:如果不同动作之间的速度衔接不好,会对电路系统造成强大的电流冲击。特别是3D打印过程,这种速度的变化每次打印任务都数以万计,这就意味着电路寿命将大打折扣。

Marlin系统的速度衔接[1],这是一个支撑步进电机速度和控制器计数器频率关系的算法理论,由IBM的工程师于1994年发表并于2004年在控制器内实现。这里算法实现的关键在于路径规划器(planner)。路径规划器的设计意味着,程序在执行步进电机的动作之前,就已经计算好了整个过程的速度曲线。后面就只是Stepper模块忠实地执行。

在机器层面,这样的设计减少了中断响应函数中的运算量,这对于单片机来说非常友好。同时3D打印机的机械运动相比控制器的16M主频来说要慢很多,路径规划器相比直接驱动,增加了一个运动缓存。这样就能够有效的利用控制器的高频率,里面蕴藏着“空间换取时间”的思想。

在代码层面,planner的本质在于对于一个FIFO的管理。使用C++的结构体指针数据结构能够非常优雅的实现这个缓存的创建和管理:planner.h:typedef struct {

// Fields used by the bresenham algorithm for tracing the line

long steps_x, steps_y, steps_z, steps_e;  // Step count along each axis

unsigned long step_event_count;           // The number of step events required to complete this block

long accelerate_until;                    // The index of the step event on which to stop acceleration

long decelerate_after;                    // The index of the step event on which to start decelerating

long acceleration_rate;                   // The acceleration rate used for acceleration calculation

unsigned char direction_bits;             // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)

float nominal_speed;                               // The nominal speed for this block in mm/sec

float entry_speed;                                 // Entry speed at previous-current junction in mm/sec

float max_entry_speed;                             // Maximum allowable junction entry speed in mm/sec

float millimeters;                                 // The total travel of this block in mm

float acceleration;                                // acceleration mm/sec^2

unsigned char recalculate_flag;                    // Planner flag to recalculate trapezoids on entry junction

unsigned char nominal_length_flag;                 // Planner flag for nominal speed always reached

// Settings for the trapezoid generator

unsigned long nominal_rate;                        // The nominal step rate for this block in step_events/sec

unsigned long initial_rate;                        // The jerk-adjusted step rate at start of block

unsigned long final_rate;                          // The minimal rate at exit

unsigned long acceleration_st;                     // acceleration steps/sec^2

unsigned long fan_speed;

#ifdef BARICUDA

unsigned long valve_pressure;

unsigned long e_to_p_pressure;

#endif

volatile char busy;

} block_t;

block_t block_buffer[BLOCK_BUFFER_SIZE];            // A ring buffer for motion instfructions

volatile unsigned char block_buffer_head;           // Index of the next block to be pushed

volatile unsigned char block_buffer_tail;

volatile 关键字确保了队列头和队列尾被不同函数访问过程中,编译器不会因为优化和丢失更改行为。block_t类型的指针可以方便的方位结构体内任何元素。在后面的planner规划动作plan_buffer_line()中,代码可以用非常优雅的结构体指针来完成。

每当3D打印机解析到位移指令的时候,plan_buffer_line()函数就被调用。在里面新的block_t首先被创建,并且排入队列的队尾;然后执行calculate_trapezoid_for_block(),计算新的block_t的关键速度节点及其对应的step数目;接着更新队列里面所有block_t的连接速度:之前队尾的block_t的收尾速度和相关速度节点会被更新。最后调用st_wake_up()保证stepper执行的中断打开。

而在%steppper中,ISR函数负责在主循环之外,执行队列里可能存在的所有block_t。在ISR中,首先由plan_get_current_block()读取队列首的block_t,然后按照结构成员的step数,调用STEP_ADD和STEP_IF_COUNTER两个宏来执行x,y,z三轴的运动。ISR每执行一次,三路各发出一个脉冲,并通过lamp ramp算法更新,根据下一个速度值来更新OCR1A寄存器来设定下一次中断响应的周期。

整个软件C++实现妙至毫巅。建议大家在win环境使用eclipse来查看Cpp工程。eclipse对条件预编译的支持非常完美,#if def能够准确显隐,可读性非常好(见下图)。全局查询,go to define等功能也很完备。

另外,eclipse有丰富的快捷键支持看代码:用ctrl+shift+G就能查到变量的引用;F12就能查到变量的定义。Alt+左键 /右键回到之前的鼠标位置和之后的鼠标位置;用CTRL+SHIFT+P就能寻找括号的另外一半。

marlin固件烧录教程_Marlin固件的步进电机控制代码解析相关推荐

  1. marlin固件烧录教程_Marlin固件配置教程详解

    首先从Marlin固件GitHub下载固件源代码,也可从Makeboard网盘下载. Marlin固件主要分为两个版本,一个是1.0.2-2版本,是稳定版,已经一年没怎么更新了,功能比较少,网上的教程 ...

  2. marlin固件烧录教程_ESP32 MicroPython教程:uPyCraft IDE入门

    介绍 本MicroPython教程的目的是解释如何开始使用uPyCraft,这是一个支持ESP32 的MicroPython IDE. IDE (集成开发环境) 是一种软件, 它通常集成一组工具, 使 ...

  3. marlin固件烧录教程_小白穿越机教程-刷固件 | 穿越机如何刷最新的betaflight固件教程...

    关注公众号[FPV One],用最酷的姿势玩穿越机✈️ 哈喽,大家好,我是小哥! (这是一期系列教程,我会从原理,部件,组装,调参,飞行技巧等几个方面来介绍新手如何入门穿越机.) 往期精彩内容,别错过 ...

  4. marlin固件烧录教程_【打印虎】Marlin firmware RepRap Prusa i3 3D打印机固件配置教程.pdf...

    [打印虎]Marlin firmware RepRap Prusa i3 3D打印机固件配置教程 [打印虎原创]RepRap_Prusa_i3_3D 打印机固件 Marlin_firmware 配置教 ...

  5. ESP8266固件烧录教程

    在使用esp8266开发过程中,或者拿到买的esp8266模块时,有时需要先给esp8266刷所需要使用的固件,摸索许久,下面分享可用的经验教程. esp8266固件烧录分在线网站编译和esp32程序 ...

  6. marlin固件烧录教程_i3型3D打印机制作详解――Marlin固件介绍

    Marlin固件下载 基本配置 使用 Arduino IDE 打开 marlin.ino,切换到 Configuration.h 即可查看并修改该文件.或者使用任何一款文本编辑器(notepad,no ...

  7. marlin固件烧录教程_marlin2.0应用到STM32实践(续)

    platformio.ini文件在将default_envs配置为STM32F407VE_black之后实际起作用的就是下文中的这些内容: [platformio] src_dir = Marlin ...

  8. 魔百盒cm211-1_ZG-晶晨S905和CH-晶晨S905L3B线刷-刷机固件及教程

    魔百盒cm211-1_ZG-晶晨S905和CH-晶晨S905L3B线刷-刷机固件及教程(固件在文章底部) 固件说明: 1.不带ROOT权限,分别适用于魔百盒CM211-1-ZG-晶晨S905L芯片.魔 ...

  9. ESP32固件烧录-初级入门

    我一开始入门esp32的时候找关于固件下载好长时间都没有找到适合入门的固件烧录教程.现在学了一段时间,所以想要写一篇关于esp32固件烧录的教程,去帮助一些入门的朋友. 这篇文章主要参考的官方文档的说 ...

  10. Hi3516DV300开发板固件烧录

    Hi3516DV300开发板固件烧录经验 1. 固件烧录的一般流程 钟老师讲解的十分详细:electronic_borad-固件烧录 2. 问题与解决方法 对于推荐的烧录方式:个人推荐网口烧录,方便且 ...

最新文章

  1. Ubuntu 安装 Etcd
  2. 消防信号总线原理_消防报警系统中消防模块分类与用途简介
  3. 剑指offer面试题23:从上到下打印二叉树(树的层序遍历)
  4. 如何在用例之间传递值_接口测试:A12_HttpRunner_cookie整理_01_提取指定cookie值
  5. 前端学习(2459):账户设置
  6. [BZOJ1565]植物大战僵尸
  7. linux备份和还原设置密码,AnyBackup Linux操作系统备份与恢复最佳实践手册(33页)-原创力文档...
  8. Mysql事物隔离级别
  9. 学习PriorityQueue源码
  10. 一篇搞定导航守卫(vue-router源码学习)
  11. Javascript数据类型转换第六课
  12. 帆软 在线Cron表达式
  13. Postman安装以及使用
  14. 给自己的Web站点嵌入一个免费的图片编辑器
  15. python解非线性规划问题_Python+Gurobi+Pulp解决线性规划问题
  16. word 插入mathtype公式对象后,默认环绕方式是浮于文字上方,每次插入后都得手动改成嵌入,如何解决?
  17. Clickhouse基本函数( 转载)
  18. AcWing 1875.贝茜的报复
  19. MySQL密码忘记了如何操作
  20. 哲学家与心理学家在选择性知觉上的不谋而合

热门文章

  1. 我看韩剧《寄生虫》,一副好牌究竟是怎么被打烂的?
  2. html网页综合项目实战
  3. MATLAB图像处理学习日记之图像的自定义裁剪imcrop操作
  4. 谈谈Fragment的用法之Fragment实现Tab切换中的那些事
  5. python列表排序sorted_python列表使用sorted排序的方法
  6. 台式计算机睡眠快捷键,电脑如何设置快捷方式迅速进入睡眠的状态?
  7. 如何合并excel文件
  8. factorial函数
  9. Python中文字符串,变成英文字符串
  10. lpush rpush 区别_关于redis之lpush、rpush、lset、lrem