当我使用我的自定义固件时,我注意到我的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闪烁并显示信息但如果我不把它读出来的话,请在通知后10s 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秒后超时。这也取决于消息的长度较大的消息比较小的消息更快。
我的设置显示在下面的代码片段中客户端python代码:
com_port  = '/dev/ttyACM0'
baud_rate = '115200'
try:
  ser = serial.Serial(com_port, baud_rate, timeout=0.1, writeTimeout=0.1, rtscts=1)

如果这些超时发生,那么如果我将超时设置为2s,我也会得到一个超时,在我的情况下,我需要一个非常低的延迟,如果我继续阅读和刷新,这确实是可能的我的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板或可能只是我的APM2.5从DIY无人机?
最后但并非最不重要的是:我在库中找不到针对此类问题的函数可能有我不知道的吗?
完整的源代码是@google code:https://code.google.com/p/rpicopter/source/browse/

最佳答案

你用的是什么板,它有什么处理器我猜你的电路板是基于ATmega32U4,或者其他一些内置USB模块的微控制器如果是这样的话,我以前也看到过类似的行为,我认为是这样的:
你的微控制器上有一个缓冲区,用来保存发送到计算机的串行数据计算机的USB串行驱动程序中有一个缓冲区,用来保存从芯片接收到的串行数据由于您没有从COM端口读取字节,计算机上的缓冲区将填满一旦计算机上的缓冲区填满,它就停止向微控制器请求数据因此,微控制器上的缓冲区最终会填满。
一旦微控制器的缓冲区已满,您希望printf命令的行为如何为了简单起见,您使用的printf可能被设计成只在阻塞循环中等待缓冲区空间可用,然后发送下一个字符,直到消息完成因为缓冲区空间永远不可用,所以程序陷入无限循环。
一个更好的策略是在调用printf之前检查是否有足够的缓冲空间可用代码可能如下所示:

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

我不知道这在DIY无人机固件中是否可行,我也不知道最大缓冲空间是否能达到80,所以你必须对此进行一些研究。

关于python - 几次串行写入后Arduino串行超时,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20360432/

10-13 08:00