【问题标题】:Arduino serial timeouts after several serial writes多次串行写入后 Arduino 串行超时
【发布时间】:2013-12-03 19:57:02
【问题描述】:

当我使用我的自定义固件时,我注意到我的 DIY 无人机板有一个奇怪的行为。 这是我在 Arduino 板上运行的固件中调用的示例函数:

void send_attitude(float roll, float pitch, float yaw) {
  hal.console->printf("{\"type\":\"sens_attitude\",\"roll\":%.4f,\"pitch\":%.4f,\"yaw\":%.4f}\n",
                      roll, pitch, yaw);
}

如您所见,代码只是在 setup (hal.uartA) 中设置的串行端口中写入一条消息。 我每 0.5 秒调用一次这个函数:

 inline void medium_loop() {
  static int timer = 0;
  int time = hal.scheduler->millis() - timer;

  // send every 0.5 s
  if(time > 500) {  
    send_attitude(OUT_PIT, OUT_ROL, OUT_YAW);

    timer = hal.scheduler->millis();
  }
}

现在来说奇怪的事情。如果我使用串行监视器或使用另一个程序或脚本读取板,一切都很好。每隔 0.5 秒,相应的 LED 会闪烁并显示消息。但如果我不把它读出来,appr 之后。 10 秒 LED 持续亮起,无法再进行连接/通信。那我得把板子拔掉。反过来观察到相同的行为。如果我通过串行端口(在我的情况下为 USB)发送到我的电路板并且不刷新输入缓冲区,则 LED 会持续刷新并且我会超时。以下代码有效:

def send_data(line):
  # calc checksum
  chk = chksum(line)
  # concatenate msg and chksum
  output = "%s*%x\r\n" % (line, chk)
  try:
    bytes = ser.write(output)
  except serial.SerialTimeoutException as e:
    logging.error("Write timeout on serial port '{}': {}".format(com_port, e))
  # Flush input buffer, if there is still some unprocessed data left
  # Otherwise the APM 2.5 control boards stucks after some command
  ser.flush()       # Try to send old message
  ser.flushInput()  # Delete what is still inside the buffer

如果我注释掉这一行:

ser.flushInput()  # Delete what is still inside the buffer

我不使用更多设置然后这个。 我迟早会(取决于消息间隔)超时。在我的情况下,我每 20 毫秒发送一个信号,导致约 10 秒后超时。还取决于消息的长度。较大的消息比较小的消息更快。

我的设置显示在下面的 sn-ps 中。客户端python代码:

com_port  = '/dev/ttyACM0'
baud_rate = '115200'
try:
  ser = serial.Serial(com_port, baud_rate, timeout=0.1, writeTimeout=0.1, rtscts=1)

如果这些超时发生,那么如果我将超时设置为 2 秒,我也会得到一个。就我而言,我需要非常低的延迟,如果我继续阅读和刷新,这确实是可能的。来自我的 Arduino 的固件代码:

void setup() {
  // Set baud rate when connected to RPi
  hal.uartA->begin(115200);
  hal.console->printf("Setup device ..\n");
  // Followed by motor, compass, barometer initialization

我的问题是:

  • 我的电路板到底发生了什么?

  • 如果我只在串行端口中写入而不读取或刷新缓冲区,为什么它不再反应?

  • 这真的是与这种奇怪行为相关的缓冲区或驱动程序问题吗?这个问题是否与所有 Arduino 板有关,或者可能只是我从 DIY 无人机上的 APM 2.5?

  • 最后但同样重要的是:我在库中没有找到针对此类问题的函数。有没有我不知道的?

完整源码为@google 代码:https://code.google.com/p/rpicopter/source/browse/

【问题讨论】:

  • 你能粘贴你的串口参数deceleration(baud, parity, timeout....)吗?
  • 我编辑了我的问题,以回答这个问题
  • 你有什么板子?请尽量详细说明所有技术细节并提供组件链接。

标签: python c serial-port usb arduino


【解决方案1】:

您使用的是什么板,它有什么处理器?我的猜测是您的开发板是基于 ATmega32U4 或其他一些具有内置 USB 模块的微控制器。如果是这样,我之前看到过类似的行为,这就是我认为正在发生的事情:

您的微控制器上有一个缓冲区,用于保存发送到计算机的串行数据。计算机的 USB 串行驱动程序中有一个缓冲区,用于保存从芯片接收到的串行数据。由于您没有从 COM 端口读取字节,因此计算机上的缓冲区将被填满。一旦计算机上的缓冲区填满,它就会停止向微控制器请求数据。因此,微控制器上的缓冲区最终会被填满。

一旦微控制器的缓冲区已满,您希望 printf 命令的行为如何?为简单起见,您使用的 printf 可能设计为在阻塞循环中等待,直到缓冲区空间可用,然后发送下一个字符,直到消息完成。由于缓冲区空间永远不可用,您的程序会陷入无限循环。

更好的策略是在调用 printf 之前检查是否有足够的缓冲区空间可用。代码可能如下所示:

if(console_buffer_space() > 80)
{
    hal.console->printf(...);
}

我不知道在DIY无人机固件中是否可以实现,我不知道最大缓冲区空间是否真的可以达到80,所以你需要研究一下。

【讨论】:

  • 我有 ATmega2560。我想你是对的。它与缓冲区相关,并且查看引导加载程序支持这个想法。也许可以为引导加载程序编写一个补丁,因为至少对我来说这种行为可能是危险的。如果 USB 电缆断开,则会导致崩溃。此外,我发现 Arduino SDK 中没有检查缓冲区的功能。
【解决方案2】:

我不明白:

ser.flush()       # Try to send old message
ser.flushInput()  # Delete what is still inside the buffer

假设您的设备已连接到 PC,python 代码正在编写(line, chk)

ser.flush() - 你为什么要使用它? ser.flushInput() - 将“删除”PC 上的串行输入缓冲区

【讨论】:

  • 我认为使用 flush() 程序会等到所有内容都发送完毕,所以我认为使用它是个好主意。但在我的情况下,它没有任何效果,并且在没有flush()的情况下一切正常。相反,如果我取消注释 ser.flushInput() 迟早会超时,但在 100% 的情况下。
  • 当您说超时时,您的意思是SerialTimeoutException?如果是这样,那么flushInput() 与它无关。恕我直言,您的问题出在固件上。
  • 我得到了这个异常。此外,即使我停止发送一段时间,直到使用此命令刷新缓冲区,板仍会继续接收数据。我想,数据的发送速度比板子可以处理的速度更快,并且一些缓冲区已填满,这会导致极度减速导致超时。但让我想知道的是,即使我只是在一段时间内使用 printf 从板上发送一些东西而不读取或只是将数据发送到板上,也会发生这种情况。
  • 我将链接添加到我的谷歌代码项目中,其中包含我问题中的所有文件。
  • 我最好的建议是尝试将问题分开。首先调试你的python代码,这是你可以通过PC TX-RX并看到你的脚本没问题的最简单的东西,然后用RS232Analyzer之类的终端尝试你的设备。
【解决方案3】:

看起来其他人也有同样的问题。感谢 Mod-Braniac 删除了我的最小示例。我敢打赌,这是 Arduino USB 控制器芯片或其上的固件的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-24
    • 1970-01-01
    • 2017-11-14
    • 2013-01-25
    • 1970-01-01
    • 2020-08-23
    • 1970-01-01
    相关资源
    最近更新 更多