【问题标题】:How to handle ISR callback?如何处理 ISR 回调?
【发布时间】:2017-11-06 09:03:47
【问题描述】:

我目前正在从事一个更大的 Arduino Mega 2560 项目;涉及伺服控制和传感器读数。我正在使用带有NewPing 1.8 库的超声波接近传感器(HC-SR04),该库使用中断来检测传感器的回波。此外,我还阅读了温度和光强度测量值。从 HC-SR04 超声波传感器接收到的距离数据通过 USB 使用cmdMessenger3 库转发到主机。伺服系统由来自主机的消息控制,使用标准的Servo 库。

当检测到超声波回波时,NewPing 库调用ISR 时,混乱就开始了。这是 NewPing 库在距离数据可用时调用的函数:

void sendSonarData(uint8_t sensorId, uint16_t distance) {
  //noInterrupts();   
  cmdMsg3.sendCmdStart(kReadSonar);
  cmdMsg3.sendCmdArg(sensorId);
  cmdMsg3.sendCmdArg(distance);
  cmdMsg3.sendCmdEnd();
  //interrupts();
}

这是另一个通过 cmdMessenger3 库向主机发送温度数据的回调:

void sendTemperatureData(uint8_t sensorId, uint16_t temperature) {
  //noInterrupts();   
  cmdMsg3.sendCmdStart(kReadTemperature);
  cmdMsg3.sendCmdArg(sensorId);
  cmdMsg3.sendCmdArg(temperature);
  cmdMsg3.sendCmdEnd();
  //interrupts();
}

问题:虽然 Arduino 例如尝试发送温度数据时,来自超声波传感器的 ISR 可能会介入并将其自己的数据写入串行流;最终导致发送到主机的串行数据一团糟,因为发送过程不是原子的,由发送一条消息的多个命令组成(sendCmdStart->sendCmdArg->sendCmdEnd)。

这是一个例子:

  1. 读取温度并调用sendTemperatureData(...)
  2. cmdMsg3.sendCmdStart(kReadTemperature); 被调用
  3. cmdMsg3.sendCmdArg(sensorId); 被调用
  4. 来自声纳传感器的 ISR 介入
  5. sendTemperatureData(); 被调用
  6. cmdMsg3.sendCmdStart(kReadSonar); 被调用
  7. cmdMsg3.sendCmdArg(sensorId);
  8. cmdMsg3.sendCmdArg(distance);
  9. cmdMsg3.sendCmdEnd();
  10. sendTemperatureData(...) 的剩余语句被调用
  11. cmdMsg3.sendCmdArg(temperature);
  12. cmdMsg3.sendCmdEnd();
  13. 导致串行通信一团糟...

然后我尝试使用noInterrupts()/interrupts() 在发送过程中阻止 ISR 调用;使发送过程具有“原子性”。但这会导致很多其他问题,millis()/micros() 函数不再精确,串行通信中断等;都依赖于noInterrupts() 禁用的计时器。此外,舵机的行为也很奇怪,因为 PWM 信号生成的时间似乎也搞砸了。

任何想法如何在不破坏我的程序中基于中断的范例的情况下解决这个“并发”问题?

【问题讨论】:

    标签: arduino interrupt interrupt-handling


    【解决方案1】:

    你正试图在你的 ISR 中做很多工作;一般来说,他们不应该做任何需要延迟的事情(任何超过 1 个字节的串行消息都属于该类别)。更合理的实现是让 ISR 简单地将传感器读数存储在全局变量中,并设置一个标志,主程序检查它是否应该发送串行消息。如果来自同一个传感器的第二个读数可能在前一个有机会发送之前到达,您可能需要更高级的东西(例如消息队列)。

    【讨论】:

    • 非常感谢您的解决方案。我会尽快发布我的实现 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    • 1970-01-01
    • 2019-05-30
    相关资源
    最近更新 更多