开源改变世界

更新通信案例(XON/XOFF流控) #50

推推 grbl 2年前 (2023-01-21) 188次浏览
关闭
chamnit 打开了这个问题 2012 年 1 月 25 日 · 49条评论
关闭

更新通信案例(XON/XOFF流控)#50

chamnit 打开了这个问题 2012 年 1 月 25 日 · 49条评论

注释

更新通信案例(XON/XOFF流控) #50
成员

在这里我想开始讨论是否应该将软件xon/xoff流控制集成到grbl的串行接口中。在使用上有利也有弊,实施起来也比较容易。

主要和最大的好处是任何标准串行终端程序都支持 xon/xoff 软件流控制。这确实简化了将 g 代码流式传输到 grbl,因为用户只需发送/上传文件,grbl 应该将其执行到文件末尾。第二个重要的好处是 grbl 可以立即从串行读取缓冲区访问下一个 g 代码块命令,而无需执行“ok”握手并等待响应。这确实加快了速度并防止了规划器饥饿。

主要缺点是它限制了流媒体接口并且可以限制控制,因为串行端口是与 grbl 的唯一软件连接。在状态报告讨论中,提出了一个问题:如何在流式传输 g 代码程序的同时发送运行时命令,如暂停和中止?如果 XOFF 标志在其接收缓冲区已满时从 grbl 发送,这会有效地阻止与 grbl 的传输通信,除非设计了特殊的流接口来强制传输运行时命令字符。在这一点上,一个专门的流接口抵消了简单性的好处。

现在,stream.py脚本通过计算和跟踪发送到 grbl 缓冲区的字符来执行伪 XON/XOFF 流控制。不完全干净和简单,但有效。

所以我想我的问题是:你们都看到 grbl 的主要界面在哪里?保留“ok”和“error:”响应界面是否有意义,或者我们是否应该开始研究有效的替代方案以进行替换或增强?这一切都应该考虑到不要放弃当前的用户支持并在没有充分理由的情况下弄乱他们的界面。

更新通信案例(XON/XOFF流控) #50
成员

最初我只想使用 xon/xoff 或 rts/cts 流控制。我的计划是

$ cat myshape.gcode > /dev/usb-serial239847239

然后它就消失了。但我的实验一无所获。据我所知,我使用的串行适配器(主要是 FTDI)或 Mac OS X 不支持流量控制,这对我来说是整个考验。我很想知道我错了。我个人认为更好的缓冲是可行的方法。如果我们支持快速缓冲到 SD 卡或类似方便的东西,我们可能根本不需要流量控制,因为我们总是能够吞噬输入。

更新通信案例(XON/XOFF流控) #50

我个人是用XON/OFF的方式控制串口流量的,但是马上就遇到了这个问题,当buffer满了,发生XOFF的时候,无法发送feedhold, Reset, Status这样的run-time command字符报告,所以我放弃了,我回到了起点,我只是在发送下一个 gcode 行之前检查了 ‘ok’ 的返回。我认为在 Satus 报告中包含一个标志以指示过程结束并且缓冲区为空会很有趣,因为流式传输代码的结束并不意味着移动结束,我无法检查是否过程真的完成了,尤其是当 gcode 的最后几行是轴长移动时。这是一个小视频,展示了一个用于控制 GRBL 和 Tinyg 的简单应用程序。 http://www.youtube.com/watch?v=li7HwmOskMM

更新通信案例(XON/XOFF流控) #50

我在 TInyG 上使用 XON/XOFF 插入字符时遇到过同样的问题,但它确实有其用途。这是一种将文件简单地传输到设备的有用方法。我已经以这种方式在 Coolterm (Mac) 上运行带有 FTDI 芯片的 TinyG 一段时间了,它非常可靠(我会说完全可靠,但不知何故我会被证明是错误的!)。但是,如果你想注入实时命令,你真的需要将发送者设置为每次传输只发送一个 Gcode 块,或者 – 正如 Simen 所建议的那样 – 有一个“无限”的高级缓冲区(就像一张大于任何实用的 Gcode 文件)。我不认为你可以两者兼得。我的偏好是同意可以在响应行中轻松扫描的单个同步字符(例如 >)。

更新通信案例(XON/XOFF流控) #50
成员作者

还有几个缺点要补充。软件流控制仅限于字符传输,不能发送二进制数据,因为二进制数据总是有机会发送 XON/XOFF 位序列。这会阻止快速、高效的二进制模式状态报告,除非以 base32 或 base 64 ascii 字符串编码。对于仍然使用“ok\n”响应也可以这样说。二进制数据也有可能触发这种情况,尽管这种可能性很小。

其次,我读到一些终端仿真器不会立即遵守 XOFF 命令,并且可能导致缓冲区溢出,除非串行缓冲区非常大并且可以处理延迟。流量控制的处理方式可能因终端而异。Alden 对 Coolterm 的使用可能是个例外,而 Simen 的“socat”和管道则不是。尽管我也可能错了。

因此,似乎有两种选择:实施 XON/XOFF 及其所有缺点或更新并继续我们一直使用的应用程序级流量控制方案(’ok\n’)。

  • 对于 XON/XOFF,二进制数据是不可能的,因此将数据压缩为 base32 或 base64 ascii 字符可能是最简单的方法,可以通过一些 CPU 开销进行快速有效的状态报告。可能需要进行测试以确保 XON/XOFF 在大多数终端仿真器上可靠地工作,并且 grbl 没有缓冲区溢出问题。并且仍然需要一种方法来强制将运行时控制字符传输到不属于标准流协议的 grbl,但用户可以使用任何终端使用 grbl sans 运行时控制。(仍然有用)。
  • 使用我们的应用程序级“ok\n”流量控制,我们可能必须进一步开发和授权某种协议。如果是这样,我仍然会使用“ok\n”响应,因为它对新用户来说并不神秘。可以通过为接口创建一个头部来发送二进制数据,表示正在发送一个固定大小的二进制数据包。这种类型的协议非常简单且易于用户使用,您发送并等待直到“ok\n”,但存在延迟问题并且串行读取缓冲区通常总是空的。如果我们继续使用这个协议,我们需要让用户更容易地保持串行读取缓冲区满,就像 XON/XOFF 协议一样,这对某些人来说可能是一个挑战。

大家怎么看?正如奥尔登所说,我们不能两全其美。或者也许我们可以?

simen:一张SD卡肯定能解决所有这些问题。您所要做的就是将文件上传到 grbl,然后点击运行。就那么简单。我真的很想看到这在某个时候发生。这个问题将不得不释放数字引脚 10-13 用于 SD 卡屏蔽,它们被限位开关占用(我们可以将其减少到一个引脚吗?)和主轴控制引脚,并确保我们有足够的 RAM 和闪存来安装它(我听说 FAT16 库很大)。

sacidu93:非常漂亮的界面!我喜欢看到人们能够毫不费力地编写自己的程序。在状态报告中包含缓冲区状态目前正在讨论中,可能很快就会进入 grbl。

更新通信案例(XON/XOFF流控) #50

实现 XON/XOFF 的首选方法是使用高水位线/低水位线方案。当缓冲区(比如说)90% 满时发出 XOFF,而当它(比如说)5% 满(同时耗尽)时发出 XON。这允许系统滞后,并通过引入滞后来防止系统抖动。这就是它在 TinyG 中的实现方式。

如果我们走 SD 卡路线,我会将其设计到 grblshield 上,这样您就不需要多个防护罩。我们还应该计算出归位开关的首选引出线和任何其他硬件要求。

更新通信案例(XON/XOFF流控) #50
成员作者

我读过高低水位线方案,但不知道它的用途。这就说得通了。谢谢奥尔登。

假设我们两者都做。保留标准的“ok\n”响应以指示已接收和解析块/行。有没有办法在连接时自动配置 XON/XOFF 协议?如果是这样,用户或界面可以选择使用其中之一。

grblshield SD 会很棒。尽管如此,如果支持 SD 卡,这将需要与生产中的任何东西兼容,我认为它使用数字引脚 10-13。西门你怎么看?硬着头皮改变引脚分配?

更新通信案例(XON/XOFF流控) #50

这是对高位的激烈竞争。如果您假设保持下端口与 0.6 引脚分配相同 – 不破坏对 RX/TX、3 步和 3 个方向位的支持 – 那么需要为 SD 卡或 3 限制/分配上端口位归位开关和 2 个主轴控制(根据 0.6 引出线)。所以你得到一个或另一个,但不是两个。我想这就是权衡。

更新通信案例(XON/XOFF流控) #50
贡献者

我会选择 XON/XOFF(高水位线/低水位线方案)协议。如果客户认可它,那很好:我们为具有许多不同终端的用户提供了尽可能快地流式传输 gcode 的能力。如果用户应用程序忽略该协议,那么什么也不会丢失。
也应该可以忽略 XON/XOFF 并使用使用“ok\n”协议的流式脚本或计算发送的字符数。
此外,只要 gcode 逐行发送,运行时命令仍然可以通过任意终端发送(在不使用流控制时也需要这样做)。
如果流脚本告诉串行驱动程序不使用流控制,它仍然可以注入运行时命令。
这实际上是我实现任何客户端的方式:使用无流控制驱动程序并在程序代码中处理 XON/XOFF(尽管要注意客户端缓冲区)。然后,当 gcode 流被 XOFFed/halted 时,程序仍然可以发送运行时命令。
我真正看到的 XON/XOFF 的唯一缺点是与二进制数据不兼容。但是二进制数据仍然可以在 128…255(第 7 位设置)范围内发送,这也会清楚地将其标记为二进制。

@chamnit:我们需要为每个轴单独设置限位开关,以便在同时归位 x 和 y 时知道哪个轴已经完成。
@chamnit和 alden:你确定任何 atmega 都有足够的闪存用于 grbl 和 FAT 库。也许我们需要考虑一个搭载的第二个 arduino,它可以处理 SD 卡和用户界面串行通信(可能还可以计算步数或读取位置反馈)。我想我在 youtube 上看到了类似的设置。也,最好保留一些用于硬件慢跑和进给保持输入的引脚。
@sacidu93: 您的应用程序的源代码是否公开?

更新通信案例(XON/XOFF流控) #50

我不确定你为什么要使用二进制文件。我知道那里有一些效率,但它真的值得麻烦和复杂吗?在采取该步骤之前,我宁愿看到一些传输时间和周期预算的分析。打包/解包处理将增加,代码大小将增加,而字符数和传输时间将减少(这也可能会稍微减少周期)。您可能会发现没有它实际上有足够的时间和带宽,并且可以避免复杂性。

使用 115,200 作为默认波特率也值得一看。当我看到它时,它是显而易见的,xmega 实际上只有 328 的 2 倍快。实际上,没那么多。

更新通信案例(XON/XOFF流控) #50
成员

我完全同意。纯文本协议实际上是自我记录的。对于二进制,人们将不得不处理字节序等等。我也同意波特率。以这样的速度运行 grbl 没有问题——我已经做过很多次了。我在发行版中保持 9600 的唯一原因是我相信它是许多系统的默认速率。它通常适用于大多数人,而无需深入研究他们的 man 文件。

更新通信案例(XON/XOFF流控) #50

坚持使用 9600 很酷(一方面,它避免了 Coolterm 设置中的一个步骤)。我会看看 9600 是否支持状态报告预期的数据更新率。100 个字符的行(过多,我敢肯定)大约需要 100 毫秒来传输,将可实现的最大更新速率设置为 10 Hz。这可能就足够了。

那就是说:如果你想将文件转储到 SD 卡上,你可能想要修改它。115,200 开始看起来不错。

更新通信案例(XON/XOFF流控) #50
成员

同意。我真正想做但从来没有想过的是通过使用 RX 引脚的中断功能在启动时自动检测波特率,然后要求客户端输入几个输入字符来“唤醒”grbl。那将是严重的 0-conf。

更新通信案例(XON/XOFF流控) #50

Riley 在他编写的控制台中做了类似的事情。它适用于 TinyG 和 grbl。它到达电路板,直到获得响应,然后进行相应的配置。板载自动波特率会很酷。那里必须有一些 atmega 示例代码。

更新通信案例(XON/XOFF流控) #50
贡献者

也同意了。服务于终端和类似 GUI 的纯 ascii 协议应该是首选解决方案。我只是想解决对 XON/XOFF 的担忧。

更新通信案例(XON/XOFF流控) #50
成员作者

哎呀!好多评论要回复。。

Alden:首先,我不是引脚分配方面的专家,但是我们有什么理由不能开始将模拟引脚用作数字引脚?我从 Arduino IDE 了解到这非常简单。不确定它在 C 中的开发如何或需要什么。

对于微处理器,两倍的速度意义重大。这些 CPU 的开销不大,通常执行速度几乎是原来的两倍。根据我开发 grbl 的经验,328p 的性能限制是真实存在的,我已经多次遇到它。获得一些额外的周期会很棒。

simen 和 alden:好吧,我不得不承认我不知道传输二进制文件到底需要什么。我假设这意味着您所要做的就是按照接收方已知和期望的设定顺序和大小发送每个变量的8 位字符部分。(或者像 Jens 状态一样对 ascii 字符 > 127 使用 7 位二进制打包,这基本上用二进制解决了这个 xon/xoff 问题。)如果是这样,这可以非常快速和有效地完成。

另一方面,我最近一直在浏览print.c源文件。要打印整数值,您必须对每个基数进行取模和除法。所以对于 base10 中的数字 94857,你有 5 个模和 5 个除法。把这一切加起来,假设你有大约 10 个整数/浮点值,每个值有 5 个数字,你需要以 20Hz 的速率发送,grbl 将必须每秒计算 1000 个模数和 1000 个除法以按所需的速率打印这些值。这加起来真的非常快。如果我们可以显着优化打印功能,那么我完全可以不包括二进制传输的能力(不一定是集成)。重申一下,只有在高速状态报告时才真正需要二进制传输,而不是其他任何东西。

至于增加波特率,我在更高的波特率下使用 grbl 也没有问题。我读过,但没有经历过,如果其他中断延迟串行中断按时执行,唯一需要注意的是在最高波特率下丢失数据位。在 115200 波特率下,每个脉冲约为 8.5 微秒,步进中断处理最少占用 3 微秒。

Jens:引脚开始供不应求,特别是如果包含 SD 卡支持(不确定它是否适合 grbl)以及循环启动、进给保持和中止控制用作引脚。将限位开关销降低到一个将释放两个。可以可行地重写归位循环以一次移动一个轴以翻转每个限位开关以定位归位。

不确定忽略字符的 XON/XOFF 协议是什么意思。将此设置为用户 EEPROM 设置以启用/禁用 XON/XOFF 流控制会更好吗?这将是直截了当且容易做到的。然后用户不必让他们的界面脚本忽略这些字符。

更新通信案例(XON/XOFF流控) #50
贡献者

哦,非常好,我完全忘记了 div 和 mods。有一些特殊的函数可以同时执行 div 和 mod,因为 mod 总是 div 的副产品。但是对于仍然有一些处理器负载的浮点数。
还有其他方法可以将 float 转换为 ascii。可以使用存储的数字 10000、1000、100、10、1、0.1 等,然后从要转换的数字中减去它们,计算使结果为负数所需的减法,这就是相应小数位的十进制值(如果需要,我可以尝试重新查找示例源代码)。但这仍然是嵌套循环,也许你对二进制传输的必要性是正确的。

通过“忽略”,我的意思是从输入流中过滤 XON/XOFF 字符,但不对它们做出反应……但这需要对流脚本进行一些更改。最初我认为偶尔的 XON/XOFF 字符可以像任何其他 grbl 响应一样打印到控制台,但这可能会破坏“ok\n”协议……我想得太快了。

我已经使用模拟引脚作为数字 IO 没问题,同样的程序,甚至不必禁用模拟或任何东西。

更新通信案例(XON/XOFF流控) #50

我为 TinyG 编写了一些高效的字符队列处理程序,只是为了看看我能把它推到什么程度。事实证明,如果您从顶部到底部加载队列,您可以在零上进行测试以执行环绕操作,然后它就变成了指针或索引加载。这是最有效的方法(我认为),因为递减到零会设置 Z 状态位,因此分支“免费”出现,没有其他操作。这符合“将 C 编译器用作机器人来编写如果您不那么懒惰就会编写的汇编器”的理念。如果需要,您可以在 xio 模块中找到代码。

关于模拟 IO 的好消息。我没有看到那个。如果将开关和主轴移动到电路板的模拟侧,则看起来可以支持所有功能。

更新通信案例(XON/XOFF流控) #50
成员作者

首先,我不得不说这是一次很棒的头脑风暴会议。惊人的。

看起来集成 XON/XOFF 方案可能是一件好事,但也许作为任何用户都可以切换的高级设置。(这引出了我的下一个问题,即设置的结构应该是什么样子,但这应该从另一个线程开始。)无论如何,我们似乎有一些关于如何使用 XON/OFF 传输二进制文件的选项,即 7 位高位 ascii Jens 建议的角色(顺便说一句,好主意)。对于不需要运行时命令或将这些控件移动到引脚的用户,这将大大简化将 g 代码流式传输到 grbl。而且,如果他们需要通过软件运行时命令,任何人都应该能够编写自己的特定流接口。此外,如果我们允许这种切换,这不会让当前用户陷入困境,他们仍然可以使用他们的标准和简单的“ok\n”调用和响应协议。

如果有人需要查看一些关于如何实现 XON/XOFF 的示例代码,我相信 Jens 已经从他的 fork、edge branch、serial.c 开始了。

Alden: *模数和除数来自二进制数到字符格式的转换。看起来 TinyG 使用标准库来打印和转换字符。Simen 在 print.c 中安装了他自己的相同打印方案的精简版本,主要是为了最小化闪存大小,但我相信这与标准库的操作方式相同。

这对模拟 IO 引脚来说是个好消息。有人反对将主轴启用和速度引脚移动到模拟 0 和 1,同时将限位开关引脚减少到引脚 9 上的一个吗?还可以在模拟引脚 2、3、4 和 5 上支持 cycle_start、feed hold、about 和 jogging(切换开/关)。这将用完除数字 IO 10-13 之外的所有引脚,这将是为 i2c、SD 卡、以太网接口或其他用户分配的引脚保留。

更新通信案例(XON/XOFF流控) #50

打印语义不同,但最终结果相同。TinyG 将 AVRGCC stdio 库用于串行,并成功地包含了浮点库,因此它可以支持格式化的打印字符串(“J Offset = %8.3f\n”以及诸如此类的东西)。这对于 328s 来说是太多的代码膨胀,所以它不是 Arduino 硬件上的真正选择。

除非绝对必要,否则我仍然对走二元路线感到不安。我认为对打印例程进行一些测试是合适的。如果不必在接收端处理二进制文件就好了。

早期的一个小修正 – 一个运行在 115,200 的 USART 大约每 86 微秒中断一次,而不是每 8.6 微秒中断一次,因为每个接收到的字符(通常是 8 位,1 位起始位,1 位停止位)中断发生一次,所以它没有它那么糟糕似乎。

更新通信案例(XON/XOFF流控) #50
成员作者

奥尔登。
除非需要,否则我无意安装二进制报告方案。可以这么说,这是一种提前计划并确保我们
不会把自己逼入绝境的练习。我猜对于大多数
人来说,基于字符的报告就可以了。对于想要
非常快速和实时报告的人来说,二进制可能是可行的方式,
至少在 328p 处理器上是这样。

115,200 波特时序仍然正确。
对于每个 USART 中断,该 10 位字符序列的每一位每 8.6 微秒发送一次。

2012 年 1 月 26 日星期四下午 6:53,Alden Hart <
reply@reply.github.com

写道:

打印语义不同,但最终结果相同。TinyG
将 AVRGCC stdio 库用于串行,并成功地包含
了浮点库,因此它可以支持格式化的打印字符串(“J Offset =
%8.3f\n”和诸如此类的东西)。这对于 328s 来说是太多的代码膨胀,
所以它不是 Arduino 硬件上的真正选择。

除非绝对必要,否则我仍然对走二元路线感到不安。我认为对打印例程进行一些测试是合适的。
如果不必在接收端处理二进制文件就好了。

One small correction from earlier – a USART running at 115,200 interrupts
roughly every 86 microseconds, not every 8.6 microseconds as the interrupts
occur once per received character (typically 8 bits, 1 start bit, 1 stop
bit) so it’s not quite as bad as it seems.


Reply to this email directly or view it on GitHub:
#50 (comment)

更新通信案例(XON/XOFF流控) #50

Agreed on all points. Perhaps I misinterpreted the baud timing question. The processor doesn’t need to be concerned about the 8.6 uSec bit timing (which is correct) as the USART handles all that. The processor will, however, be interrupted every 86 uSec, and if a higher priority interrupt is running that takes longer than that serial characters can be lost. But that’s not a situation that should be of concern as the step timer gets in and out in way less than that. Sounds like I’m agreeing with you but arguing over details. No matter. Just me being thick headed.

更新通信案例(XON/XOFF流控) #50
MemberAuthor

I guess it would be a good time to make a summary on this discussion:

  • Install XON/XOFF flow control as a toggle-able setting, either at compile-time or in EEPROM (to be discussed how). This will give users have a simpler interface for streaming g-code sans run-time commands. Higher level users can and should write their own advanced interfaces. ‘ok\n’ and ‘error:’ protocol will remain the same.
  • Higher baud rates are available as a compile-time setting and would likely need to be faster than 9600 baud for fast status reports. This could be available as an EEPROM setting as well (will start a new discussion on settings). If we can do this as auto-config instead, this would be even better.
  • Data flow back to the user, i.e. status reports, will be in ascii form only. Binary data, which will not be officially supported for now, may be packed into the higher ascii character set to avoid flow control problems.

If anyone has any objections to these points, let everyone know. Otherwise, we’ll solidify these points as goals and move on. Other things that still need to be ironed out on other threads is pin-reallocation for future uses and developments and how advanced

喜欢 (0)