注释
如何编写一个简单的 Arduino 草图来呼应一个字符,以确定它是 grbl 问题还是影响这些平台的更广泛的问题? |
@109JB: 有趣的结果。尤其是 Mega 和 Nano 之间的区别。Mega 数据表显示与 Uno 的 328 相同的串行时序错误,因此“应该”排除时序错误,但我认为这里的变量比我们可以确定的要多得多。 只是好奇,将每毫米的步长降低一半或更多如何改变行为?我想知道步进 ISR 是否花费了比预期更多的时间。理论上,执行时间应该是一样的,但是步进 ISR 会以一半的速率触发。这可以帮助排除步进 ISR。 我也会做什么@kfoltman建议并尝试 Arduino 草图。这可能会告诉你一些事情,但很难复制所有事情的确切时间。也许在那里放一个大约 1-4 毫秒的随机延迟,因为这大约是 Grbl 解析和计划 g 代码运动所需的时间。 |
我今天大部分时间都离开了,但我确实编写了,或者更确切地说是修改了一个 arduino 代码,它只接收一个串行字符串,然后用“ok”回显它,以模拟来自 GRBL 的响应。我将详细描述 Arduino 代码的工作原理: 1 – arduino 检测到串行事件并读取单个字符并将其缓冲在字符串变量中。 这是一个 10,000 行 g 代码文件的前几行的示例,后面是返回的内容(去除了“[echo:”和“]”) G01G21G90X-0.5375Y3.5375Z3.3598F4000 G01G21G90X-0.5375Y3.5375Z3.3598F4000 我还发现,无论是使用 Arduino 测试代码还是 GRBL 固件,还是使用字符计数或发送响应,我都可以通过在向 Arduino 发送数据的循环中插入一个小的延迟来消除所有错误。 Arduino 测试代码中的延迟并不能消除错误。此外,应要求@chamnit,改变GRBL中的steps/mm不会影响是否产生错误,但是改变最大速率会。步数/毫米会影响 GRBL 代码,但不会影响 GRBL 流式传输数据所需的速度。但是,更改最大速率将影响需要流式传输数据的速度。所以错误与arduino需要多快从串行流中获取数据有关。此外,使用具有实际移动长度的代码可以消除错误,这也表明流速度是问题所在。 基于使用 GRBL 固件或使用 Arduino 测试代码获取错误,我相信问题与我拥有的 Arduino 硬件有关。我所有的测试都是使用 Arduino 克隆,而不是真正的 Arduinos。我计划在未来得到一个真正的 Arduino Uno,看看是否同样适用于真正的 Arduinos,但我可能需要一段时间才能得到一个。 似乎所需的延迟也取决于我选择的波特率。对于使用发送响应的某些波特率,我不需要任何延迟即可使它们正常工作。对于其他波特率,即使发送响应也需要延迟,但只有非常小的延迟(1 到 2 毫秒)。对于字符计数,所有波特率都需要这种延迟,但有些只需要 1-2 毫秒,而其他波特率需要大约 5-6 毫秒,而另一些则无法正常工作。 我确实想指出,仅仅因为 GRBL 没有抛出错误并不意味着没有错误。例如,我之前的帖子强调了一个示例,其中发送的内容和 GRBL 回显的内容不匹配并没有记录来自 GRBL 的错误,因为该行仍然是正确的 G 代码格式,但坐标值是错误的。我发现的一些错误只是通过使用将 GRBL 回显与原始 G 代码逐行比较的代码才发现的。 |
很久以前,我在 AT90S2313 和 max232 上遇到过这种行为,但是看看16U2 和 Capa 1uF 上的振荡器侧面( Arduino Uno 图中的 2015-11-15 9:33 GMT+01:00 109JB通知@github.com :
|
@euchcat– 谢谢(你的)信息。克隆 Nano 板不使用 16U2,我认为将其归咎于克隆板可能有点为时过早,因为据我所知,没有人在正版板上进行过类似的测试。在真正的电路板上进行测试之前,它们仍然是可疑的。 我已经做了一些更多的测试,并对我的克隆板做出了更多的决定。我制作了一些不同的 Arduino 代码和一些简单的 Visual Basic 测试程序来检查各种事物。以下是重点: 1:我尝试了两个 Arduino 代码来接收串行数据。第一个代码一次读取一个字符,直到使用 Serial.read() 函数接收到“\n”,而第二个代码使用 Serail.readStringUntil() 函数将数据作为整个字符串读取。尽管在功能上是等效的,但使用 Serial.readStringUntil() 的第二个代码导致读取错误少得多,并且可以容忍更快的流式传输。这是一个 Arduino 代码而不是 GRBL,但我不知道 GRBL 在这方面是如何工作的。 2:上述代码也回显了接收到的线路。在代码#1中,我使用 Serial.println() 函数将字符串发回,依靠 println 函数将 \r\n 附加到末尾。在第二个代码中,我添加了一行以先将 \r\n 附加到字符串,然后使用 Serial.print() 函数发送它。这导致更少的错误。我发现这一点是因为我看到响应中的 \r\n 可能与它们应该在的位置不同。例如,延迟了几个字符,甚至在 \r\n 之前缺少 2 行响应。 3:虽然不确定,但我在互联网上阅读了一些内容,表明从 Serial.read() 到 Serial.print() 需要一些时间并且可能导致错误。我读过的一些帖子表明,如果立即从读取到打印,则需要在 Arduino 代码中故意添加延迟。我还没有真正发现这是真的,但我认为我应该提一下。 4:根据我的测试,我很明显无论出于何种原因,我所拥有的 Arduinos 在连续的连续事件之间需要一段时间。我发现 GRBL 和我的测试 Arduino 代码都是如此。GRBL 似乎需要比在发送前将 \r\n 放在末尾的测试代码有更长的延迟。 5:发送-响应协议是 100% 没问题的。我发现只要关闭了定时状态请求,我就无法使用发送响应生成任何错误。随着定时状态请求的开启,我认为可能发生的情况是定时请求可以被发送,从而导致两个串行事件靠得太近,以至于 Arduino 无法处理。这是一个非常罕见的事件。我估计在使用完全不切实际的 g 代码程序和快速定时请求的情况下,我大约每 300,000 行代码就可以做到这一点。对于现实的程序和较慢的请求(0.2 秒),我认为这甚至都不是问题。 6:字符计数协议在发送事件之间需要大约 4 毫秒的 GRBL 延迟,以防止发送比这更快。在大多数情况下,这不会成为问题,但在发送开始时,前几行肯定可以发送得比这更快,从而导致错误。这种延迟确实会减慢速度,但在实际使用中,我认为它不会真正影响实际 G 代码的运行时间。延迟仅在需要减速以防止错误的情况下起作用。可以生成的错误类型是不会导致 GRBL 错误的类型。我的 GUI 在字符计数模式下似乎工作正常,但实际上并不是因为发送了带有细微错误的行。直到我创建了一个例程来逐行比较已发送与回显的行,才发现这一点。 7: 在所有情况下,错误都取决于所选的波特率。Mega 克隆和 Nano 克隆在这方面也有些不同,但我的 Mega 克隆使用 Atmel 16U2 USB 转串行芯片,Nanos 使用 ch340g 芯片。我认为这可能是造成这里差异的原因。我确实注意到 Nanos 有 2 个晶体,一个用于 USB,一个用于 MCU(12 MHz 与 16 MHz),而 Mega 只有一个 16 Mhz 振荡器。不知道该怎么做,但足以说明它们在 USB 和使用的串行硬件方面有所不同。 |
@109JB: 我以为我发表了这条评论,但我一定没有。隔离 USB 串行芯片的一种方法是直接嗅探 Arduino 上的 RX/TX 引脚。在 Uno 上,引脚 0 和 1 连接到 USB 串行和 328p。因此,您将能够看到两者之间的流量。如果 Grbl 通过 TX 线正确接收数据,这意味着它与 328p 和/或 Grbl 的串行通信有关。如果它在 328p 接收之前就出现乱码,那么它是 USB 串行芯片或主机端 USB。 |
@chamnit 在我看来,更好的测试是使用嗅探器程序来监控第二个连接到 Arduino 的 RX/TX 引脚的 com 端口。这将使 GRBL 能够正常运行,但我不确定如何使用我拥有的硬件来执行此操作,因为我的计算机上没有实际的串行端口。我将不得不使用另一个 USB 到串行适配器,这将在循环中引入另一个适配器。然后,如果检测到错误,我将不知道它是否是第二个 USB 适配器。 您可以就如何测试提供任何建议,我们将不胜感激。 谢谢 |
@109JB:不确定您的意思,但 Arduino Uno 引脚 0 和 1 硬连线到 USB 串行芯片和 328p。应该能够从这些引脚读取所有数据流量。我只是想你可以在那里使用另一个 Arduino 来读取传入的 TX 数据,然后让它吐出它读取到你计算机上串行终端的任何内容。免责声明:我从来没有这样做过,但这似乎是可能的。 |
我能够对硬件进行一些测试。我使用 Arduino 论坛上推荐的环回程序来做到这一点。基本上,程序是短接 arduino 上的 TX 和 RX 引脚,并在复位引脚和接地之间放置一个跳线。这使 MCU 处于复位模式,从而使引脚保持低电平。这使 328P 脱离了循环,因此测试只检查主机硬件驱动程序、USB 电缆和 USB 到串行转换器。发生的情况是因为 TX 和 RX 引脚短接在一起,接收到的数据流只是通过 USB/串行转换器发送回计算机。 在我的 Mega 克隆上,它使用与正品板相同的 Atmel 16u USB 到串行转换器,测试立即成功,数据流按预期回显到主机计算机。 在我的纳米克隆上,这个测试涉及更多一点。它并不像 mega 那样简单地使用几根跳线。我使用的 Nano 克隆使用的是 ch340g USB/串行转换器。我确实发现直接在 ch340g 上短接引脚是有效的,所以我认为电路中一定有什么东西使环回测试不起作用。我找不到这个克隆板的原理图,但是用仪表稍微戳了一下,发现 ch340g 的 TX 和 RX 焊盘连接到 328P 的 RX/TX 引脚,每个引脚都有一个 1 k-ohm 电阻就像正版板上的 16U 一样。但是,16U 有单独的焊盘来为 LED 指示灯供电。在 ch340g 上,LED 指示灯由带有 LED 和 1k 欧姆电阻器的 TX/RX 线路供电。我怀疑 LED/电阻器电路可能正在拉动足够的功率,以至于将 TX 和 RX 引脚短接在一起是行不通的。所以,拿出我的小刀,我打破了 TX 和 RX LED 的灯以消除该电路。它工作并且环回测试正在工作。 然后我编写了一个测试程序,发现在使用 Atmel 16U USB/Serial 芯片的 MEGA 2560 克隆上,发送线路的速度超过 2.9 毫秒会导致错误。带有 ch340g USB/串行芯片的 Nano 做得更好一些。Nano 克隆直到大约每 2.2 毫秒发送一次行才会显示错误。有趣的是,ch340g 的波特率越快越好。在 2,000,000 波特率下,您可以以 1.7 毫秒的间隔发送而不会出错。Mega 在所有波特率下都相当稳定。因此,这些延迟时间是 USB/串行硬件正常工作所需要的。 由于我必须“修改”一个 Nano 进行测试,我使用了一个未修改的 nano 和 Arduino 测试代码,并且在主机上使用相同的测试程序发现所需的延迟在测试的波特范围内是相同的(76800, 115200, 230400, 250000, 1M, 2M),除了 115200 和 230400。115200 需要比 USB/串行硬件单独需要更长的延迟,而 230400 根本无法正常工作。所以这其中有一部分与 USB/串行芯片和 328P 之间的波特率匹配有关。该测试证实,尽管 LED 电路干扰了环回测试,但它们并没有干扰正常操作。 测试还向我表明,简单地指责克隆板上的错误是不正确的。我拥有的 Mega 克隆使用与真正的 UNO、Mega 和 Nano 板相同的 Atmel 16u USB 芯片,它的性能与许多克隆板上的 ch340g 芯片相似,但实际上更差一些。 这是什么意思呢?正因为如此,我改变了我的看法,现在认为不应使用字符计数协议,除非主机程序结合了某种方法来确保命令的发送速度不能超过每 3 毫秒 1 行。这是因为引入的错误可能只是数据流中丢失的字符。例如,X12.3456 可能以 X1.3456 的形式出现。最安全的方法是使用 send-response 协议,因为它不会比这更快地发送,因为 GRBL 无论如何都无法以大约每 4 毫秒一次的速度接收和解析一行 我会把它留给@chamnit 决定是否应在 WIKI 中注明。 |
谢谢你的诊断工作,约翰。我想知道他们在旧 Arduinos 上使用的 FTDI 芯片是否存在这个问题。 我想如果要完全绕过 USB 堆栈并改用硬件 UART 和电平转换器(例如,RPi 的片上 UART 连接到 Arduino Pro Mini),您将不太可能遇到损坏问题,并且可能会受益延迟也稍低。 PS作为旁注,76800波特也不适用于ch340g Mac驱动程序(请求250000返回错误状态;76800返回成功但实际上不会连接,所以我猜它错误地配置了波特率发生器) . 驱动程序只是二进制文件,不清楚是谁编写的或如何联系他们,因此修复它的可能性不大。我认为将来我将避免使用 ch340g 进行克隆。 |
@109JB: 同意。感谢您对此进行了如此深入的研究。很高兴知道 328p 和 Grbl 不是原因。我想我们现在可以用你的结果明确地说明这一点。 但是,我仍然不确定是 UBS 串行芯片本身、主机/GUI 还是 USB 协议本身。你的实验还没有完全找出原因,尽管它确实为这个问题提供了很多启示。 我想知道这是否与通过 USB 协议本身发送的数据量有关。在我对 USB 的有限理解中,它非常复杂并且以数据包的形式发送数据。它要么等到一个数据包已满再发送一个,要么等待超时再发送一个不完整的。您能否将消息大小从几个字节更改为 256 个字节并重新进行测试?我认为这可能会有所不同。 另外,我想知道计算机是否与它有关。是否可以使用另一台计算机和/或操作系统?如果行为相同,这将排除操作系统和主机(但不是 GUI)。 |
@AlexHolden– 我认为你是正确的,直接使用 328P 的内置 UART 可以消除 USB 硬件的延迟。我实际上也在想同样的事情,昨晚我正在寻找一个 Arduino Pro Mini 和一个 MAX232 芯片,以便它可以连接到计算机上的实际 RS-232 端口,而不是 USB 到串行的转换。不知道我是否真的会这样做,但我考虑了一下。当然,也可以使用像 RPi 这样的东西直接通信,并且还可以消除 USB 到串行硬件。 @chamnit– 是的。它绝对消除了 328P 和 GRBL 固件,并将其放在上游的某个地方。我明白你关于它是否是 USB 芯片的观点,一般来说是 USB,或者我猜它甚至可能与芯片的驱动程序相关联。我可以在另一台计算机上尝试它,看看它是否在那里。我可以在另一台 Windows 机器上轻松完成,因为我有几个不同的品牌/型号和操作系统。我的主计算机运行 Windows 7,但有几台运行 Windows 10。我不确定在我的旧 XP 计算机上运行是否会告诉我们任何事情,因为它一开始就太慢了。至于导致它的 GUI,除非它是 Visual Studio 或 OS 如何处理 USB 或串行端口的东西所固有的,我认为可以排除 GUI 的编码。我写的测试程序只是使用了一个超简单的循环将一个静态字符串发送到串口。这是显示该循环的代码片段: For i As Integer = 1 To 5000 “j”循环仅用于可调节的人工延迟,我在“i”循环之前和之后获取计算机时钟时间,以计算发送的每条线路的平均时间。在串口读取事件中,比较传入的字符串以确保它与“0123456789ABCDEF”匹配。如果不是,则增加一个“errorCount”变量。同样在这里,“linesReceived”计数器增加,并且在“i”循环结束时,比较确保接收到 5000 行并且没有检测到不匹配。很简单。我同意这仍然可能与构建 Visual Studio 程序时如何处理串行端口事件或操作系统如何处理它们有关。 我可以轻松地修改测试代码以发送更短或更长的字符串,看看它有什么影响。我使用了 16 个字符的字符串,因为我认为这有点接近典型 G 代码命令 (X1.2345Y1.2345) 的平均字符串长度我昨晚对字符串长度有同样的想法,但测试它为时已晚. 我今晚可能有时间。 我也有其他一些额外测试的想法,但是在这一点上,除了上面简单的额外测试之外,我想我会放弃它们,因为简单地使用发送响应没有问题。不过,我可能会在以后的某个时间重新审视这一点。 |
@chamnit– 昨晚我没有太多时间,但能够进行一些测试,我想我可能需要稍微改变我的方法来测试更长的字符串。例如,在 115200 波特和 10 位/字符(1 个开始,8 个数据,1 个停止)下,发送数据流需要(字符数)/11,520 秒。所以如果我的数学是正确的,一个 256 个字符的行需要 22 毫秒来发送字符串。所以我的测试程序方法不太擅长计算延迟。但是,我确实发现确实仍然需要某种延迟。如果我只是让它循环通过而没有人为延迟,它会导致偶尔的错误。我需要研究如何在 Visual Studio 中进行微秒延迟。有毫秒延迟的内置函数,但这些仅适用于整毫秒,所以我不会使用内置函数获得我想要的分辨率,这就是我使用我描述的浪费循环和计算方法的原因。我找到了一些商业可用功能的参考来做到这一点,但价格太高了,所以我可能不得不自己弄清楚。 我现在在想,从发送一行到发送下一行的延迟不仅需要几秒钟,还需要从第一行完成到延迟,然后再发送下一行,这使得它更加复杂。如果是这种情况,那么它甚至进一步支持使用发送-响应协议的需要,因为实际流式传输数据行的时间已内置到该协议中。例如发送连续的 256 个字符行将是 Send(22mS) – Delay(x mS) – Send(22mS)…. 更多的测试即将到来。 |
我刚订购了一个 MAX232 串行到 TTL 转换器。一旦它到达,我应该能够找到更多关于这个的信息。 |
经过进一步的测试,我在我的铣床上回到了 115200,因为我在 250000 看到了我在 115200 没有遇到过的明确损坏。在使用字符计数时发生的频率要高得多,但在呼叫响应时偶尔会发生也。这是一个运行我自己的 GUI 的 RPi 2,连接到带有 Atmega 16u2 转换器的 Uno 克隆。 如果我们的工作假设是 USB 串行转换器有时会在两个写入发生得太近时损坏数据,如果一个块碰巧发送得太接近状态请求实时命令,即使调用响应也会发生这种情况 有趣的是,我打开了回显,当使用呼叫响应时,损坏似乎通常表现为块中的一个字符被替换为“>\r\n”,这看起来有点像状态回复的结尾。例如(从记忆中打字,因为我在车间里没有互联网),GUI 发送了一个类似的命令: |
@AlexHolden: 有趣的结果。它绝对看起来像
|
为了消除诊断问题时的一些猜测,我在我的 GUI 中实现了一个验证例程,如果它从 grbl 接收到与它发送的块不匹配的回显,它会立即停止发送并发送一个中止命令。 增加 grbl 的传输缓冲区大小似乎没有什么不同。改变状态更新频率的结果目前尚无定论。 正式地说,RPi 没有 5V 容错 I/O(有些人报告说不用它,但我不想冒险),所以我订购了一个电平转换器模块,并会在它到货时尝试。也应该可以使用它来窥探来自 16u2 的数据。 |
@AlexHolden– 出于好奇,您目前使用的是真正的 Arduino 或克隆。从我的测试来看,我认为这并不重要,因为我的一个克隆具有与正品相同的 Atmel 16U2 USB/串行芯片,但我想我会问。我看到您有一块带有 Atmel 芯片的电路板,并且您的结果与我的结果非常吻合。 我得出了和你一样的结论。高速运行包含大量短段的代码,或快速状态请求,或这些的组合可能会导致更多错误。在我使用 ch340g 芯片的测试中,虽然似乎以 250000 运行会导致更少的错误,而在我的带有 Atmel 芯片 250000 的 Mega 板上会导致更多错误。我在 ch340G @ 115200 上遇到的错误是整个交易的开始。 事实上,正如我在之前的一篇文章中指出的那样,如果我只是使用发送响应流式传输 G 代码并关闭状态请求,我无法从 GRBL 中得到错误。如果我打开状态请求,我可能会偶尔遇到错误。这是相当随机的,但在我看来,减慢定时请求会导致更少的错误,这是有道理的。 我一直在阅读很多关于 USB/串行芯片如何响应的内容,似乎当它们将数据发送回 PC 时发生的一个常见事情是这些芯片在发送缓冲区中等待一定数量的字节,或者等待一个实际发送数据之前的超时时间。在某些芯片上,超时时间可以在 PC 的驱动程序中设置。但是,Atmel 16U/8U 芯片或 ch340g 似乎都不是这种情况。不确定这是否与它有关。 |
与我的工厂相连的车间中的一个是带有 16U2 的 Uno 克隆。我的大部分 GUI 开发都是使用带有 ch340g 的 Nano 克隆完成的(未连接到真机)。 我实际上并没有尝试完全禁用状态请求,但是在今晚进一步测试之后,如果我提高状态请求率,呼叫/响应模式中的错误肯定会更频繁地发生。 |
我相信我可能已经解决了 16U2 以 250000 波特损坏数据的问题。 执行摘要是 16U2 中的固件有错误,我在这里放了一个固定版本: 请试一试,如果有帮助,请告诉我。 稍长的版本。Arduino(和克隆制造商)在 16U2 上安装的固件是 USBtoSerial 演示的一个分支,它与 LUFA 捆绑在一起,LUFA 是 AVR 微控制器的开源 USB 堆栈。它是从一个不再与最新版本的 avr-gcc 编译的库的过时版本中派生出来的,并且该代码包含几个错误和低效率的问题,LUFA 开发人员已经修复了这些问题。 我所做的是从最新版本的 LUFA 重新分叉 USBtoSerial,在相关的地方应用各种 Arduino 特定的更改。如果您想尝试自己编译,请从此处将我的 USBtoSerial_arduino.zip 解压缩到 LUFA 151115 的 Projects 文件夹中: 在使用 250000 波特的字符计数在检查模式下发送大文件时,我仍然偶尔会感到奇怪,但是症状看起来与我之前看到的完全不同(例如,完整的行没有被回显),我怀疑它可能有不同的原因。 |
使用新的 16u2 固件,我使用呼叫响应协议以 250000 波特成功发送了一千万行测试文件(grbl 处于检查模式),同时以 20Hz 请求状态更新。回声已打开,每个回声都与发送的内容相匹配。 耗时1天8小时;平均每秒 87 行。 我确实将 grbl 的 TX_BUFFER_SIZE 增加到 128;不确定这是否有必要,但 config.h 中的注释建议在启用回显时增加它。 我现在有足够的信心关闭回声并使用 250000 波特的呼叫响应作为我机器上的默认值。 |
@AlexHolden– 我尝试使用 Atmel Flip 编程器将我的 Mega2560 克隆上的固件更新为您的新固件。一切似乎都很好,但是在重新插入 Arduino 后,Windows 无法正确识别它。它显示在设备管理器中,但表示未安装设备的驱动程序。我尝试重新安装驱动程序无济于事。然后我下载并重新安装了 Mega 的“库存”16u2 固件,它又可以工作了。有什么想法可能是错的吗? |
嗨,约翰,我认为问题在于,在 Arduino 发布固件的源代码时,他们从 Atmel“借用”了 USB 供应商 ID。我从发布的源代码中复制了供应商和产品 ID,但不知道他们后来获得了自己的供应商 ID,并在没有更新其 github 存储库中的源代码的情况下创建了更多产品 ID。我认为 OSX 和 Linux 驱动程序只是查看它声称是 CDC 类设备并忽略 VID/PID 的事实,而 Windows 需要在驱动程序 .inf 文件中找到匹配的 VID/PID。 请使用此更新版本重试: 请注意,对于不同的板,还有几个 hex 文件。它们之间的唯一区别是 USB PID 和产品名称字符串;你可以使用错误的,它应该仍然可以正常工作,除了在 Arduino GUI 中可能被描述为错误类型的板。 如果它仍然不起作用,我能想到的 Windows 可能关心的唯一其他区别是我将版本号从 0.01 增加到 0.02。 |
@AlexHolden和@109JB. 非常感谢你们如此努力地了解这一点。这是一个非常有趣的发展。我想知道是否有一种简单的方法可以为遇到此问题的用户诊断此问题。如果有一个快速的解决方案。我知道闪烁 16U2 对大多数人来说并不简单,因为在旧板上,你必须焊接一根电线。 |
在我使用官方 Arduino 16u2 固件进行的测试中,它从未发生在 115200,但它总是迟早会在 250000 发生。使用命令/响应协议并降低状态更新率只会减少它发生的频率。如果没有更新的 16u2 固件,我建议不要使用 250000 波特。 问题基本上是由于主事件循环的工作方式效率低下,如果有很多数据以 250000 波特率来回传输,它有时会耗尽 Arduino->PC 缓冲区中的空间(而且它不会没有办法让 Arduino 停止发送,所以数据不断进来)。更糟糕的是,当这种情况发生时,缓冲区会溢出并破坏 PC->Arduino 缓冲区的内容。 |
@chamnit– 这听起来像@AlexHolden问题是否已解决,因为它与配备 16U2 的 Arduinos 相关。最简单的解决方案似乎是只使用 16U2 Arduino 或克隆并设置 115200 波特,或者如果您想以 250000 波特运行,则为 16U2 加载他的更新固件。我将在我的 Mega 上加载新固件,并在今晚晚些时候试一试。 至于配备 ch340g 的克隆,我正在研究基于 GUI 的工作,我想我有它。由于我认为这个问题与 PC 和 Arduino 串行事件打包在一起,因此我已经对此进行了一些检查,如果有必要,我的测试代码不会在 2 个单独的事件中发送 G 代码行和状态请求,而是将 g 连接起来-代码行和一个事件中的状态请求。我的另一台计算机目前正在运行一个 1,000,000 行的 g 代码以进行第一次测试。在我宣布它有效之前,我会再执行几个。一旦我有时间做更多的测试,我会报告回来。 我希望我的解决方法能奏效,但如果 gui 没有实现这样的东西,那么我认为最好的解决方案是坚持使用配备 16U2 的板。我已经为自己订购了带有 16U2 的 UNO 克隆。 |
使用我的变通方案对配备 ch340g 的 nano 进行了一些测试。我仍然收到回声不匹配,但没有 grbl 错误报告。检查回波不匹配让我相信 GRBL 现在正在获取正确的数据,但回波变得混乱。我这样说是因为回声不匹配的性质。例如,对于发送的这两行 g 代码: X3.1486Z1.331 预期的回声是: [回声:X3.1486Z1.331] 但我得到的是: [回声:X3.1486Z1.ho:X3.1643Z1.3342] 这是第一个回声的第一部分和第二个回声的最后一部分。这并没有导致 GRBL 出错。在我看来,GRBL 正确获取了数据并回显了两次,但可能是由于 ch340g 到 PC 回复缓冲区中的缓冲区问题,它已损坏。一旦我得到我订购的 MAX232 芯片,我将通过使用“真实”串行端口在第二个串行通道上监控 arduino 上的 TX 引脚上的 grbl 回复并将其与 ch340g 发送的内容进行比较来进行测试。我怀疑会有不匹配。听起来这个问题与什么非常相似@AlexHolden在 16U2 上找到了,但我们没有要为 ch340g 修改的固件。至少我找不到。 |
我刚试完@AlexHolden我的 Mega2560 克隆上的新固件。Atmel Flip 编程器可以很好地加载最新的固件,并且非常容易操作。我刚刚使用我的测试流程序通过 grbl 运行了 1,020,001 行 g 代码,没有人为延迟。结果是: 循环时间(秒)= 9321.464(2 小时 35 分 21.464 秒) 一切都很好。谢谢亚历克斯。 |
太好了,谢谢你让我知道它对你有用。 我已将固件从我自己的服务器移动到 Arduino github repo 的一个分支: PS 我今天早上才意识到,在具有 8u2/16u2 的板上,它们具有与主 CPU 相同的振荡器频率和波特率发生器硬件,因此只要 grbl 使用与 USBtoSerial 相同的算法来配置 BRG,它们应该在每个支持的波特率下非常紧密地匹配。即使理论上 115200 波特在绝对值上相差几个百分点,串行链路的两端也会以同样的方式出错。 |
这些示例是从 1971 年到 1981 年的协议,并且仍在使用中。但是
|
@cri-s我完全同意派对这一点,似乎开发人员一般不会因任何原因而烦恼。它添加了很少的代码来处理它,与框架错误等相同。通常人们只是希望最好。 |
首先,我不是电气工程师,我需要其他人来帮助我。我确实知道一些,但他们没有要求改变目前的运作方式。 AFAIK,USB协议集成了发送到设备和从设备发送的数据包的CRC。如果我错了,请纠正我。这表明 USB 串行芯片也执行与主机之间的 CRC。因此,数据损坏必须发生在 USB 串行芯片和运行 Grbl 的 328p AVR 之间。通常这些是彼此相邻的,数据线的局部屏蔽和缓冲应该可以解决大部分 EMI 问题,而良好的电子设计通常具有这些问题。 FWIW,我没有更改 Grbl 中的串行接口,因为没有真正迫切的需求。否则,我很久以前就会从原始设备制造商那里听到一些消息。也就是说,数据错误检查是要做的事情之一,但我认为这最适合 ARM 版本,其中 CPU、闪存和 RAM 限制不再是问题。 |
在此代码之后的 serial.c 上,除了增加一个计数器外,还应该有 else 命令检查 tx 缓冲区是否未满并发送一个字符(如果已配置,例如 CAN),它清楚地发出此事件的信号。if (next_head != serial_rx_buffer_tail) { serial_rx_buffer[serial_rx_buffer_head] = 数据;serial_rx_buffer_head = next_head;} 同样在这里。ISR(TIMER1_COMPA_vect){如果(忙){返回;} // 忙碌标志用于避免重新进入此中断而不是仅仅返回它应该更新一个饱和 8 位计数器,或者如果您更喜欢两个饱和 8 位计数器。如果使用回显功能,tx 缓冲区应至少增加行大小,规划缓冲区块至少减少行大小字节数,规划块缓冲区约为 40 字节,否则可能会出现 RX 缓冲区溢出。
|
据我所知,我可能是错的,只有 usb3 对有效载荷数据有 CRC,usb2 USB 也支持奇偶校验位。
|
所以我只是看到过去几天的这些回复。我是一个业余程序员,所以我倾向于用简单的术语来思考。谈到错误检查、奇偶校验位、CRC 等,我不禁想知道为什么不使用 GRBL 中已经内置的东西来执行错误检查。我编写了几个测试流媒体程序,它们只是比较主机 GUI 发送的内容与 GRBL 回显的内容以及 config.h 中启用的回显功能。看起来 GRBL 在回显响应之前只做 2 件事,即将小写字母更改为大写字母,并删除空格。命令的顺序不会改变。 正如我所说,我已经编写了几个 GUI 类型的流程序来实现这一点,并简单地将发送的字符串与接收的字符串进行比较。发送的字符串应用了相同的 2 个操作(大写和删除空格)。实现回声会有一点性能损失,但是我刚刚编写的一个简单的测试程序表明,使用这种错误检查方法效果很好,并且测试程序可以以每分钟超过 10,000 行的速率流式传输,即使回声打开上。 我个人已经进行了足够的测试,我相信配备 16U2 USB 转串行芯片和修改固件的 Arduino 就可以了。我已经编写了几个测试程序并运行了测试,其中我通过配备 16U2 的 UNO 流式传输多达 200,000,000 行而没有任何异常行为,我个人只是将配备 CH340G 的 NANO 切换为配备 16U2 的 UNO 克隆并且没有回头. UNO 克隆花了我 4 美元,包括运费,所以这不是成本问题。 如果您打算使用配备 CH340G 的 Arduino,那么我同意需要某种类型的错误检查,但没有多少人需要超过 10,000 行/分钟,所以我会说发送到回显的 GUI 比较应该没问题。 |
你好@109JB(大家好) 在软件LaserGRBL 中,我实现了一个流线程,能够发送高达 800 gcode 行/秒。https://www.youtube.com/watch?v=pK9GnzNFpHM 我已经在带有 CH340 的纳米克隆上使用 grbl v1.1f 对其进行了测试,这是我的结果:
然而,一些 LaserGRBL 用户报告了一些流挂断问题。 |
@arkypita– 几件事。
|
谢谢@109JB为您的建议。 使用简单的发送响应 + 回显检查是防止错误的最安全方法(但是如果收到不对应的回显怎么办?)。但是它不适用于公共使用的 gcode 发送器,因为它速度慢但更重要,因为它需要重新编译/刷新 grbl 才能激活回显。 一位 LaserGRBL 用户告诉我,使用 sourcerabbit 他可以流式传输数百万行而不会出错,而使用 LaserGRBL 他总是有错误。错误是 grbl 中的一个挂起(grbl stop 发送回“ok”并且只响应 ctrl-x)。 我在 LaserGRBL 和 sourcerabbit 之间看到的区别在于 LaserGRBL 以 5Hz 查询位置(“?”)和 sourcerabbit 以 1Hz 查询。CH340/grbl 可能有问题吗? sourcerabbit 在开始流式传输之前发送一个“~”而 LaserGRBL 没有,但我真的不重要。 |
@arkypita:激光作业通常对 Grbl 要求很高,尤其是光栅作业和以高步进速率运行。5Hz 的状态查询相当快。每次查询,Grbl 都必须花费几毫秒来生成报告并排队等待传输。这可能会导致通信流中断(停止-启动),其中 Grbl 执行其规划器缓冲区的速度比它从 GUI 接收新动作的速度要快。 高报告率还可能导致接近最大 30kHz 步频的系统开始变得不稳定。唯一的判断方法是您是否使用较慢的刷新率进行测试。 顺便说一句,CH340 固件很可能已经更新以解决这个问题,因为我们在几年前第一次注意到它。带有 CH340 和可能的固件更新的较新 Arduinos 可能不再受到影响。 |
你是个天才@chamnit: 几句话,你把我引向了正确的方向! 我发现,那个用户正在使用非常高的步进/毫米速率(320 步进/毫米),价值 100,101,102 美元。我用这个值进行测试,我发现查询报告 @ 5Hz 并快速流式传输会导致 grbl 挂起。 我几乎可以肯定问题已得到解释。明天我们将通过用户的一些测试得到确认。 |
抱歉,如果我利用您的空闲时间…您认为流媒体线程的最佳方法是什么?睡眠(添加延迟)或在每个连续代码发送之间不睡眠?什么是查询位置的好频率? 附言。在我看来,grbl 所做的事情很神奇,只有当你将它推到极限时它才会投降……但考虑到有限的硬件,它的极限非常高! |
代码发送之间的睡眠不起作用,因此没有理由这样做。 |
亲爱的@109JB @chamnit供您参考,这是我发现的。 我猜挂起的原因是质量很差的 arduino 克隆。 我需要通过启用 grbl 缓冲区报告与该用户一起测试这个假设。 然而,在这项工作的指导下,我利用了一些旨在使 LaserGRBL 更灵活(使查询状态和其他时间更可配置)和更快的改进。 最新版本可以流高达 3000 线/秒 |
@arkypita 我尝试了很多次来纠正这个问题,在配备 CH340 的板上,我无法使用字符计数或发送响应协议来消除这个问题。较慢的流传输速率并不能真正解决问题。我觉得我的 GUI 是由于流和状态请求发生在不同的线程中,因此无法调节状态请求和 g-code 之间的时间,并且仍然可能发生错误。 作为旁注,我不记得我运行了多少测试,但如果我完全关闭状态请求,我认为在 ch340 板上使用任一协议都不会出现任何错误, 最后,我决定使用配备 16U2 的板子,不再回头。我还决定,对于我的使用,发送响应协议足够快。我知道激光爱好者需要比我更快的流媒体。我将 Grbl 与铣床一起使用,铣削不需要激光材料的流速度。出于这个原因,我强烈建议只使用配备 16U2 的 Uno 或克隆。我能够以每个大约 4 美元的价格购买 16U2 Uno 克隆。 |
非常感谢您的详细报告。
在 LaserGRBL 中,我发送 GCode 并在同一 TX 线程中查询状态。但是,即使从两个线程执行此操作也不应该有所不同(除非您忘记在串行上同步发送)。 遇到此问题的用户向我报告说,无论查询状态频率如何,他总是遇到字符计数问题,步长/毫米速率低,但他可以很好地处理发送响应和 1Hz 的查询。我认为这只能几乎完全限制问题,但可能会偶尔再次发生。 最后,用户决定从当地商店购买原装 Arduino UNO,问题现在消失了。我让他把越野车板寄给我,这样我就可以很好地测试它。 |
在我的 gui 中有一个发送“?”的计时器线程。在选定的时间间隔进行状态查询。这个定时器是自己的线程,和G代码发送线程是分开的,但是两个线程都使用同一个串口,所以这个单串口的串口控制来处理发送到grbl的排队和同步。 我要说的是,由于状态请求和 g 代码发送来自不同的线程,因此每次发送的时间可以并且确实会有所不同。即使我要延迟我的 GUI 的 g 代码发送部分,状态计时器也可以从其线程发送请求。因此,您可能在发送之间有时间间隔,或者在发送之间可能没有时间间隔。例如,如果串口正在发送一行g-code,时间为10mSec,而状态报告线程在此期间触发了请求,则状态请求将在g-code行完成后立即发送基本上没有时间间隔发送。听起来您的 GUI 设置有所不同,但这就是我的工作方式。 我们不知道究竟是什么导致了问题,但类似上述情况的情况是我们讨论的可能性之一。此外,当所有这些发送都在进行时,Grbl 正在向 GUI 发送回响应。这一切都要经过CH340芯片,所以也有可能是CH340的收发发生了某种它无法处理的“碰撞”。由于无法检查 CH340 的固件,因此无法知道。 由于克隆板上 CH340 芯片的流行,我尝试了很多与此相关的事情,但有一件事对我来说是肯定的。这是 CH340 的问题,而不是 328P 或 Grbl。以下是我尝试过的一些事情:
|
人们这个错误是什么,以及如何解决它?
C:\Users\acc\Documents\Arduino\libraries\grbl/grbl.h:68:4: 错误:#error “未定义所需的 HOMING_CYCLE_0。” #error “未定义所需的 HOMING_CYCLE_0。”
C:\Users\acc\Documents\Arduino\libraries\grbl/grbl.h:108:4: error: #error “WCO refresh must be greater than one.” #error “WCO 刷新必须大于一。”
C:\Users\acc\Documents\Arduino\libraries\grbl/grbl.h:111:4:错误:#error“覆盖刷新必须大于零。” #error “覆盖刷新必须大于零。”
为“config.h”找到多个库 已 |
您发布的内容与您发布的主题完全无关。 |
关于streamig错误:错误的数字格式,如何纠正错误 |
先生,如果您在右侧查看该命令也是所有轴的 hv 值,但不知何故 grbl 软件具有分离的值和轴,如果您查看屏幕图片,它说删除了不支持的命令。请等待您的进一步支持。谢谢。
|
这不是 Grbl 问题。是发件人的问题。请在 GUI 网站上查找解决方案。 |
危机 评论 2019 年 8 月 6 日
可能您已经设置了一个国家/地区,其中使用“,”而不是“。” 因为你是发件人软件,而不是 GRBL 删除那些“难看”的数字并只发送信件。更改程序以科学/技术格式解析数字的发送软件或更改窗口的区域设置。两者都可以工作,这不是 GRBL 的错误,而是你在美国工作的 Windows 软件的错误,而不是在德国或其他地方的例子。有 101 个使用点的语言环境和 69 个使用逗号作为数字小数分隔符的语言环境。2019-08-06 14:40 GMT+02:00,shivmahesh <notifications@github.com>:
|
请发送gui website.sir的链接,我是软件方面的新手。
|
109JB 评论 on 14 Nov 2015
第一的。让我为这篇文章的长度道歉,但我觉得这是一个非常重要的问题。
我一直在做更多的测试来验证 GRBL 对 g 代码文件的运行。我决定使用一个串行端口嗅探器程序来准确查看发送的内容以及接收的内容,以验证这些未发现的错误是否来自我的 GUI 或其他什么。我已经确定发送到 GRBL 的数据是正确的,但回显的返回不正确,这意味着错误发生在 arduino 或 GRBL 代码中的某个地方。请参阅以下描述以了解我是如何得出这个结论的。
作为进一步的测试,我做了一个小程序用于测试。该程序的流式代码非常精简,除了流式传输和检测 GRBL 错误消息绝对必要的代码外,没有任何额外的东西。没有其他的。发送响应和字符计数协议都可以使用,并且都产生了错误。该程序唯一要做的另一件事是记录 GRBL 回声,以便可以将它们与原始代码进行比较以发现差异。这些文件可以在没有任何定时状态请求的情况下流式传输到 GRBL,并且在关闭定时状态响应的情况下遇到以下错误。
我正在使用修改为只有 G0 命令的 CAM 生成的 g 代码进行测试。这导致非常快速的流式传输。如果我通过在流代码中故意延迟来放慢流速度,它会按预期工作而不会出错,但全速 GRBL 并不总是回显发送的同一行和/或引发错误。我已经通过使用串行端口嗅探器程序验证了发送的行是正确的。
例如,在最近一次使用字符计数流的运行中,在运行开始时发送了以下行:
G01G21G90X-0.5375Y3.5375Z3.3598F4000
X3.8999Z1.0234
X3.896Z1.0262
X3.8645Z1.0475
X3.8566Z1.0527
X3.8212Z1.0742
X3.8173Z1.0765
上面的前 7 行由 GUI 立即发送,字符数包括每行末尾的 LF,巧合的是总共 127 个字符,填充了 RX 缓冲区,并且使用串行端口嗅探器验证了发送的行。GRBL 的回应是:
[回声:G01G21G90X-0.5375Y3.5375Z3.3598F4000]
好的
[回声:X3.8999Z1.0234]
好的
[回声:X3.896Z1.0262]
好的
[回声:X3.8645Z1.0475]
好的
[回声:X3.8566Z1。 0527]
好的
[回声:X3.8999Z1.0742]
好的
[回声:X3.8173Z1.0765]
好的
注意第 6 行。来自 GRBL 的回波具有错误的 X 值,但具有正确的 Z 值。请记住,以上所有信息都来自串行端口嗅探器,而不是来自我自己的程序。但是,当比较来自 GRBL 的回声与原始 G 代码文件时,我的测试程序显示完全相同的内容,显示第 6 行不匹配。同一文件的第二次运行顺利通过了这一点,没有出现错误。
在另一次测试运行期间,发送的行是:
X2.8811Z1.167
X2.889Z1.1702
X2.9362Z1.1889
X2.9441Z1.192
来自 GRBL 的这些回复
[echo: X2.8811Z1.167]
ok
[echo: X2.889Z1.1702]
ok
[echo:]
ok
[echo: ]
ok
[echo: .9362Z1.1889]
错误:预期的命令字母
[echo: X2.9441Z1。 192]
好
这是在检查模式下使用发送响应协议运行的 90,000 行 G 代码文件的末尾。和以前一样,串行端口嗅探器确认生成错误的行已正确发送,并使用 LF 作为行尾字符。但请注意,GRBL 为该单行回显 3 次,并在最终回显中删除“X2”。串行端口嗅探器在发送的数据流中未检测到额外的行尾字符。
我不知道该怎么做。上面的错误,尤其是第一个例子很奇怪,让我觉得这可能是一个 GRBL 问题,但我不确定。我以可以运行的绝对最大速度运行这些测试,并且运行文件的时间可能比其他任何人都长,所以也许我只是超出了 GRBL 的能力,或者这仍然与我报告的波特率问题有关。正如我所说,如果我通过插入延迟减慢流循环速度,但波特率保持不变,错误就会消失。
上周我遇到了似乎与波特率有关的错误。实际上,当仅更改波特率时,这些错误确实消失了,并且使用我的 GUI 中的一个简单代码将原始文件与 GRBL 响应进行比较来验证这一点。我的新测试程序使用相同的比较,运行时的主要区别在于新代码不包括我的 GUI 为固定循环、工具更改支持等实现的所有内容,因此运行循环与可能的。
在我的 Arduino Nano 克隆上,我仍然无法在 250000 波特或 76800 波特上产生错误,但在我的 Aruino Mega 克隆上,情况正好相反,错误出现在 250000 波特,而不是 115200 波特。Nano 使用 ch340G USB 转串口芯片,但 Mega 没有,所以 USB 芯片可能是罪魁祸首。我不确定如何进一步测试,但根据串行端口嗅探器程序显示线路发送正确,在我看来,错误必须与 Arduino 硬件或 GRBL 代码有关。在这一点上,我不知道如何确定它是哪个,但是在流循环中添加一点延迟似乎可以正常工作,但会减慢一点速度。
有人有想法么?