开源改变世界!!

停止然后停止(重置)? #26

推推 grbl 2年前 (2022-10-30) 147次浏览 0个评论
关闭
jjg 打开了这个问题 on 17 Jun 2011 · 81 条评论
关闭

停止然后停止(重置)?#26

jjg 打开了这个问题 on 17 Jun 2011 · 81 条评论

注释

停止然后停止(重置)? #26

jjg 评论 on 17 Jun 2011

我开始使用 grbl 和 Arduino diecimila,它适用于简单的形状(正方形、星形),但是当我喂它任何复杂的东西时,它会表现出这种行为。认为这是由于 diecimila 的限制,我用 Arduino Uno 替换了它,我看到了类似的结果。

问题表现为系统在工作中停止,通常大约 20 步,几秒钟后,步进电机“倾斜”,然后没有其他反应。

接下来我认为这可能是我正在使用的 gcode 流设置(在我的 mac 上的 windows VM 内运行的 windows 程序)所以我切换到使用 stream.rb 但我看到了相同的结果。详细输出如下所示:

Jason-Gullicksons-MacBook-2:script jasongullickson$ ruby​​ stream.rb -p -v sat_0003.nc
处理文件 sat_0003.nc
G90
G21
G0 X24.0755 Y19.7266
M03
G1 F30.000000
G1 X21.1376 Y13.253
G1 X14 .1191 Y14.1956
G1 X16.1185 Y17.1478
G1 X24.0755 Y19.7266
M05
G0 X18.1316 Y23.9059
M03
G1 F30.000000
G1 X15.5065 Y19.6021
G1 X12.8133 Y148.9263
G1 X1. Y22.5187
G1 X18.1316 Y23.9059
M05
G0 X14.9624 Y17.8414
M03
G1F30.000000
Grbl >>
Grbl >> Gr
Grbl >> Grbl 0.6b
Grbl >> ‘$’ 转储当前设置
Grbl >> 错误:预期的命令字母
G02 X14.8158 Y17.1606 I-1.6543 J0.0001
Grbl >> ok
G02 X14.1191 Y15.9741 I-5.8858 J2.658
Grbl >> ok
G02 X13.2008 Y14.9285 I -7.3696 J5.5469
Grbl >> 好的
G02 X11.9564 Y13.8577 I-8.9782 J9.1746
Grbl >> 好的
G02 X9.7392 Y12.5417 I-7.032 J9.322
Grbl >> 好的
G02 X8.42 Y12.2571 I-1.3192 J2.9147
Grbl >> 好的
G02 X7.755 Y12.5034 I-0。J1.0207
Grbl >> 正常
G02 X7.5087 Y13.0396 I0.4604 J0.5362
Grbl >> 正常
G02 X7.9513 Y14.4099 I2.3424 J0。
Grbl >> 好的
G02 X10.2154 Y16.7921 I9.8949 J-7.1373
Grbl >> 好的
G1 X10.8139 Y15。

G01 X10.9566 Y15.3499
Grbl >> 好的
G03 X11.2219 Y15.4405 I0。J0.434
Grbl >> ok
G03 X11.4472 Y15.7168 I-0.4639 J0.6082
Grbl >> ok
G01 X11.4532 Y15.9207
Grbl >> ok
G1 X10.8547 Y17.2723
Grbl >> ok
G02 X12.9356 Y18.4741 I5.875 J-7.7708
Grbl >> 正常
G02 X14.0511 Y18.6239 I0.8323 J-1.9682
Grbl >> 正常
G02 X14.7161 Y18.3776 I-0。J-1.0208
Grbl >> ok
G02 X14.9624 Y17.8414 I-0.4604 J-0.5362
Grbl >> ok
M05
Grbl >> 错误:错误的数字格式
Grbl >> ok
G0 X13.9287 Y18.375
Grbl >> ok
M03
Grbl >>

G03 X13.2109 Y18.259 I0.0001 J-2.2796
Grbl >> ??C?????0.6b
Grbl >> ‘$’ 转储当前设置

…此时“突然”发生了,我从 Arduino 上拔下 USB 线。

如果有帮助,我可以包含 gcode 文件(它是使用 Inkscape 生成的),或者您能想到的任何其他信息。

我期待使用 grbl,感谢您的辛勤工作!

停止然后停止(重置)? #26
成员

四门 评论 on 17 Jun 2011

谢谢!我已经将该脚本用于复杂、长达一小时的铣削工作,没有任何问题,但我偶尔会引入错误。我会尽快去。

停止然后停止(重置)? #26
贡献者

jgeisler0303 评论 on 17 Jun 2011

嗨,也许你的问题是由于 arc 命令。它们目前不支持加速管理。因此,当您尝试以电机无法立即跳到的进给率运行弧时,它们将停止。我有一个类似的问题。

我开始了一个叉子,当我的磨坊(http://www.youtube.com/watch?v=6DoqTpJEfDE)完成后,我将尝试实现一个更快的弧算法,允许加速管理。我已经有一个在 MATLAB 中工作的概念。但自从我们刚开始买房以来,可能需要一些时间:-)

停止然后停止(重置)? #26
作者

jjg 评论 2011 年 6 月 19 日

这是有道理的,因为我很幸运地运行了没有曲线(星形、方框等)的形状,但其他文件(例如这个文件(字母“J”)和另一个有椭圆的形状似乎就是它的那些)窒息。

我能做些什么来解决这个问题,也许是不同的 grbl 配置设置等?我正在使用我制造的 2 轴激光器,并且仍在试验进给率等。

感谢您查看,我一定会发布我所做的任何成功更改!

停止然后停止(重置)? #26
贡献者

jgeisler0303 评论 2011 年 6 月 19 日

就目前而言,您可以为每个圆弧命令添加一个非常低的进给率。对我来说,这很有效。

停止然后停止(重置)? #26
作者

jjg 评论 2011 年 6 月 21 日

我一直在做一些实验,我有更多关于这个问题的细节。

我将控制器升级到“边缘”固件,并且能够使用 ruby​​ 脚本可靠地制作由直线组成的形状。但是,我仍然遇到弧线问题。

我生成了一些 gcode 来画一个圆圈:

G90
G21
G0 X22.8783 Y11.8311

M03
G1F30.000000
G02 X19.9515 Y4.9224 I-9.6173 J0.
G02 X12.722 Y1.9956 I-7.2294 J7.4652
G02 X5.4926 Y4.9224 I0. J10.392
G02 X2.5658 Y11.8311 I6.6905 J6.9087
G02 X5.4926 Y18.7398 I9.6173 J-0.
G02 X12.722 Y21.6666 I7.2294 J-7.4652
G02 X19.9515 Y18.7398 I0. J-10.392
G02 X22.8783 Y11.8311 I-6.6905 J-6.9087
G1  X22.8783 Y11.8311
M05

G0 X0.000 Y0.000
M05
M02

当我使用 ruby​​ 脚本将其流式传输到 grbl 时,圆圈的前半部分运行良好。然而,当我们进入圆圈的三分之一时,激光开始减速(这是加速开始了吗?),直到圆圈完成 3/4 时完全停止。

现在,如果我使用终端手动输入 grbl 每一行,也会出现同样的减速,但是一旦达到 3/4 点,速度就会再次缓慢增加,直到在完成圆圈时恢复正常速度。

我将看看我是否可以更改/禁用加速以查看这是否有任何影响(也许我什至看错了方向)但是如果这些信息提供了对问题的任何见解或者如果您有任何建议,请通过他们一起。

谢谢!

ps 这是我当前的 grbl 配置:

$0 = 53.330 (steps/mm x)
$1 = 53.333 (steps/mm y)
$2 = 755.906 (steps/mm z)
$3 = 30 (microseconds step pulse)
$4 = 30.0 (mm/min default feed rate)
$5 = 480.0 (mm/min default seek rate)
$6 = 0.100 (mm/arc segment)
$7 = 0 (step port invert mask. binary = 0)
$8 = 25.0 (acceleration in mm/sec^2)
$9 = 50.0 (max instant cornering speed change in delta mm/min)
停止然后停止(重置)? #26
贡献者

jgeisler0303 评论 2011 年 6 月 21 日

据我所知,弧线总是在没有加速度的情况下绘制的。他们应该跳到并以指定的速度(你的 F30)运行,可能在每个 gcode 行之间会有一点小插曲。它们实际上由非常短的行组成。我真的不明白为什么你的弧线变慢了。您可以检查它是否真的是减慢的步进,或者是否绘制了线段之间的中断。尝试使用 6 美元(毫米/弧段)。也许从 3 毫米开始。
干杯,延斯

停止然后停止(重置)? #26
成员

四门 评论 2011 年 6 月 28 日

你对弧线的看法是正确的。他们在加速管理方面有点难以正确,而且我个人发现我根本不使用弧命令。我宁愿让我的 CAM 软件用线条生成近似值,因为无论如何它们都必须为任何其他弯曲形状做。

我打算以永远不会超过设定的加加速度限制的安全速度运行弧线。这可能是保守的,但老实说,在我完成加速版之后,由于一些愉快的个人情况,我没有太多时间使用 Grbl 进行生产。我期待很快回到实验室并进行一些调整。在那之前:请随时向我提供有关如何解决这些问题的详细建议。

停止然后停止(重置)? #26

我刚刚尝试运行此代码,但我以 F1000 的进给率运行它。我的步进器的分辨率约为每毫米 157 步。所有的弧线对我来说都是一样的。我的问题在于弧段之间有明确的停顿。当进给率低时它并不明显,但我相信它仍然会发生。我对此没有信心,但我认为发送命令行时会暂停。在读取该行之前,它似乎停止了运动。这绝对不好,它使弧线无法使用。我也不相信这种情况不会发生在海峡中,但我会继续试验。

停止然后停止(重置)? #26
贡献者

jgeisler0303 评论 2011 年 6 月 29 日

你观察到的行为是正确的。目前 grbl 等待缓冲区在新的弧开始之前被清除。此外,在发送线路之后,需要一些更复杂的浮点数学运算才能生成运动命令。
在我的前叉中,我正在做一些修改,希望能让弧线更快、更平滑。但目前该代码完全无法使用。只有 MATLAB 文件夹在一些简单的脚本文件中显示了基本的 Idea。Wiki 列出了计划中的修改。
@simen: 很抱歉我们以这种间接方式取得联系。我非常尊重您的工作,并且一直想写信给您分享一些想法,并可能为 grbl 做出贡献。但是我不喜欢分享未完成的东西,因为我不知道什么时候我会准备好东西,所以我不想太早做出任何承诺。我希望很快能和你更频繁地交谈。

停止然后停止(重置)? #26
成员

四门 评论 2011 年 6 月 29 日

没问题!我曾经在 grbl 的旧版本中有一个适当的整数圆插值器。它占用了大量的代码空间,而且非常复杂,我意识到我从未使用过 arc 命令,而是让 CAM 工具生成一个近似值。我同意,如果弧线在日常使用中很重要,那么代码需要一些爱。我会欢迎一个精心制作的补丁或任何可能导致比我上次使用的更简单的插值器的建议。

但是看到弧只是弯曲特征的一种非常特殊的情况,我认为它应该被弃用。我可能错了。

停止然后停止(重置)? #26

我也遇到了类似的弧问题(UNO w/grbl edge)。我写了一个类似于 simen 的 ruby​​ 流脚本的 python 脚本。当我发送 g 代码块并且总是在发送另一个块之前等待“确定”确认时,只要正在处理弧块,串行端口就会冻结。完成后,串行端口将再次打开以允许更多数据。这很奇怪。这只会在处理弧线时发生,始终如一。如果缓冲区为空,这将导致意外停顿。

我设法通过强制预缓冲区而不等待确认来修复缓冲区等待问题,然后恢复等待“确定”(在切换之前刷新读取缓冲区)。只要缓冲区中有另一个 g 代码块,并且我的 arc 测试 g 代码程序运行顺利,没有任何问题。g 代码基本上创建了 2 个圆形和 2 个带有内部圆角的正方形。每个弧是 90 度或 180 度弧。处理弧时串行端口冻结仍然会发生,但缓冲区会在执行其他任何操作时快速重新填充。

无关,我遇到了弧模式的 i 和 j 命令的问题。它不做全圆 360 块,并且在处理它时会做一些奇怪的事情。它偶尔会加速到无限速度并使 Arduino 崩溃。幸运的是,当它发生时,我的步进器会发出一声响亮的高音呜呜声。到目前为止没有损坏电机或驱动器。

停止然后停止(重置)? #26
成员

四门 评论 2011 年 8 月 6 日

我真的很抱歉弧线。事实是我真的很讨厌他们。它们在 G 代码和解析器中引入了很多复杂性,但仅代表弯曲形状的一种非常特殊的情况。就我个人而言,我从不使用它们,但让我的 CAM 工具为我近似任何弯曲的形状。

当涉及到 360 度 g 代码时,从技术上讲,这可能是一个应该修复的错误,但标准建议您永远不要在单个命令中渲染超过 180 度的弧,因为舍入错误会在不同的机器上产生不可预测的结果.

grbl 中 arcs 的高级实现很不错,但是我不得不承认实际的 step 生成有点破旧。弧线强制同步是正确的,它排除了我为所有其他运动实现的漂亮流水线。作为一个反对弧的人,我对此犹豫不决:以一种漂亮而坚固的方式完成对弧的支持,或者将其全部撕掉并留给代码生成器。

停止然后停止(重置)? #26

是的。从技术上讲,您只需 G00 和 G01 即可完成您需要的所有动作。使用 G02/03 的唯一原因是可读性、易于手写和直接编辑 g 代码。虽然很方便,但它不是必需的,因为它基本上是一个简单的固定循环。此外,就像您说的,您可以让功能强大的 CAM 系统为您进行翻译,甚至可以使用预处理器 Python/Ruby 脚本将 G02/03 块翻译和流式传输到 grbl。

在阅读了您的代码库后,我明白了为什么难以使其精简和高效,尤其是考虑到所需的计算数量、将其集成到您的加速规划器中以及 Arduino 的空间限制。我会投票赞成从微控制器中完全消除电弧运动。相反,我会使用节省的 CPU 和内存来改进加速计划器并实现您提到的添加的那些功能:第 4 轴、PCM 输出到进给率以及状态/进度反馈。

我对 Python 相当流利,如果它对您的项目有用的话,我会尝试为 grbl 编写预处理器。这种方法的好处之一是可以更完整地实现 g 代码标准,即固定循环、可调进给率、单程序段执行等,同时保持 grbl 简单、高效, 并且灵活适用于许多应用程序。

停止然后停止(重置)? #26
作者

jjg 评论 2011 年 8 月 6 日

感谢大家跟进此事。

仅供参考,我正在使用从 Inkscape 插件生成的 g 代码(我相信该插件是用 python 编写的)。由于我没有直接生成 g 代码,因此我不知道我可以控制它用来生成弧线等的内容,但我可以使用您所讨论的后处理器来转换从插件中出来的代码-进入 grbl 更喜欢的东西。

当然我也可以重写插件,但是我对python不是很熟悉,至少现在还不是。

如果您想出一些方法来进行此转换并需要帮助测试,请告诉我,谢谢!

停止然后停止(重置)? #26

大家好

我想开源的问题之一是跟上每个人的步伐。近一年来我没有在 grbl 上做过任何工作,但我确实花了一些时间来解决电弧停滞问题。我的大部分贡献都在这个提交中:

bobgates@ e4b7919

我之前对 grbl 进行了更改,因为我引入了一个小型命令解释器,并且我试图完全摆脱阻塞。正如你们都知道的那样,Grbl 在线路上已经是非阻塞的,但是在弧上停止,因为它们没有作为弧排队。我的代码标记了一个弧,然后将其所有子段排队。如果队列有 10 条命令,当弧中剩余的段少于 10 条时,它将允许另一个 g 代码指令进入队列,结果是下一条命令在弧之后立即开始。

我不能保证上面的提交是唯一需要改变的东西,后来有一些调试,但看看组织如何绘制弧的想法。它对我有用!我在 Simen 引入加速之前就这样做了,所以不能保证让它与加速一起工作可能需要什么。

停止然后停止(重置)? #26

嗨,鲍勃。除非您的修改很重要,否则我看不出为什么您的方法不适用于 Simen 的加速度曲线计算。您只需将新的插值插入到队列中,然后再进入加速代码。这与我在 Arduino 上使用 Python 后(前)处理器将其转换为在 grbl 上运行效率最高的内容没有什么不同。

我担心的是 Arduino 不是最擅长多任务处理或速度非常快的。我怀疑,如果您开始添加许多新功能,例如第 4 轴和状态报告,以及用于弧线和其他内容的内部 gcode 转换器,您将开始限制 grbl 运行多个步进脉冲序列的速度。我建议尽量减少 grbl 必须在内部做的所有事情,但只添加它需要的功能,就像 Simen 已经在做的那样。

如果一切都高效,我不明白为什么 grbl 可以进化为运行 5 轴或 6 轴机器或六足机器人。问题是:要获得最大的灵活性和实用性,您需要的最低限度的功能是什么?

停止然后停止(重置)? #26

首先,看起来 grbl 试图做 Bob 所说的事情,但我不确定它为什么被禁用,除了它可能在速度或其他方面对加速规划器不友好。不能确定,直到我回到家尝试一下。

供参考。我花了一些时间研究当前对最佳进给率生成的研究,试图让自己在外出工作时保持忙碌。本质上它看起来是 g 代码插值和规划的问题。使用有限且不断变化的前瞻进行动态规划是很困难的,尤其是对于线性插值曲线。研究人员现在正在使用带有约束优化方法的 b 样条曲线近似来求解预处理器中的曲线,并将曲线作为短参数集发送到控制器,以便在控制器中快速有效地重建它们。(参见 Timar 和 Farouki,2005,沿曲线刀具路径对 CNC 机器进行时间优化控制的算法。)有一个更新的算法,它也解释了在较高速度下较低的电机扭矩。

停止然后停止(重置)? #26
成员

四门 评论 2011 年 8 月 17 日

这是正确的:chhamnit。圆圈是通过缓冲许多细小的线段生成的。禁用管理的原因是微型处理器在计划所有细线时窒息。一种强大的解决方案是仅增加分段大小并重新启用规划。

有许多更高级的方式来实现加速管理。我选择了一种简单的方法,我认为这种方法对于您在典型的家用铣削中看到的进给率和刀具惯性来说已经足够了。Grbl 中的管理器保证恒定的线性加速度,并将所有速度变化限制为特定的恒定加速度。此外,它允许用户接受某种突然的“跳跃”速度,这似乎会产生更合理的转弯。鉴于规划器只查看未来大约 10 个命令(由于内存限制),它可能会错过本可以继续以更高速度运行的机会。在这些情况下,计划者会犯错误,以确保永远不会超过设定的加速度。根据我使用 Grbl 进行铣削的经验,这没有实际意义。

理想情况下,您想要管理“混蛋”(加速度随时间的变化(加速度派生)),但我认为这种方法不适合有限的平台,并且很难用简洁的代码表达我更喜欢这个项目。

停止然后停止(重置)? #26

很公平。我读过的大多数关于高级进给率规划的文献在实施到现实世界方面仍然很幼稚,或者仅适用于大批量生产的高速加工。将这样的东西视为开源会很有趣,也许在某个时候,我会将这个 Pythagorean-hodograph 方法作为一个副项目来试一试。

另外,前几天我刚刚注意到 jgeisler0303 的 fork 刚刚发布了一个重写的支持弧的规划器。看起来它删除了 sin() 和 cos() 计算,并用计算效率更高的计算替换它们,以使其与规划器一起工作。我不确定他与当前的 grbl master/edge 相比有多大变化,但我会尝试看看。

停止然后停止(重置)? #26
贡献者

jgeisler0303 评论 2011 年 8 月 17 日

我提交的代码又很原始(很多注释的 printf 调试行并且没有经过很好的测试)。无论如何我都做了,所以完美主义不会导致永远不做。我已经知道两个小错误,但是在我现在完成的磨机上的第一次运行显示出非常令人满意的结果。

该代码是具有许多新功能的重大返工(更好的归位,限位开关跳闸时的急停,带减速的即时中止,缓动轮模式)以及 – 除了弧例程 – 一个全新的并且希望完全更快的规划器。把它拉回上游会很痛苦,但现在还不是解决这个问题的时候。

除了我努力通过加速管理获得弧之外,我完全同意 atmega 应该主要运行实时代码,并且将来应该获得像 EMC2 这样的前端,它可以进行预处理、GUI 和其他东西。在 EMC2 中直接集成 grbl 或茶杯之类的东西可能是不可能的,因为它的整个架构(它非常通用,并且为直流电机的反馈控制带来了巨大的开销)。

现在我做了弧线,因为我想要某种“手动”数控铣床,以获得更好的铣削和 gcode 感觉。

停止然后停止(重置)? #26

我为 tinyG 项目实现了一个受控的 jerk 加速解决方案——它是开源的,可以在https://github.com/synthetos/TinyG找到。Simen 和我多次讨论过这个问题 – 混动方程中的数学与 Arduino ATmetas 不兼容。TinyG 运行 Xmega 芯片。回顾重新计划是 16 步 – 再次用于内存空间。我一直在研究最佳转弯背后的物理原理,并将在我有结果展示时发布。

停止然后停止(重置)? #26

嗨奥尔登。您能否详细说明数学与 Arduino ATmegas 不兼容的含义?

我也一直在研究最佳进给率的物理特性。进给率/加速度问题是高度非线性和路径相关的,通常需要一种受约束的非线性优化方法来获得真正的解决方案,而 Arduino 无法在板上实时完成。我在文献中看到了其他算法,它们比 Simen 的方法更强大,但仍然无法在 Arduino 实时上完成。虽然,如果你做出一些假设,可能有一种比 Simen 现在更简单、更有效的方法,但我还没有找到一个像样的解决方案。

停止然后停止(重置)? #26
贡献者

jgeisler0303 评论 2011 年 8 月 22 日

步进电机是否存在无限加加速度的问题?加加速度通常是柔性结构的问题,它会引起振荡。grbl 中的“jerk”是允许在线路接头处发生的速度的即时变化。所以它更像是曲率诱导加速度的离散版本。grbl 中的规划器已经非常适合其用途(步进和螺纹驱动的铣削轴)。恕我直言,任何更复杂的东西都应该包括圆角。
BTW Alden,我开始阅读 tinyG 代码。非常令人印象深刻的工作!可能有一个或另一个功能可以移植到 grbl。您对规划器的内部工作有更多说明吗?

停止然后停止(重置)? #26

嗨 Chamnit 和 J – 我对数学的评论只是小 Arduino 上没有足够的周期来使算法公正。您有 16 个 MIPS 和 8 位可供使用。xmega 在 32 MIPS 时稍快一些,但我正在寻找更多周期。你几乎回答了第二段中的数学问题。

也就是说,xmega 能够进行一些相当复杂的数学运算,但我必须注意周期预算。GCC -Os 是一个很棒的东西。TinyG 规划器使用 3 阶方程实时求解 jerk 方程。在这种情况下,加加速度是速度的瞬时变化量,它实际上只是使运动更平稳,因为机器的撞击更少。

我现在正在转弯(切向混动)。我的目标与 Simen 有所不同,或者我只是在 grbl 中使用启发式并完成。当旋转轴的速度、加速度和加加速度特性与线性轴完全不同时,就会出现问题。还有一些机器(例如 makerbot)有 X 和 Y 的皮带,以及 Z 的螺丝——同样的问题。所以你真的希望方程是轴感知的,并由单个移动的单位向量驱动。我一直使用的模型源自运动的加加速度方程,并合成了一个“加加速度过渡区域”,在该区域中管理切向加加速度。这为拐角样条曲线铺平了道路——因为它真正的作用是将过渡区域的大小增加到样条曲线的直径。这稍后会出现。首先,我只需要让它工作。一旦我让转换正常工作,我将更新 github。此外,代码中将有更多关于它如何工作的注释。

至于Simen的代码更简单,更高效……?与 Simen 所做的盆景工作相比,我感觉自己就像一个带电锯的伐木工。我怀疑我能否让这一切在这么小的空间内运行。几年前我做了类似的事情,并在 5 MIPS pic(汇编中)上编写了 192 个 PWM LED 控制通道和模式生成语言。我准备让编译器做一些工作。

顺便说一句 – 我们的 TinyG 的第一次实际生产运行已经完成!制作了24块板。我们将建造更多。

停止然后停止(重置)? #26

Alden-我同意你的观点,解决这个问题的一种方法是使用更快的处理器,但我认为 grbl 的主要吸引力在于它位于一个不吓人的平台 Arduino 上,它可以将 CNC 介绍给很多新人。我刚刚在我的博客上发布了一些内容,你已经知道了。( http://onehossshay.wordpress.com ) 基本上,我完全赞成在 Arduino 的限制范围内使 grbl 尽可能好。创建一个易于理解且可靠的代码库供人们使用,可以真正放开人们对 CNC/机器人可以做什么的想象。

我完全同意您对 Simen 高效编码的看法。看到这么多对细节的关注真是太棒了。尝试提出一种更紧凑、更高效的新算法非常困难,但我仍然会尝试。:) 而且,很高兴听到 TinyG 正在生产中!我说,制造商的权力。

J-我喜欢您通过删除每个线段的 sin() 和 cos() 计算来简化弧函数的计算方法。您是否遇到过任何复合错误问题?特别是对于大圈子?

停止然后停止(重置)? #26
贡献者

jgeisler0303 评论 2011 年 8 月 22 日

嗨,正如我前几天刚刚了解到 atmega 上的 double = float 一样,我在我的 pc-test 代码中找到/替换了它。运行以下测试:全圆(不应该在 gcode 中完成,但无论如何都可以)100mm 半径出来 x:0.014664,y:0.099866 离开起点。半径变化的幅度相同。这远低于我工厂的精度。对于四分之一圆弧,我会说 400 毫米半径应该没问题。
@chamnit: 你似乎对源代码很熟悉。也许你可以看看我的规划器修改。我非常感谢一些反馈,因为我的测试能力目前非常有限。

停止然后停止(重置)? #26

我完全同意您的观点,即 Arduino 的可访问性以及向尽可能广泛的受众介绍 CNC 和机器人技术的价值。这就是我们构建 grblshield 的原因 – 让它尽可能简单。(除非我们卖出 100,000 个,否则我们不会辞掉日常工作!)。

TinyG 是对其他东西的开源探索。TinyG 的使命在什么是 TinyG 和为什么 ( https://www.synthetos.com/blog/what-is-tinyg-and-why/ ) 中阐述。我们正在寻求一种可联网的综合解决方案,我们可以将每个轴的成本降低到可以忽略不计的水平。将六足位移台想象为从同一命令流馈送的 2 个联网板。生产就是要达到我可以完成的批量。我现在让他们在弗吉尼亚手工组装,但我过去曾在塞尔维亚使用过组装厂——但这仅适用于 250 多个板。

停止然后停止(重置)? #26

jgeisler0303:对不起!我在尝试为 grbl 编写 Python 预处理器脚本时有点心烦意乱,但我肯定会在本周末的某个时候看看你的规划器。

jjg:这是一个适合您的 grbl 预处理器。我基本上采用了 Simen 的代码并转换了逻辑以跟踪正在发生的事情,然后将它遇到的任何 G02/03 弧线转换为线性段。如果需要,它还会删除所有额外的字符、注释和不受支持的命令。不要对输出的 g 代码文件变得巨大感到惊讶,尤其是在有很多弧的情况下。

但是……它是测试版。有一些已知的问题并且仍在解决它们,但是对于大多数事情来说它应该可以正常工作。我在我的机器上测试它没有任何问题,只在英寸模式下运行。请让我知道这对你有没有用。

#!/usr/bin/env python
"""\
G-code preprocessor for grbl
- Converts G02/03 arcs to G01 linear interpolations
- Removes comments, block delete characters, and line numbers
- Removes spaces and capitalizes commands
- Minor input error checking
- OPTIONAL: Remove unsupported grbl G and M commands

TODO: 
- More robust error checking
- Improve interface to command line options
- Improve g-code parsing to NIST standards
- Fix problem with inverse feed rates
- Positioning updates may not be correct on grbl. Need to check.

Version: 20100825
"""
import re
from math import *
from copy import *

# -= SETTINGS =-
filein = 'test.gcode'   # Input file name
fileout = 'grbl.gcode'  # Output file name
ndigits_in = 4 # inch significant digits after '.'
ndigits_mm = 2 # mm significant digits after '.'
mm_per_arc_segment = 0.1 # mm per arc segment      
inch2mm = 25.4 # inch to mm conversion scalar
verbose = False  # Verbose flag to show all progress
remove_unsupported = True   # Removal flag for all unsupported statements

# Initialize parser state
gc = { 'current_xyz' : [0,0,0], 
       'feed_rate' : 0,         # F0
       'motion_mode' : 'SEEK',  # G00
       'plane_axis' : [0,1,2],  # G17
       'inches_mode' : False,   # G21
       'inverse_feedrate_mode' : False, # G94
       'absolute_mode' : True}  # G90

def unit_conv(val) : # Converts value to mm
    if gc['inches_mode'] : val *= inch2mm
    return(val)

def fout_conv(val) : # Returns converted value as rounded string for output file.
    if gc['inches_mode'] : return( str(round(val/inch2mm,ndigits_in)) )
    else : return( str(round(val,ndigits_mm)) )

# Open g-code file
fin = open(filein,'r');
fout = open(fileout,'w');

# Iterate through g-code file
l_count = 0
for line in fin:
    l_count += 1 # Iterate line counter

    # Strip comments/spaces/tabs/new line and capitalize. Comment MSG not supported.
    block = re.sub('\s|\(.*?\)','',line).upper() 
    block = re.sub('\\\\','',block) # Strip \ block delete character
    block = re.sub('%','',block) # Strip % program start/stop character

    if len(block) == 0 :  # Ignore empty blocks

        print "Skipping: " + line.strip()

    else :  # Process valid g-code clean block. Assumes no block delete characters or comments

        g_cmd = re.findall(r'[^0-9\.\-]+',block) # Extract block command characters
        g_num = re.findall(r'[0-9\.\-]+',block) # Extract block numbers

        # G-code block error checks
        # if len(g_cmd) != len(g_num) : print block; raise Exception('Invalid block. Unbalanced word and values.')
        if 'N' in g_cmd :
            if g_cmd[0]!='N': raise Exception('Line number must be first command in line.')
            if g_cmd.count('N') > 1: raise Exception('More than one line number in block.')
            g_cmd = g_cmd[1:]  # Remove line number word
            g_num = g_num[1:]
        # Block item repeat checks? (0<=n'M'<5, G/M modal groups)

        # Initialize block state
        blk = { 'next_action' : 'DEFAULT',
                'absolute_override' : False,
                'target_xyz' : deepcopy(gc['current_xyz']),
                'offset_ijk' : [0,0,0],
                'radius_mode' : False, 
                'unsupported': [] }

        # Pass 1
        for cmd,num in zip(g_cmd,g_num) :
            fnum = float(num)
            inum = int(fnum)
            if cmd is 'G' :
                if   inum is 0 : gc['motion_mode'] = 'SEEK'
                elif inum is 1 : gc['motion_mode'] = 'LINEAR'
                elif inum is 2 : gc['motion_mode'] = 'CW_ARC'
                elif inum is 3 : gc['motion_mode'] = 'CCW_ARC'
                elif inum is 4 : blk['next_action'] = 'DWELL'
                elif inum is 17 : gc['plane_axis'] = [0,1,2]    # Select XY Plane
                elif inum is 18 : gc['plane_axis'] = [0,2,1]    # Select XZ Plane
                elif inum is 19 : gc['plane_axis'] = [1,2,0]    # Select YZ Plane
                elif inum is 20 : gc['inches_mode'] = True      
                elif inum is 21 : gc['inches_mode'] = False
                elif inum in [28,30] : blk['next_action'] = 'GO_HOME'
                elif inum is 53 : blk['absolute_override'] = True
                elif inum is 80 : gc['motion_mode'] = 'MOTION_CANCEL'
                elif inum is 90 : gc['absolute_mode'] = True
                elif inum is 91 : gc['absolute_mode'] = False
                elif inum is 92 : blk['next_action'] = 'SET_OFFSET'
                elif inum is 93 : gc['inverse_feedrate_mode'] = True
                elif inum is 94 : gc['inverse_feedrate_mode'] = False
                else : 
                    print 'Unsupported command ' + cmd + num + ' on line ' + str(l_count) 
                    if remove_unsupported : blk['unsupported'].append(zip(g_cmd,g_num).index((cmd,num)))
            elif cmd is 'M' :
                if   inum in [0,1] : pass   # Program Pause
                elif inum in [2,30,60] : pass   # Program Completed
                elif inum is 3 : pass   # Spindle Direction 1
                elif inum is 4 : pass   # Spindle Direction -1
                elif inum is 5 : pass   # Spindle Direction 0
                else : 
                    print 'Unsupported command ' + cmd + num + ' on line ' + str(l_count) 
                    if remove_unsupported : blk['unsupported'].append(zip(g_cmd,g_num).index((cmd,num)))
            elif cmd is 'T' : pass      # Tool Number

        # Pass 2
        for cmd,num in zip(g_cmd,g_num) :
            fnum = float(num)         
            if   cmd is 'F' : gc['feed_rate'] = unit_conv(fnum)   # Feed Rate
            elif cmd in ['I','J','K'] : blk['offset_ijk'][ord(cmd)-ord('I')] = unit_conv(fnum) # Arc Center Offset
            elif cmd is 'P' : p = fnum  # Misc value parameter
            elif cmd is 'R' : r = unit_conv(fnum); blk['radius_mode'] = True    # Arc Radius Mode
            elif cmd is 'S' : pass      # Spindle Speed
            elif cmd in ['X','Y','Z'] : # Target Coordinates
                if (gc['absolute_mode'] | blk['absolute_override']) :
                    blk['target_xyz'][ord(cmd)-ord('X')] = unit_conv(fnum)
                else :
                    blk['target_xyz'][ord(cmd)-ord('X')] += unit_conv(fnum)

        # Execute actions
        if   blk['next_action'] is 'GO_HOME' : 
            gc['current_xyz'] = deepcopy(blk['target_xyz']) # Update position      
        elif blk['next_action'] is 'SET_OFFSET' : 
            pass 
        elif blk['next_action'] is 'DWELL' :
            if p < 0 : raise Exception('Dwell time negative.')
        else : # 'DEFAULT'
            if gc['motion_mode'] is 'SEEK' : 
                gc['current_xyz'] = deepcopy(blk['target_xyz']) # Update position
            elif gc['motion_mode'] is 'LINEAR' :
                gc['current_xyz'] = deepcopy(blk['target_xyz']) # Update position
            elif gc['motion_mode'] in ['CW_ARC','CCW_ARC'] :
                axis = gc['plane_axis']

                # Convert radius mode to ijk mode
                if blk['radius_mode'] :
                    x = blk['target_xyz'][axis[0]]-gc['current_xyz'][axis[0]]
                    y = blk['target_xyz'][axis[1]]-gc['current_xyz'][axis[1]]
                    if not (x==0 and y==0) : raise Exception('Same target and current XYZ not allowed in arc radius mode.') 
                    h_x2_div_d = -sqrt(4 * r*r - x*x - y*y)/hypot(x,y)
                    if isnan(h_x2_div_d) : raise Exception('Floating point error in arc conversion')
                    if gc['motion_mode'] is 'CCW_ARC' : h_x2_div_d = -h_x2_div_d
                    if r < 0 : h_x2_div_d = -h_x2_div_d
                    blk['offset_ijk'][axis[0]] = (x-(y*h_x2_div_d))/2;
                    blk['offset_ijk'][axis[1]] = (y+(x*h_x2_div_d))/2;

                # Compute arc center, radius, theta, and depth parameters
                theta_start = atan2(-blk['offset_ijk'][axis[0]], -blk['offset_ijk'][axis[1]])
                theta_end = atan2(blk['target_xyz'][axis[0]] - blk['offset_ijk'][axis[0]] - gc['current_xyz'][axis[0]], \
                                  blk['target_xyz'][axis[1]] - blk['offset_ijk'][axis[1]] - gc['current_xyz'][axis[1]])
                if theta_end < theta_start : theta_end += 2*pi
                radius = hypot(blk['offset_ijk'][axis[0]], blk['offset_ijk'][axis[1]])
                depth = blk['target_xyz'][axis[2]]-gc['current_xyz'][axis[2]]
                center_x = gc['current_xyz'][axis[0]]-sin(theta_start)*radius
                center_y = gc['current_xyz'][axis[1]]-cos(theta_start)*radius

                # Compute arc incremental linear segment parameters
                angular_travel = theta_end-theta_start
                if gc['motion_mode'] is 'CCW_ARC' : angular_travel = angular_travel-2*pi
                millimeters_of_travel = hypot(angular_travel*radius, fabs(depth))
                if millimeters_of_travel is 0 : raise Exception('G02/03 arc travel is zero')
                segments = int(round(millimeters_of_travel/mm_per_arc_segment))
                if segments is 0 : raise Exception('G02/03 zero length arc segment')
#        ???    # if gc['inverse_feedrate_mode'] : gc['feed_rate'] *= segments
                theta_per_segment = angular_travel/segments
                depth_per_segment = depth/segments

                # Generate arc linear segments
                if verbose: print 'Converting: '+ block + ' : ' + str(l_count)
                fout.write('G01F'+fout_conv(gc['feed_rate']))
                if not gc['absolute_mode'] : fout.write('G90')    
                arc_target = [0,0,0]
                for i in range(1,segments+1) :
                    if i < segments : 
                        arc_target[axis[0]] = center_x + radius * sin(theta_start + i*theta_per_segment)
                        arc_target[axis[1]] = center_y + radius * cos(theta_start + i*theta_per_segment)
                        arc_target[axis[2]] = gc['current_xyz'][axis[2]] + i*depth_per_segment
                    else : 
                        arc_target = deepcopy(blk['target_xyz']) # Last segment at target_xyz
                    # Write only changed variables. 
                    if arc_target[0] != gc['current_xyz'][0] : fout.write('X'+fout_conv(arc_target[0]))
                    if arc_target[1] != gc['current_xyz'][1] : fout.write('Y'+fout_conv(arc_target[1]))
                    if arc_target[2] != gc['current_xyz'][2] : fout.write('Z'+fout_conv(arc_target[2]))
                    fout.write('\n')            
                    gc['current_xyz'] = deepcopy(arc_target) # Update position
                if not gc['absolute_mode'] : fout.write('G91\n')    

        # Rebuild original gcode block sans line numbers, extra characters, and unsupported commands
        if gc['motion_mode'] not in ['CW_ARC','CCW_ARC'] :
            if remove_unsupported and len(blk['unsupported']) : 
                for i in blk['unsupported'][::-1] : del g_cmd[i]; del g_num[i]
            out_block = "".join([i+j for (i,j) in zip(g_cmd,g_num)]) 
            if len(out_block) : 
                if verbose : print "Writing: " + out_block + ' : ' + str(l_count)
                fout.write(out_block + '\n')

print 'Done!'

# Close files
fin.close()
fout.close()
停止然后停止(重置)? #26
作者

jjg 评论 2011 年 8 月 26 日

多么巧合 Chamnit,我正在做我明天制造的激光器的演示。今天下午我将对此进行测试,看看它是否有效。谢谢!

停止然后停止(重置)? #26

jjg:考试怎么样?我在加速规划器尝试规划小的线性插值时遇到了一些问题,当尝试一直加速和减速时,它们会发出咔哒声。除此之外,它似乎改善了我的运行方式,尤其是从弧线中出来。

jgeisler:今天花了一些时间来看看你的planner。我真的很喜欢你如何通过将计算返回到一个已知的好点来阻止规划器过度计算。据我所知,grbl 目前计划每个新传入块的整个缓冲区。这与我在阅读的路径优化文献中看到的方法相同。这似乎是正确的方法,应该会极大地提高规划器的速度。

另外,我注意到您最初计算了最大连接速度,但是当连接速度发生变化时,不要在规划器中重新计算它。这是有原因的还是我看错了?

停止然后停止(重置)? #26

很高兴您发现了不连续性错误。我一直在花时间尝试优化梯形段构造。2 段案例(仅头部和尾部)是需要逐次逼近的熊。我可能错过了一些非常明显和优雅的方式来做到这一点。

您描述的转弯算法在低速到中速时对我来说效果很好,但在高速时我会遇到问题。禅宗咕噜咕噜地转了 90 度。你运行的速度是多少,在什么样的机器上运行?我在 Zen 上以 350 毫米/分钟的速度做得很好,但在 600 毫米/分钟或以上时我做得不太好。我不确定 Zen 能不能做到——所以我可能只是达到了机器的极限。本周末我将尝试让它在 Lumenlabs MicRo3 上运行,它具有更高的最高速度,甚至可能是 Probotix V90,它是 3 中最快的。我的问题可能只是我没有参数调得很好。

我正在探索扩展算法以管理受控的混蛋 – 而不仅仅是加速。应该可以通过知道路径在过渡区域中花费的时间来求解加加速度,过渡区域是由圆的切线定义的弧除以通过它的速度。我通过计算“phi”来做到这一点,“phi”是由切线定义的弧所对的角度。我早期的 excel 成绩令人鼓舞;时间从零下降到 45 或 60 度线非常缓慢(相对恒定),然后随着角度变得更锐利而越来越快地下降。这与观察到在较低角度下速度降低是可以的,但可能需要在更锐角处进行更多校正。下降的时间是 J=a/t 所需的时间。

希望 NM 的天气很好。很高兴知道您所在的时区。我认为 Jens 在德国,但我不确定。

停止然后停止(重置)? #26

我正在通过 Pololu 步进驱动器运行带有 DIY CNC 升级的 Sherline 5400 铣床。它发布在我的博客上。我的搜索速率约为 28ipm (~650 mm/m)。我的测试程序的进给速度大约是那个速度的一半。不确定您所说的 grunches(跳过的步骤?)是什么意思,但这可能是机器的限制。如果您减小 delta(路径宽度)参数,这应该将所有结点速度缩放到相对于您的加速度参数更低的程度。您只需调整这两个参数即可从您的机器中获得最佳响应。

停止然后停止(重置)? #26

咕噜声只是机器在跳过步骤时发出的描述性噪音。我可能将机器运行得太快,超出了它自身的限制——进给速度为 600 毫米/分钟。这只是我不耐烦。但是,在 90 度或更大的拐角处,我仍然可以看到明显的抖动。这就是促使进行混蛋探索的原因。我已经开发了一些早期的算法,这些算法着眼于每个轴的 jerk 贡献(因为 jerk 必须被视为一个向量)并按比例缩小速度以适应限制轴。这在尖角上效果很好。

停止然后停止(重置)? #26
贡献者

jgeisler0303 评论 2011 年 9 月 4 日

Chamnit:是的,浮点向量数学在我的叉子(边缘)中。这个想法是这样的:对于短线段,尤其是半径较大的线段,量化的效果是某些线具有完全相同的单位矢量,然后(突然)发生变化,通常与前面的变化仅相差一步。因此,量化半径不断从 inf 变化到 finit,这是一个巨大的差异!使用浮点数学应该导致弧的每个交汇点的半径大致相同(因此交汇点速度一致)。
是的,我来自德国(奥尔登:你怎么知道的?)
这些天我真的很忙,要为我的新家地下室的墙壁做防水。那就是挖一个 2m 深的沟渠,然后涂上一层厚厚的黏黏的沥青。我嫉妒你真的在磨东西。我猜我得等 6 个月,但我会为自己拥有一个完整的地下室房间 :-) 我期待着关注这个帖子!

停止然后停止(重置)? #26

终于完成并测试了!进入和退出因素导致了我看到的很多错误。我花了比我想承认的时间更长的时间来修复它们。我已将所有内容更改为路口入口速度,以 (1) 消除不必要的分隔 (2) 并使事情更清晰。只有在转换为步进率信息时才会计算进入和退出因素。就像你有 Jens 一样。现在它工作得很好。代码发布在我的边缘叉上。伙计们让我知道你的想法。

Alden:现在我想起来,对于 Zen 上的那些小步进器来说,600 毫米/分钟听起来相当快。NEMA 17 对吗?步进扭矩在更快的速度下会显着下降,而 grbl 并没有考虑到它的恒定加速度。对于未来的模组,我想可以引入一个缩放参数来解释电机扭矩的降低。我想我记得看到 EMC2 也做了类似的事情。

jjg:仍然想知道它是如何与剧本搭配的。如果您在我的 fork 中使用更新的规划器,它应该可以解决所有问题!:)

停止然后停止(重置)? #26

很好。当我不编码时,我会参加一些社交庆祝活动。迫不及待想试试这个。Jens:这是一个幸运的猜测。

停止然后停止(重置)? #26

我得到了运行 Probotix V90 的代码。使用 100,000 的加速度值和 0.01 的增量,它以 600 毫米/分钟的速度处理复杂的绘制(braid.gcode)就好了。我继续加快速度。我认为您对 Zen 上的小 NEMA17 因扭矩下降而以这些速度发出的声音是正确的。

停止然后停止(重置)? #26

很高兴听到它运作良好!仅供参考,我刚刚发布了今天早上发现的错误修复。在某些情况下,前瞻性规划器的工作并不完全正确。结果发现反向规划器正在重置初始速度,并且在加速进入短线段时会导致意外的速度跳跃。现在应该工作得更好。

停止然后停止(重置)? #26

是的,它在 lumenlabs MicRo v3 上也运行良好。所以我的结论是,当 Zen 接近它的运行极限时,它真的很挑剔。这在某种程度上很好,因为它很好地测试了你能把信封推到多远。我迫不及待地想让 Grizzly 0619 磨机改装,这样我就可以进行一些严肃的加工了。(不,我不只是收集机床,我已经获得了所有这些作为项目的测试平台)。你看过 John Knoll 使用 grblshield 制作的关于荣富转换的视频吗?http://www.youtube.com/watch?v=mHmDhi2u2BE 真的很棒。

停止然后停止(重置)? #26

伟大的!我一直致力于规划器优化,并将规划器的速度显着提高了一个数量级。主要是通过删除或限制所有昂贵和不必要的重复计算(sqrts、trig、divides、重复梯形计算)。如果我启用对当前 arc 实现的规划(有很多 trig 计算),它现在适用于大多数情况,以前它会完全窒息。昨晚,我有机会通过矢量变换实现和测试 Jens 的弧方法。它完全没有问题地飞过弧线。今晚,我将对代码进行更多测试并清理一下。它应该在今晚或明天晚些时候发布。总体而言,这些更改稍微增加了代码的大小,但效率要高得多。

Jens:我研究了你的向量变换方法的错误传播。在 MATLAB 脚本中,我比较了变换圆的 norm () 与已知的半径长度。对于半径为 1m 的圆和 0.1mm 的线段,误差小于 1e-6mm。这是使用 MATLAB 的双打。看起来这种方法的错误传播不应该有任何问题。非常好的工作。虽然,您确实看到的错误可能归因于从半径模式转换为偏移模式时的数值问题,或者 Arduino 可能无法足够准确地计算 sin() 和 cos()。没有把握。有任何想法吗?

更新:啊。Arduino 只进行单精度浮点计算。

停止然后停止(重置)? #26

我也一直在做一些代码工作。我一直在试验角落规划器的子功能,以允许将增量值设置为每轴增量的组合。这样做的原因是支持具有不同特性的轴的机器。我之前已经提到过这种情况——比如参数不同于 X 和 Y 的 Z,并且支持 ABC 轴。例如,Probotix 有 5 节距 X 和 Y(每转 0.200 英寸),以及 12 节距 Z。另一个例子 – 如果你为 A 使用转台,那么它的 V、A 和 Jerk 特性与 X 和 Y 完全不同.

该函数查看单位向量,然后根据每个轴对移动的贡献计算聚合增量。如果所有增量都相同,则移动的几何形状无效。如果 Z(例如)需要更紧密的 delta(更慢的转弯),那么具有 Z 分量的移动将被 Z 对移动的贡献程度“降级”。所有这些都是为了找到可以运行这些机器的最大速度。

停止然后停止(重置)? #26
贡献者

jgeisler0303 评论 2011 年 9 月 7 日

嗨 Chamnit,对于我刚才在这里陈述的向量变换圆的错误值,我实际上使用了包裹在 s 函数中的真实 grbl 代码的相关部分(code= strrep(code, ‘double’, ‘float’) )。但我认为有一个错字。错误是 x:0.014664,y:0.0_0_99866@100mm半径整圆(不是 y:0.099866)。给出大约 1/100 毫米的标准。不知道为什么会这样。我会猜测 double 和 float 之间的差异很可能是标准误差指数的一半:1e-3 而不是 1e-6——不过这仍然没有问题。我真的很期待尝试您的代码。

停止然后停止(重置)? #26

好的。代码在我的叉子上。现在启用了完整的规划器优化和弧支持。为了提高速度,我使用 Jens 的 arc 方法以及附加的误差校正方案和小角度近似来用于变换矩阵。在我的机器上测试过,效果很好。起初,我确实遇到了没有多大意义的打嗝问题。我认为它们与内存不足有关,但我不能 100% 确定。在我进行了一些内存清理并更正了一些函数变量类型以传递和接收正确的变量类型后,这些问题得到了解决。让我知道它是否适用于你们两个的弧线。

奥尔登:同意。每个轴的加速度分离对于 CNC 路由器尤其有用。目前,单加速模型运行良好,我不确定它能否处理太多其他计算,尤其是现在支持 arc 的情况下。我想你可以根据结向心加速度的方向来计算最大加速度,但这会随着方向的变化……嗯。有趣的问题。

延斯:你是对的。我把双打误认为是真正的双精度(我知道你之前说过,但我想我的头骨很厚)。在 MATLAB 中,我查看了您实现的单精度变换矩阵的累积误差。我按照您所做的顺序收到了路径错误。所以这是有道理的。如您所说,在大多数情况下,错误将小于 CNC 机器的顺序,但并非适用于所有情况和所有机器,例如大型 CNC 路由器。所以,我最终创建了一个周期性路径校正函数。现在保证路径误差不超过0.01mm。路径校正使用相同的变换矩阵方法,因此我不必使用 atan2() 计算初始起始角度。

停止然后停止(重置)? #26

非常了不起的工作,你们。我已经开始阅读增强功能。回到工作区后,我会尽快将它放到 Arduino 和 grblshield 上,并进行一些测试。

停止然后停止(重置)? #26

奥尔登:测试进行得如何?仍在努力改进规划器。我在一些假设上相当保守。我必须在 MATLAB 中编写一个 grbl 模拟器,才能真正直观地了解规划器的行为,然后再在其中实现更多的计算效率逻辑。

停止然后停止(重置)? #26

我今晚做了一些测试。对于简单的手动输入动作来说一切正常,但我无法让它运行 braid_2d 的“转弯酷刑测试”。我已经使用 gcode 目录更新了 github synthetos / tinyg,我在其中放置了一些我一直用来测试的文件。尝试运行 braid_300mm(300mm/min 版本)。而不是循环的 XY 运动,我得到的运动主要在 Y 维度,X 很少 – 然后 Y 崩溃,所以我将其关闭。我刚刚使用股票 simen edge 0.7 运行了相同的完全相同的工具链,并且它在该文件上工作(正如我一直看到的那样)。顺便说一句,我正在使用 gctrl 处理草图来流式传输文件 – github damellis / gctrl。如果您想尝试一下,我应该指出,由于某种原因,我无法让 JOptionPane Swing 对话框工作以选择串行端口,所以我恢复到 github 上没有该功能的 v2 提交。我是Processing的菜鸟,所以也许我缺少一些明显的东西。

关于发生了什么的任何想法?

PS 有没有办法以低于 2100 美元的价格获得 Matlab?哎呀!我不能去那里。但我不是学生,也不是教育机构,也不是政府,所以我想按照他们的逻辑,这使我成为一名专业人士——这是唯一的选择。职业黑客?没有类别。个人许可证的报价为 2100 美元。我会坚持使用 Excel 和 Wolfram Alpha。

停止然后停止(重置)? #26

那很奇怪。我今天早上上班前刚刚运行了 braid_300mm.gcode,它运行得很好。我正在使用 Python 脚本发送 grbl gcode 块。我确实注意到我的eeprom突然改变了我并开始表现不稳定。我不确定我是否对代码进行了正确的更改来重置它们。但是一旦我手动重新编写它们,从那以后就没有同样的问题了。这可能是你得到的奇怪反应。我将进一步研究它,因为我还没有完成规划器代码中的所有更改。

是的,MATLAB 非常昂贵,特别是如果您不是学生。幸运的是我的作品有许可证。我正在努力将我的一般编程转换为带有 SciPy 的 Python,以实现可移植性,并且几乎同样强大和灵活。但我仍然是 MATLAB 中速度更快的编码器。

停止然后停止(重置)? #26

奇怪的。你能把你使用的脚本给我,这样我就可以尽可能地对齐吗?我会在周末重新测试。

停止然后停止(重置)? #26

这是我最近一直在使用的一个。它强制字符进入 Arduino 串行读取缓冲区,因此 grbl 不必等待下一个块的串行发送和响应。您将需要 pyserial 库才能正常工作。在 Mac 上,在终端提示符下键入“sudo easy-install pyserial”。

如果结果证明设置不兼容,请告诉我。就像我之前说的,我不得不重新编写它们,因为它们已经腐败了。我需要研究一下是否只是更改设置版本号会自动重置 eeprom。

#!/usr/bin/env python
"""\
Stream g-code to grbl controller
"""

import serial
import re
import glob
import time
import sys
# import getopt

device_str = '/dev/tty.usbmodem*'  # Serial port device string. Wildcards OK.
filename = 'grbl.gcode'
RX_BUFFER_SIZE = 128
verbose = True
# TODO: Single block mode
# TODO: Complete command line interface

# Search for serial device and returns name(s).
def scan():
    return glob.glob(device_str)

# Search for and open Arduino port based on search string
portscan = scan()
if len(portscan) != 1 :
    print "No port or multiple ports found:",portscan
    sys.exit()
print "Grbl port found: ",
s = serial.Serial(portscan[0],9600)

# Open g-code file
f = open(filename,'r');

# Wake up grbl
print "Initializing grbl..."
s.write("\r\n\r\n")

# Wait for grbl to initialize and flush startup text in serial input
time.sleep(2)
s.flushInput()

# Stream g-code to grbl
print "Streaming [",filename,"] to grbl..."
l_count = 0
c_line = []
for line in f:
    l_count += 1 # Iterate line counter
#     l_block = re.sub('\s|\(.*?\)','',line).upper() # Strip comments/spaces/new line and capitalize
    l_block = line.strip()
    c_line.append(len(l_block))
    grbl_out = '' 
    while sum(c_line) > RX_BUFFER_SIZE | s.inWaiting() :
        grbl_out += s.readline().strip() # Wait for grbl response
        del c_line[0]
    if verbose: print "SND: " + l_block,
    s.write(l_block + '\n') # Send block to grbl
    if verbose : print "BUF:",str(sum(c_line)),"LN:", str(l_count),"REC:",grbl_out

# Wait for user input after streaming is completed
print "G-code streaming finished!\n"
print "WARNING: Wait until grbl completes buffered g-code blocks before exiting."
raw_input("  Press <Enter> to exit and disable grbl.") 

# Close file and serial port
f.close()
s.close()
停止然后停止(重置)? #26

桑尼,今天早上我有机会在我的设置上运行你的脚本(Arduino Duemilenova,grblshield,Zen Toolworks 7×12)。我使用了您之前选择的编织 300 毫米文件。我认为规划器中有些东西仍然需要工作。您是否将它与股票 grbl edge 0.7 并排运行?我这样做并得到了不同的结果。这可能是我的设置中的一个错误,但最好验证这两个跟踪相同的确切路径。

停止然后停止(重置)? #26

诡异的。我检查了 Simen 的股票 0.7b grbl。它的工作原理完全一样,因为它在逻辑上是相同的,除了 G02/03 弧、最大连接速度计算和一些额外的规划器逻辑。我刚在打字时注意到您正在使用 Duemilenova。我认为这是问题所在。据我了解,Simen 做了很多事情来尝试将 grbl 与加速计划安装到 Atmega 168 上。我现在所做的更改可能不适合,明显内存不足(1k 与 2k),或者你是从严重截断的缓冲区大小(16 个中的 5 个块)中看到一些问题。我使用的是 Arduino Uno,并且我的所有测试都基于它。抱歉,我没有 Arduino Duemilenova。

在我的 matlab grbl 模拟器中,您将希望拥有尽可能大的缓冲区大小,因为这将允许规划器沿着缓冲区中的路径长度规划更高的整体速度。换句话说,由于编织代码有很多快速变化的短块占用了缓冲区,因此没有足够的计划长度来从缓冲区结束时的零速度加速到开始时的当前运行速度。我敢打赌,Simen 的 max_jerk 隐藏了 Atmega 168 构建中的一些问题。因此,我不建议在其中一个上使用我的代码并且只使用 328p 或更高版本,至少目前是这样。

此外,我最近重新编写了一些规划器代码,以在一些极端和时间紧迫的情况下提高速度。它们应该在我测试和验证代码后不久发布在这里。大概本周晚些时候。

停止然后停止(重置)? #26

我将在 Uno 上运行它。这可能是问题所在。我会寻找你的新代码,并在可用时从你的 fork 中提取。

停止然后停止(重置)? #26

所以我现在在 Uno 上运行它,效果很好。Duemilenova 实际上是 Atmega 328p,所以我不确定这里有什么。我会继续调查。

停止然后停止(重置)? #26

太棒了,奥尔登!我非常感谢您花时间测试代码。你是对的。我以为所有的 Duemilenove 都是 Atmega168 的。奇怪的是它适用于 Uno 而不是 Duemilenove。据我所知,唯一的区别是USB接口。如果你发现了什么,请告诉我,我可以调查一下。

刚刚在我的叉子上发布了规划器改进。主要的变化是删除了非常昂贵的模运算符,考虑到它被调用了多少次,节省了大约 192 字节的运行时内存(将缓冲区大小 b/c 增加到 18,可以到 20)并改进计划者逻辑。这些更改似乎使 grbl 运行更顺畅,但这可能只是在我的脑海中。仅供参考,此更新将重置您的 EEPROM 设置,因此请不要忘记事先写下所有设置(如果您还没有的话)。

在此之后,我认为当前系统的改进空间不大,因为弧已经完全启用了规划器,并且规划器正在快速有效地工作。所以我可能会开始关注其他一些功能,比如状态报告和 e-stop。

停止然后停止(重置)? #26
作者

jjg 评论 2011 年 9 月 14 日

大家好消息!

今天早上,我能够使用来自 chamnit 叉子的代码成功地切出一个圆圈。我在使用 ruby​​ 脚本(stream.rb)让它工作时遇到了一些麻烦,但是当我逐行“喂”gcode 时,它​​工作得很好!

我将做一些更复杂的测试来验证,但我需要弄清楚为什么 ruby​​ 脚本会给我带来麻烦,或者首先找到另一种方式来流式传输 gcode(我写了一个小 OSX 应用程序来发送代码一段时间前一次一行,但我似乎放错了位置……)。一旦我把它理顺,我会看看我是否可以切割一些更复杂的形状。

谢谢大家为此所做的工作,我迫不及待地想开始用我的激光制作更多东西!

停止然后停止(重置)? #26

听到这个消息我很高兴!您在使用 ruby​​ 脚本时遇到了什么样的麻烦?在我的一些测试中,我发现串行接口现在是瓶颈,尤其是当你同时有两个弧形运动时。一旦第一个弧完成,grbl 必须发送一个 ok 然后接收下一个块并处理它。滞后会导致缓冲区在启动下一个弧之前清空。

试试我几天前为 Alden 发布的 Python 脚本。如果您没有 Mac,您可能需要对其进行一些修改才能使其正常工作。它强制 128 个字符的 g 代码进入 Arduino 的串行接收缓冲区,并将其保存在那里,以便 grbl 立即访问它,无需等待任何串行握手。该脚本通过跟踪已从其中清空了多少字符来不断发送更多字符,并始终尝试使其保持完整。

停止然后停止(重置)? #26
作者

jjg 评论 2011 年 9 月 15 日

我能够找到我编写的应用程序来一次输入 gcode 一行(或者更确切地说,等到它从 grbl 听到“OK”后再发送下一行)并且使用它能够毫无问题地切割圆圈。我尝试了一些更复杂的 gcode 文件,虽然它们并不完美,但我认为问题与文件有关(运行时两者都产生了一些“错误的数字格式”错误)而不是 grbl 本身。

希望今晚我有时间创建一些新图纸并从头到尾尝试整个过程,并在 gcode 数字格式错误再次出现时对其进行调试。再次感谢您为解决此问题而付出的努力,看到结果非常令人兴奋,现在我可以继续改进我的硬件了 :)

顺便说一句,一旦我清理并调试它,我将发布我的 OSX 流媒体应用程序的代码。与脚本相比,它可能有点矫枉过正,但它提供了一些有助于调试 gcode 文件/脚本的视觉反馈和信息。

停止然后停止(重置)? #26

哇你们真聪明。刚刚完成我的数控机床,担心我的问题不保证你的专业知识,但我走了。我使用 phlatboys 和 Sketchup 生成 Gcode,通过 GCodesender 传递给 m arduino。Phlatboys 似乎仅限于切割 2D 模板。我有 CamBam 试用,但不能让它产生线性插值而不是圆形。(因此我在这个线程上绊倒了)。我的选择是查看不同的 CAD 和 Flow 软件或对 Cambam 进行后处理(我还没有)。您的建议将不胜感激。

停止然后停止(重置)? #26

您可以使用我的 grbl fork,它支持弧线并对 grbl 进行了
许多其他改进,或者使用我
编写的 grbl 预处理器 preGrbl,将弧线转换为线性插值。第
一个选项是最简单的。

2011 年 10 月 6 日上午 6:48,basics0603
reply@reply.github.com
写道:

哇你们真聪明。刚刚完成我的数控机床,担心我的问题不保证你的专业知识,但我走了。我使用 phlatboys 和 Sketchup 生成 Gcode,通过 GCodesender 传递给 m arduino。Phlatboys 似乎仅限于切割 2D 模板。我有 CamBam 试用,但不能让它产生线性插值而不是圆形。(因此我在这个线程上绊倒了)。我的选择是查看不同的 CAD 和 Flow 软件或对 Cambam 进行后处理(我还没有)。您的建议将不胜感激。

直接回复此邮件或在 GitHub 上查看:
https ://github.com/simen/grbl/issues/26#issuecomment-2309338

停止然后停止(重置)? #26
 
添加标题文本添加粗体文本,<Ctrl+b>添加斜体文本,<Ctrl+i>
添加引号,<Ctrl+Shift+.>添加代码,<Ctrl+e>添加链接,<Ctrl+k>
添加项目符号列表,<Ctrl+Shift+8>添加编号列表,<Ctrl+Shift+7>添加任务列表,<Ctrl+Shift+l>
直接提及用户或团队引用问题、拉取请求或讨论

添加已保存的回复

喜欢 (0)

您必须 登录 才能发表评论!