【发布时间】:2011-04-05 18:12:30
【问题描述】:
我正在开发通过串行端口控制 8 位 MCU 的现有驱动程序。 MCU 有许多不同风格的固件,但它们都有一个共同的方法来尝试确保链路完整性。这种方法不是很健壮,我正在寻找有关驱动程序如何修改其行为以充分利用它的想法。
命令是带有行号和校验和的 gcode:
N3 T0*57
N4 G92 E0*67
N5 G28*22
N6 G1 F1500.0*82
N7 G1 X2.0 Y2.0 F3000.0*85
N8 G1 X3.0 Y3.0*33
行号必须是连续的(但可以用M110 重置)。如果校验和不匹配或行号乱序,固件将回复Resend: nnn,其中nnn 是最后一次成功的N 加1。“校验和”非常原始:
// Calc checksum.
byte checksum = 0;
byte count = 0;
while(instruction[count] != '*')
checksum = checksum^instruction[count++];
主要问题是主要错误机制是丢弃字节,因为中断被推迟,导致 1 字节 MCU FIFO 溢出。实际的串行总线在 FTDI(或类似的)USB 串行桥和 MCU 之间只有几厘米,因此不太可能出现位错误。我从未在固件的回复中观察到一点错误。
如您所见,上面的算法会检测到一个丢弃的字节,但如果您丢弃了两个相同的字节(任何地方!),结果仍然会匹配。因此F3000.0(进给率 3000mm/min)可以转换为F30.0 并且仍然匹配。另外,字符集非常小,因此永远不会涉及某些位。
驱动程序可以做些什么来使给定的线路更健壮?
- 添加或删除尾随(甚至前导)零
- 添加或删除空格
- 重新排序单词(
X1 Y1与Y1 X1相同) - 添加或删除空格
- 在一定的公差范围内对值进行“无关紧要”的修改(例如,
F2999.9而不是F3000) - 重置行号以获得给定行的特定
N - 将单个命令分解为多个等效命令(例如,
G1 X2变为G1 X1G1 X2假设最初 X=0) - 消除(或添加)多余的词(例如,
T0对大多数命令来说是没有意义的,如果你发送F3000一次它暗示将来可以选择发送或不发送)
如果我认为固件会分组丢弃字节,那么最重要的事情可能是避免像 00 这样的背靠背重复,这将(如果一起丢弃)是不可见的。
【问题讨论】:
-
明确一点 - 您无法控制或修改 8 位 MCU 的固件以使用不同的校验和/或命令行解释器?
-
都是开源的,所以这绝对是一种可能。对于那里的许多固件实例,使驱动程序尽可能健壮会很好。 (虽然更好的固件修改是更好的串行通信管理!)
-
容差修改思路吓人!在复杂的序列中,公差可能会叠加,客户会发现在您的机器上制造的零件似乎永远不会很合适!
-
关于容差修改思想的另一件事:“F2999.9”和“F3000”有同样的问题——连续三个'9'字符和一个连续三个'0'字符一样糟糕排。您必须执行“F2989.9”之类的操作,以避免连续删除 2 个相同的字符。似乎要引入很多错误。它仍然会丢失两个未检测到的九,尽管非连续丢失的字符可能更不常见。
-
协议中是否有任何“回读”机制?即您能否要求机器回显您刚刚发送的进给率,以确保它是正确的?
标签: embedded serial-port driver checksum