Arduino Serial.parseInt() 数据读取被太多 Serial.print() 损坏?

Arduino Serial.parseInt() data read corrupted by too much Serial.print()?

我正在做一个 Arduino 项目,让风扇根据 iRacing 中的车速旋转。这是我的第一个 arduino 项目,所以请多多包涵。我真的对 PC/Arduino 串行通信的一些奇怪行为感到困惑,我希望有人能帮助解释发生了什么......

基本上,PC 上有一个 C++ 程序,它从 iRacing SDK 获取车辆速度数据,并通过串行线将其发送到 Arduino。 Arduino 做一些简单的处理并驱动电机控制器 运行 风扇。

我试图理解的现象是,如果我让 Arduino 使用 Serial.print() 语句向串行写入太多内容,它就会开始破坏其使用 Serial.parseInt 读取的值().


我已经让它工作了,只是没有将 "too much" 写入串行线路,但有一段时间它表现不稳定 - 风扇速度上下波动即使 iRacing 值稳定。我在我的 arduino sketch 和 serial.readSerial 中添加了额外的 Serial.print 东西来尝试在 PC 端查看这些值发生了什么,结果证明这让情况变得更糟。

稍微拉扯我的头发后,我从头开始在 arduino 草图上工作,它使用所有相同的逻辑,但 Serial.print 命令被注释掉了!所以我系统地把它们加回去,发现有一个阈值,如果我在串行线上打印太多,它就会开始出现故障。

这是 PC 工作时看到的输出。 PC 将 59 作为整数发送到 Arduiono。 Arduino 正在接收 Serial.parseInt() 执行 constrain() 到 55,然后将其映射到 40-255 范围。最小的 Serial.print() 语句将该数据发送回 PC,在那里读取和打印数据。一切顺利。

59     55      255
59     55      255
59     55      255
59     55      255
59     55      255
59     55      255
59     55      255
59     55      255

如果我添加更多 Serial.print() 语句来描述数据,我使用 Serial.parseInt() 从 PC 读取的值开始受到干扰。此输出显示了发生这种情况时我所看到的内容。数据看起来一团糟,而且风扇速度确实失控了。这与上面的情况相同,应该稳定在 59:

Car Vel: 59     55      255
Car Vel: 59     55      255
Car Vel: 9      9       71
Car Vel: 47     47      223
Car Vel: 59     55      255
Car Vel: 59     55      255
Car Vel: 9      9       71
Car Vel: 47     47      223
Car Vel: 59     55      255
Car Vel: 71     55      255
Car Vel: 47     47      223
Car Vel: 59     55      255
Car Vel: 59     55      255

这是一直简化的 Arduino 草图,所以它所做的只是从 PC 读取 int,约束它,将它映射到一个范围并打印值。如下所示,它将发生故障并产生输出(如上面的第二个清单)。如果我注释掉 "Car Vel:" 打印,那么它就可以工作并且数据稳定(就像上面的第一个清单)。

#define MIN 40
#define MAX 255
#define TOPSPEED 55

void setup() {
  Serial.begin(9600);
}

void loop() {
  uint8_t v;
  uint8_t s;
  if (Serial.available() > 0) {
    v = Serial.parseInt();
    Serial.print("Car Vel: ");       //UNCOMMENT ANY OF THESE TO SEE THE FAIL
    Serial.print(v);
    Serial.print("\t");
    v = constrain(v,0,TOPSPEED);
//    Serial.print("Clamped Vel: ");   //UNCOMMENT ANY OF THESE TO SEE THE FAIL
    Serial.print(v);
    Serial.print("\t");
    s = map(v,1,TOPSPEED,MIN,MAX);   
//    Serial.print("Fan Speed: ");      //UNCOMMENT ANY OF THESE TO SEE THE FAIL
    Serial.println(s);
  }    
}

在 PC 端,我使用 iRacing SDK 中的 irsdk_ir2ad C++ 代码,仅对 运行() 例程进行如下修改:

void run()
{
    // wait up to 16 ms for start of session or new data
    if(irsdkClient::instance().waitForData(16))
    {
        // and grab the data
        int v = g_carVelX.getInt();
        serial.writeSerialPrintf("%d\n", v);
    }

    // check for data coming back from Arduino
    if (serial.serialHasData())
    {
        static char buffer[256];
        serial.readSerial(buffer, 256);
        printf("%s", buffer);
    }

    monitorConnectionStatus();
}

我相信取消对 Serial.print 行的注释确实会导致问题出现,但对于原因我没有真正好的解释。谁能帮忙?是否超出了某种发送长度(似乎是非常少量的文本)?或者当 Arduino 正在写出自己的数据时从 PC 写入了太多数据?或者某种计时问题,它只是额外的时间,与正在写入的数据量没有任何关系?

答案原来是9600波特的字符限制。

在这种特殊情况下,PC 正在以 60Hz 的频率获取数据。在 9600 波特率下,串行线路每个周期只能处理 16 个字符。

尝试输出整个字符串超过了 16 字节的限制: "Car Vel: 59 55 255"

实验表明,如果我将组合的 send/receive 数据降低到 <= 16 字节,它始终不会出错。