串行没有正确读取监视器的所有输入

问题描述

我正在尝试使用监视器向 Arduino MEGA 发送输入。我注意到有 1/6 次,Serial 在我的输入中跳过 1 个或多个字母。我试过 Serial.read() 和 Serial.readStringUntil() 但都跳过输入。我尝试在 Serial.read() 之后放置延迟,但它什么也没做。我还尝试在 if(complete){...} 代码块中执行 Serial.flush 但无济于事。

this picture 中,“A**”被正确发送(我注意到它总是有,因为它是第一个监视器输入)。但是诸如“s**100”之类的后续命令被发送为“s*0”。这里是否滥用了 Serial 类?使用串行监视器时是否存在配置错误? (无行尾)。会不会是使用其他自定义类会干扰 Serial,即使它没有明确与之交互?

//===========================================THE IMPORTANT PART===============================================
void loop() {
  digitalWrite(13,HIGH);
  while (Serial.available()){
    String temp = Serial.readStringUntil(';');
    Serial.println(temp);
    command = temp.substring(0,3);
    param = temp.substring(3).toInt();
    complete = true;

    Serial.println("temp  "+temp);
    Serial.println("comm "+command);
    Serial.println("para "+command);
  }
//=============================================================================================================
  if(complete){
    Serial.println("complete");

    if(command == MODE_SOLID || command == MODE_GRADIENT || command == MODE_OFF){
       current_mode = command;
    }
    else if(command == COMMAND_BRIGHTnesS){
      current_brightness = param;
    }
    else if(command == COMMAND_SATURATION){
      current_saturation = param;
    }
    else if(command == COMMAND_COLOR){
      current_color = param;
    }
    else if(command == COMMAND_RANDOM_BRIGHTnesS_UPPERLIMIT){
      current_random_brightness_upper_limit = param;
    }
    else if(command == COMMAND_RANDOM_BRIGHTnesS_LOWERLIMIT){
      current_random_brightness_lower_limit = param;
    }
    else if(command == COMMAND_RANDOM_SATURATION_UPPERLIMIT){
      current_random_saturation_upper_limit = param;
    }
    else if(command == COMMAND_RANDOM_SATURATION_LOWERLIMIT){
      current_random_saturation_lower_limit = param;
    }
    else if(command == COMMAND_RANDOM_COLOR_UPPERLIMIT){
      current_random_color_upper_limit = param;
    }
    else if(command == COMMAND_RANDOM_COLOR_LOWERLIMIT){
      current_random_color_lower_limit = param;
    }
    else if(command == COMMAND_COLOR){
      current_color = param;
    }
    complete = false;
    command = "";
    param = 0;
  }
  if(current_mode == MODE_SOLID){
    solid.setBrightness(current_brightness);
    solid.setSaturation(current_saturation);
    solid.setColor(current_color);
    solid.runPattern();
  }
  else if(current_mode == MODE_GRADIENT){
    blinkSolid.setCurrentRandomBrightnessLowerLimit(current_random_brightness_lower_limit);
    blinkSolid.setCurrentRandomBrightnessUpperLimit(current_random_brightness_upper_limit);
    blinkSolid.setCurrentRandomSaturationLowerLimit(current_random_saturation_lower_limit);
    blinkSolid.setCurrentRandomSaturationUpperLimit(current_random_saturation_upper_limit);
    blinkSolid.setCurrentRandomColorLowerLimit(current_random_color_lower_limit);
    blinkSolid.setCurrentRandomColorUpperLimit(current_random_color_upper_limit);
    blinkSolid.runPattern();
  }
  else if(current_mode == MODE_OFF){
    strobePalette.runPattern();
    //fill_solid( leds,NUM_LEDS,CRGB::Black);
    //FastLED.show();
  }  
}

解决方法

我在使用物理设备时遇到过类似问题,大多数情况下是在恶劣的环境中或使用有缺陷的接线。 我使用 tinkercad 和 Arduino Uno 测试了你的代码,只有通信部分。这是我测试的代码:

bool complete;
String command;
int param;

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

}

void loop()
{
  
  digitalWrite(13,HIGH);
  while (Serial.available()){
    String temp = Serial.readStringUntil(';');
    Serial.println(temp);
    command = temp.substring(0,3);
    param = temp.substring(3).toInt();
    complete = true;

    Serial.println("temp  "+temp);
    Serial.println("comm "+command);
    Serial.println("para "+ String(param)); //I changed this line in order to see the value of "param" in the serial monitor
  }
  if(complete){
    Serial.println("complete");
    
    complete=false;
    command="";
    param=0;
  }
}

我测试了发送字符串 A**100;B**101;C**102;D**103; 的代码所有部件都完好无损,并且解码良好。这是 TinkerCad 输出:

A**100
温度 A**100
通讯A**
第 100 段
B**101
温度 B**101
通讯B**
第 100 段
C**102
温度 C**102
通信C**
第 100 段
D**103
温度 D**103
通信 D**
第 100 段

我还使用物理 Arduino uno 测试了代码,它在 Tinkercad 中运行良好。这就是我要做的:

  1. 让代码只包含通信部分,就像我所做的那样,看看它是如何表现的。如果您的代码仅在通信部分运行正常,那么您的代码的其余部分就会受到干扰。如果不知道自定义类的代码,就很难判断可能是什么。
  2. 如果您将物理 arduino 连接到 PC 的 USB 端口,请更换该电缆。某些有缺陷的电缆可能会运行异常并导致此类问题。
  3. 如果您要在恶劣的环境中安装设备,请尝试使您的代码能够抵抗此类错误,它们很可能无论如何都会出现。在这种情况下,我使用了起始字符、结束字符和固定长度,例如 @A**100;@B**101;其中@ 是起始字符,分号 (;) 是结束字符,所有命令的长度均为 8 个字符。我丢弃了所有不满足这些参数的命令。使用 CRC 是另一种选择,但在大多数情况下,使用我刚刚描述的简单模式就足够了。