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