开源改变世界!!

添加 SPI #748

推推 grbl 2年前 (2022-10-30) 132次浏览 0个评论
关闭
J-Dunn 打开了这个问题 on 25 Jun 2015 · 32 条评论
关闭

添加 SPI第748章

J-Dunn 打开了这个问题 on 25 Jun 2015 · 32 条评论

注释

添加 SPI #748

我正在尝试使用通过 SPI 编程的驱动程序芯片添加一些硬件。主要是初始化,但也有错误状态。通常的 step 和 dir 行。

Arduino SPI 库非常简单,因为大部分是由硬件完成的。它主要是将一个字节插入寄存器并等待状态标志,然后读取返回字节。

我需要稍微移动默认引脚以释放 MOSI 和朋友,所以我不会有主轴控制(不需要)并且限制引脚将不得不进入端口 A。

现在我知道 GRBL 已被压缩到最低限度以使其适合 UNO。在它开始出现问题之前,我还有多少空间可以玩?我需要特别注意哪些限制?

谢谢京东。

添加 SPI #748
成员

尚尼特 评论 on 25 Jun 2015

@J-Dunn:您希望有大约 400 字节的可用内存并且不希望超过 31-31.5kB 的总闪存(引导加载程序驻留在 32kB 的最后 0.5kB 中)。或者您可以使用 Mega2560 cpu 映射来获得额外的闪存、内存和引脚。

添加 SPI #748
作者

J-邓恩 评论 on 25 Jun 2015

“二进制草图大小:27,962 字节(最大 32,256 字节)”

非常感谢。所以我还有一些喘息的空间,但不多。我有一个挥之不去的疑问,即草图大小不考虑存储在 pgmspace 中的字符串。你能评论吗?

添加 SPI #748
成员

尚尼特 评论 on 25 Jun 2015

它说明了一切。Pgmspace 是闪存存储的。

添加 SPI #748

我正要构建我的第一个 GRBL 单元,并注意到此线程中有关使用 Mega2560 的评论。当我查看物理 I/O 布局时,我正要订购一个。我打算将 CNC 屏蔽与插入式步进驱动器一起使用,但 Mega2560 完全不同。我猜所涉及的 I/O 线的数量并不多,但值得付出努力吗?

添加 SPI #748
成员

尚尼特 评论 on 25 Jun 2015

@dgoadby:Mega2560 上的 Grbl 不受官方支持,引脚映射与现有屏蔽不兼容(我认为)并且可能存在错误。所以小心行事。

添加 SPI #748

我猜像L6474这样的东西?
我不确定它会如何影响代码大小,但你可以稍微敲一下 spi,它的引脚分配更加灵活,速度不应该是一个大问题,因为你通常只将它用于设置和/或何时有警报,无论如何你必须停止一切

添加 SPI #748

是的,L6474。感谢您的建议,但是…

Arduino 硬件处理所有 SPI 交互。只需写一个寄存器并读回返回字节。手工操作会相当大,基本上是浪费开发时间。它允许使用不同的引脚,但您仍然需要其中的四个。我只需要移动限位开关并放弃一些额外的功能,如主轴速度。

无论如何,这是将整个事情转移到 stm32 的垫脚石。我只是不想一次把所有的球都扔到空中。使用未知的驱动芯片、一个新的 mirco 和一键移植 GRBL 似乎是主要调试头痛的秘诀。

添加 SPI #748

我已经从 Michel_F 的 L6474 库和 SPI lib 中删除了必要的部分,转储了所有 cpp 类。
通过对每个 fn 的令牌调用以确保链接,它出奇的轻。
二进制草图大小:27,962 字节(最大 32,256 字节)
二进制草图大小:28,726 字节(最大 32,256 字节)

这尚未与 GRBL 集成,但作为足迹可行性,它看起来很有希望。

现在我必须解决引脚分配问题。由于 ST 板旨在使用 PWM 进行简单的电机驱动。主要担心的是,虽然所有 dir 引脚都在 portD 上,但其中一个 step 引脚在 portB 上。所以我要么弯曲一些别针,要么弯曲我的 GRBL。

我先试试后者。

// Define step pulse output pins. NOTE: All step bit pins must be on the same port.
这似乎是因为它允许在关键 ISR 中进行一些很好的优化。如果我在拆分端口上,它将基本上将代码加倍。

看起来主要的打击将出现在 ISR(TIMER0_OVF_vect)

ISR(TIMER1_COMPA_vect) 已经加载了一些,所以可能没有 %age 命中。

这里有什么东西会成为真正的杀手并让人想要弯曲硬件吗?

谢谢。

添加 SPI #748

@J-Dunn:不。大多数这些 8 位掩码和寄存器设置每次操作只需要几个周期。如果您只坚持简单的 8 位操作,您可能不会注意到任何区别。我没有将它们分开的主要原因是没有必要,它节省了一些闪存和几个周期。

添加 SPI #748

尝试修改内容时,我发现包含链似乎没有集中式结构。
例如 default.h 具有以下条件,但不包括定义它的 config.h。
#ifdef DEFAULTS_GENERIC
我还期望定义 N_AXIS=2 来做一些与代码中的一些#ifdefs 相关的事情。
我希望构建和两条腿的 GRBL 来解决引脚问题,以测试我到目前为止所拥有的东西。

这种事情会很好,而且相当简单。

添加 SPI #748

@J-Dunn: 是的。这样的事情就好了。

添加 SPI #748

也许至少 defaults.h 应该 #include config.h

添加 SPI #748

由于引脚改组,我需要在端口 C 以及外部用户 i/p 引脚上有限制引脚。

这意味着一些诡计,因为它们具有相同的 ISR。我制作了一个伪 ISR,它是从真正的 ISR 调用的,并且做的事情完全相同。

// if limit sw and Ext input pins are on same port , handle ext pins subroutine
#if  ( LIMIT_INT_vect == EXT_INPUT_INT_vect )

uint8_t  Ext_pin_peudo_ISR() 
{
  // Enter only if any  pin is actively low.
  if ((EXT_INPUT_PIN & EXT_INPUT_MASK) ^ EXT_INPUT_MASK) { 
    if (bit_isfalse(EXT_INPUT_PIN,bit(PIN_RESET))) {
      mc_reset();
    } else if (bit_isfalse(EXT_INPUT_PIN,bit(PIN_FEED_HOLD))) {
      bit_true(sys.execute, EXEC_FEED_HOLD); 
    } else if (bit_isfalse(EXT_INPUT_PIN,bit(PIN_CYCLE_START))) {
      bit_true(sys.execute, EXEC_CYCLE_START);
    } 
  }
  return 1;
}
#else 
uint8_t Ext_pin_peudo_ISR() { return 0; }
#endif
#ifndef ENABLE_SOFTWARE_DEBOUNCE
  ISR(LIMIT_INT_vect) // DEFAULT: Limit pin change interrupt process. 
  {
    // Ignore limit switches if already in an alarm state or in-process of executing an alarm.
    // When in the alarm state, Grbl should have been reset or will force a reset, so any pending 
    // moves in the planner and serial buffers are all cleared and newly sent blocks will be 
    // locked out until a homing cycle or a kill lock command. Allows the user to disable the hard
    // limit setting if their limits are constantly triggering after a reset and move their axes.
    if (sys.state != STATE_ALARM) { 
      if (bit_isfalse(sys.execute,EXEC_ALARM)) {
        mc_reset(); // Initiate system kill.
        bit_true_atomic(sys.execute, (EXEC_ALARM | EXEC_CRIT_EVENT)); // Indicate hard limit critical event
      }
    }
    if ( Ext_pin_peudo_ISR() ) { return;}
 }  

system.c 中真正的 ISR 会被类似的 #if 删除,
这意味着将几行代码从 system.c 拉入到 limits.c 中,但这没什么大不了的。

逻辑看起来合理吗?

谢谢。

添加 SPI #748

似乎设置结构中有死变量。我想知道它可能是什么,然后发现:什么都没有;)

settings.dir_invert_mask

它由 report.c 打印,可以从命令行设置,但从未使用过。阶跃掩模需要反转才能结束阶跃脉冲,但方向是一一反转的。根据位置。

有机会时可以做一点清理工作。

添加 SPI #748

你确定?检查 stepper.c 的初始化例程。我想你会发现这不是真的。

添加 SPI #748

好吧,它确实存储在 EEPROM 中,但似乎没有用。我刚刚编辑了所有提及它并将其从结构中删除并编译,所以我必须查看所有用法。它节省了 132 个字节。

它似乎是从 st_generate_step_dir_invert_masks() 中的步骤掩码中克隆出来的,但从未被使用过。

添加 SPI #748

@J-Dunn:我没有看到任何这样的方向反转克隆到步进掩码中。它们是完全独立的实体。两者都适用于其特定目的。您能否指出您认为源代码中没有使用 dir_invert_mask 的地方?

添加 SPI #748

好的,我想我已经看到了我所缺少的东西。每次 ISR(TIMER1_COMPA_vect) 触发它都会反转哪些步进器得到处理:主轴或从属 Bresenham 轴。

我被误导了,因为这些方向掩码似乎没有任何方式可以以编程方式改变。似乎这些未定义常量的全部意义在于允许它以交互方式设置和存储。需要一段时间才能意识到其中一些在做什么,这很令人困惑,因为其中几个变量名称是相似的。

希望我现在和它在一起。对不起,噪音。

添加 SPI #748

我现在对 ISR 的内部运作有了更好的理解。您已经说过,您的目标之一是使此代码易于适应,我同意它的注释和布局都很好。我发现一个障碍是变量名,这经常令人困惑。一旦我更熟悉代码,我会提交一些建议。目前我正在本地进行更改并做笔记。

一件事让我觉得有点冒险。
STEP_PORT = (STEP_PORT & ~STEP_MASK) | st.step_port_bits;

这将影响 DIRECTION_PORT 上刚刚设置为“几个 ns”的位,因为默认情况下 step 和 dir 都在同一个 Arduino 端口上。此处输出的值在上一次调用此 ISR 结束时确定。:
st.step_port_bits ^= step_port_bit_mask;

准确地说,这条线应该只对相关位进行异或,或者输出线应该只对相关位进行或。例如。
STEP_PORT = (STEP_PORT & ~STEP_MASK) | (st.step_port_bits & STEP_MASK );

它花费2字节。

认识到 GRBL 是成熟且经过良好测试的软件,它似乎可以在该领域工作,尽管它似乎是飞近电线以在设置 STEP_PORT 输出的同时意外更改 dir 端口。它也无助于理解代码和对其他硬件的可移植性,在这些硬件中,时序将不一样。

相反,重置引脚的 ISR 可能做的比需要的更多。
STEP_PORT = (STEP_PORT & ~STEP_MASK) | (step_port_bit_mask & STEP_MASK);

如果由手动命令行或 EEPROM 设置,step_port_bit_mask 可能包含比定义的常量 STEP_MASK 更多或更少的位。如果更多,STEP_MASK 将杀死额外的位(这很好),但这不应该在这里捕获。如果更少,做 & STEP_MASK 是多余的。

添加 SPI #748
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
    st.counter_x += st.steps[X_AXIS];
    st.counter_y += st.steps[Y_AXIS];
    st.counter_z += st.steps[Z_AXIS];
#else
    st.counter_x += st.exec_block->steps[X_AXIS];
    st.counter_y += st.exec_block->steps[Y_AXIS];
    st.counter_z += st.exec_block->steps[Z_AXIS];
#endif 

添加 SPI #748

您正在进入语义,这是受欢迎的,但这很容易成为浪费时间而没有太多好处。很好地抓住了阶梯面具部分。它暗示是正确的,但不像你说的那样可移植。可能是写的时候疏忽了。至于组合计数器,没关系。

添加 SPI #748

counter 只是一个简单的整理,使它更容易阅读。很高兴我对 STEP_MASK 的事情是正确的,这意味着我正在掌握它在做什么。

#define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_AXIS)|(1<<Z_AXIS))
这里的默认值为 6,它不是反转掩码。令人困惑。将其称为地图以将其与面具区分开来可能会有所帮助,它在功能上有所不同。当我通过时,我会建议更好的名字。

我很难理解为什么从轴的方向与驱动轴相反。暗示?

添加 SPI #748
作者

J-邓恩 评论 2015 年 7 月 1 日

@langwadt 您似乎对 L6474 很熟悉,并且您说您更喜欢对 SPI 进行 bit-bang。您看过 Michel F 发布的 L6474 库吗?
https://github.com/MotorDriver/L6474

它看起来相当彻底,但我没有使用他提供的演示从 SPI 获取合理的状态字节。演示使电机移动,但我不确定 SPI 是否正常工作。

我希望以此作为将 L6474 引入 GRBL 的基础,并假设它是工作代码。

添加 SPI #748

是的,我在工作中的一个项目中使用了 L6474,并且我还在 Nucleus stm32f411 + 3*L6474 上运行了一个 grbl 端口。
我见过这个库,它有这样的库总是有的优点和缺点,它们是如此的
通用。我做得更简单,一个函数写入设置所有
寄存器所需的字节,一个函数启用/禁用输出,一个函数读取状态

至于状态,请记住许多状态位是低电平有效

添加 SPI #748
作者

J-邓恩 评论 2015 年 7 月 2 日

谢谢 langwadt,你愿意分享 grbl 的 Nucleo 端口吗?Stm32f4 + 3*L6474 是我要去的地方。在 Arduino 上进行这项工作只是掌握使用该库作为示例代码以菊花链方式连接三个板的第一步。在这种情况下,将其用作库显然太笨重了。我已经删除了要添加到 grbl 的必需品,初始构建只添加了大约 800 个字节。

我发现我没有从 SPI 得到正确的返回,所以回到库演示,发现那里发生了同样的事情。所以我不确定这个库是有问题还是我有接线故障。

如果您已经在 stm32f4 上进行了这项工作,那么重新发明该特定轮子将为我节省大量时间。谢谢。

添加 SPI #748
作者

J-邓恩 评论 2015 年 7 月 5 日

我接近让 GRBL + L6474 在 Arduino 上工作。

显然有一些额外的开销,而且 GRBL 已经很紧张了。你有我可以运行的压力测试吗?当我连接硬件并开始向它抛出一些 gcode 时,我特别想到堆栈和堆溢出。

这是一台相当重的机器,我不希望在硬件测试期间出现这样的情况。

我可以发明一些测试,但随着项目的成熟,我想有人已经这样做了。有什么建议么?

谢谢。

添加 SPI #748

我有一堆使用 GRBL 的三个 L6474,代码大小为 30440 字节。可以稍微修剪一下,但这完全在代码限制之内。

如果存在将输出置于 HiZ 状态的严重错误,它会像限制引脚一样进行硬停止;热警告软停止;并且只清除非关键错误,例如错误的命令字节。我使用了 INT0,因为这就是 L6474 的接线方式。通过在 ISR 顶部重新打开 sei(),它对 GRBL 时序的干扰最小。

所有这些都需要经过适当的测试,但简单的 circle.gcode 示例确认 GRBL 仍在运行。

感谢以上所有人的帮助。;)

添加 SPI #748

你好@J-Dunn:我也在尝试使用与 L6474 类似但具有更高额定电流的 powerSTEP01 运行 GRBL。您能否分享您的适用于 Arduino+GRBL+L6474 的代码或项目。我也打算以后去STM32s。但只是想先尝试 Arduino,因为我使用 Arduino+GRBL_Easy Driver 来运行小型 CNC。

谢谢你和这里的其他人。你的讨论很有启发性。

-卡子

添加 SPI #748

嗨,我没有任何可发布状态的东西,这都是在制品。如果我在不久的将来有一点时间,我会考虑一下。

我目前正在移植 stm32 代码以与 STEP01 板一起使用,尽管我一直试图通过合适的编译器切换保留以前的代码库,它可能会在再次用于 AVR 之前进行一些调试。

step01 代码已准备好在硬件上进行测试,我可以通过更改 #define 将其从 L6474 翻转到 Step01。

添加 SPI #748

好吧。谢谢@J-Dunn.
将定期检查您的帖子。

添加 SPI #748
作者

J-邓恩 评论 2017 年 3 月 18 日  

为了不让您一无所获,我认为这是 AVR 文件中 L6474 的最新版本。以通常的方式将它们添加为库。我使用 arduino makefile 使用 Geany 编辑器构建和调试,以摆脱可怕的 Arduino 伪 IDE,但我认为它仍然应该在 IDE 中工作。

它为 Arduino 上最多三个 L6474 板提供基本 SPI 通信。3 板 get_status() 的往返时间约为 19us ,这足够快,足以适应 Arduino GRBL 通常的最高速度。该代码仅适合大约 140b 备用 IIRC 的内存。

https://github.com/J-Dunn/grbl_stm32/blob/master/grbl_L6474_latest.bz2

您将需要更改基本的 GRBL 代码以调用所需的库函数。抱歉,我手头没有完整的点击即走解决方案,但您拥有快速工作界面的胆量。其余的应该相当明显:设置 FLAG 引脚,如 GRBL 限制输入等。

在 c 文件的末尾,您将找到一个用于 FLAG 引脚的中断处理程序,该处理程序可以整理出关键和非关键错误并提供一些 USB 输出。

当我完成 STEP01 代码的调试后,我可能会有更完整的东西。

这不是为发布而整理的,它是所见即所得的,“原样”丰富的评论,可能还有一些不相关或神秘的调试说明。我希望它是有用的。

添加 SPI #748

添加 SPI #748
喜欢 (0)

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