Contact me: hankecnc@gmail.com

使用数字和模拟输入扩展 GRBL #1275

推推 grbl 3年前 (2023-01-23) 318次浏览

关闭
dastultz 打开了这个问题 2017 年 8 月 18 日 · 4条评论
关闭

使用数字和模拟输入扩展 GRBL#1275

dastultz 打开了这个问题 2017 年 8 月 18 日 · 4条评论

注释

使用数字和模拟输入扩展 GRBL #1275

你好,

我在这里认真地旋转我的轮子,希望我能得到一些帮助。我正在尝试为带有多个按钮、灯和电位器的 Sanguino/644p 定制 GRBL。(我正在用 GRBL 替换我自己开发的运动控制器,所有这些都是为了点动/覆盖控制。)

我的一些代码遇到了一个非常奇怪的问题。我已经从主协议循环中添加了对我的代码的调用,这里进行了简化以关注问题:

void loop() {
  input_service();
  
  if (input_edgeHigh(6)) {
    println(input_edgeHigh(6), 8);
  }

  uint8_t high = input_edgeHigh(6);
  if (high) {
    println(high, 8);
  }
}

input_service()函数读取数字输入和一个模拟输入。数字输入状态存储在字节数组中。我跟踪当前和以前的状态,以便我可以响应上升沿和下降沿。

当数字输入 6 变高时,该函数input_edgeHigh返回一个非零值。2 个“if”块具有不同的行为。“if”块都打印出input_edgeHigh函数调用返回的值。第一个“if”块第一次打印“1”,然后多次打印“0”(只要引脚保持高电平)(println以二进制字符串形式写入串行)。第二个“if”块只打印一次“1”。这似乎是非常错误的(第一个块打印“0”),因为如果函数返回零,则不应输入该块。第二个“if”块的行为符合预期,以某种方式将结果分配给局部变量可以解决问题。

如果你仍然和我在一起,这里是相关的代码,简化了。我将引脚的当前和先前状态存储在 buttonStates[] 中每个条目的最右边的 2 位中。

#define DIN_STATE_CURR 0b001
#define DIN_STATE_PREV 0b010

uint8_t buttonStates[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

uint8_t input_edgeHigh(uint8_t dinIndex) {
  return (buttonStates[dinIndex] & DIN_STATE_CURR)
      && !(buttonStates[dinIndex] & DIN_STATE_PREV);
}

有趣的是,我有一个input_edgeLow工作正常的功能……

我更大的问题是,因为我没有解决办法,读取模拟输入总是返回 0。我已经在 Arduino 草图中测试了所有这些逻辑(除了串行之外不使用 Arduino.h 东西)并且一切正常完美无缺。

我已经浏览了 GRBL 代码并注释掉了与 IO 相关的所有内容,但行为没有变化的步进器除外。

任何人都可以解释发生了什么,或者给我一些读取模拟输入的方法吗?是否有 Arduino sketch 做了 GRBL 没有做的事情,或者 GRBL 做了 Arduino sketch 没有做的事情?

谢谢。

/达里尔

使用数字和模拟输入扩展 GRBL #1275
作者

你好,我已经解决了逻辑问题和模拟读取问题,虽然我不太明白发生了什么。

analogRead()实现于wiring_analog.c调用delay(1). 这在某种程度上是有问题的。直接delay(1)放入我的代码无法编译。关于. vector_18_stepper.c

该函数input_edgeHigh声明为返回uint8_t,但它实际上返回多于 8 位。在一个更简单的场景中,比如比较uint8_t3 和 3 的 2 个值,返回值实际上是 256。我对第 9 位没有任何解释,但我知道如何解决它。如果我没记错我的故障排除,此行为不会出现在 C++ 中。

我离开这个开放希望有人可以教育我。如果您觉得它离题,请继续并关闭它。

谢谢。

使用数字和模拟输入扩展 GRBL #1275

Arduino API 和 Grbl 不能混用。真的,省去麻烦,甚至不要尝试。

ArduinoanalogRead()使用一种复杂的(并且设计非常糟糕,恕我直言)方式来读取 ADC 而无需实际使用中断(即它应该完成的方式)。它对转换何时开始以及需要多长时间做出假设,并通过delay()在 ADC 执行其操作时调用以停止 CPU 来隐藏所有这些。
反过来, Arduinodelay()也对哪些计时器可用或不可用做出假设,由于 Grbl确实使用计时器而不考虑或允许 Arduino API(因为它们不应该共存) ,因此该假设无效. 这就是产生 vector_18() 错误的原因。

从 Grbl 读取模拟输入的正确方法是这样的:

  1. 为 ADC 编写 ISR,尽可能简单和简短:基本上只需从 ADC 读取转换后的值并将其存储在全局易失性变量中。除了该值,还设置一个布尔标志,指示该值 [刚刚] 已更新。
  2. 在通用初始化代码中,配置 ADC 并启用其“转换完成”中断。
  3. 在 Arduino 的调用站点analogRead(),将布尔标志设置为 false 并启动 ADC 转换。
  4. 再往下,当您实际使用该值时,插入一个标志检查:如果为真,则存储的值可用。如果没有,则 ADC 尚未完成,您应该“稍后再回来”。根据您的代码设计方式,这可能字面意思是“稍后再试,在未来的迭代中”或忙循环。请记住,Grbl 是实时运行的,因此任何时间的繁忙循环都可能导致其性能下降。
使用数字和模拟输入扩展 GRBL #1275
成员

Grbl 不使用任何 arduino 代码,如果你这样做就会中断。它只是使用 arduino IDE,作为一种工具,可以轻松地将 Grbl 编译和闪存到 Arduino 兼容硬件。

使用数字和模拟输入扩展 GRBL #1275
作者

是的,我知道与 Arduino 不兼容。我描述的路径帮助我解决了所有问题,但我不打算继续使用 Arduino 库或错误 GRBL 来解决问题。GRBL 很棒。如果其他人认为有用,我会分享我的发现。

感谢您的解释和一个伟大的项目。

喜欢 (0)