I am currently developing a small Arduino sketch that receives serial data. When testing I noticed that in some cases gibberish would be printed by the host computer when it received data from the Arduino. I put together a small no-thrills sketch to reproduce the problem. The sketch follows. All it does is wait to receive a command from the host and when it does it echos the result. The host sends the command in this format:
p:*
I the example I support two commands: p and d. The asterisk denotes the end of the command line. The Sketch receives the command, parses the data and prints it out to he serial connection. I am using the Arduino Uno, original, the Arduino IDE and the included serial monitor. In some cases, the host would only receive partial text, such as "Perc" instead of the complete line "Percent dec: ", plus the data. In other cases it would print gibberish. The baud rates on the sketch and serial monitor matched. The sketch:
String strInComm = "";
boolean bComplete = false;
float PercentData;
int intDelay;
void setup()
{
Serial.begin(9600);
// Serial.begin(115200);
}
void loop() //Main Loop
{
String sCmd = "";
String sData = "";
char chInChar;
if (bComplete) {
//The entire line is in, now parse the command and interptret.
//Get the command. The command is 1 char.
sCmd = strInComm.substring(0,1);
//Get the data. This goes from the : to the end.
sData = strInComm.substring(strInComm.indexOf(':') + 1);
//Serial.print("strInComm: ");
//Serial.println(strInComm);
//Serial.print("Cmd: ");
//Serial.println(sCmd);
//Serial.print("Data: ");
//Serial.println(sData);
if (sCmd=="p" or sCmd=="P")
chInChar = 'p';
if (sCmd=="d" or sCmd=="D")
chInChar = 'd';
switch (chInChar) {
case 'p':
char cmdChar[sData.length() + 1];
sData.toCharArray(cmdChar, sizeof(cmdChar));
PercentData = atof(cmdChar) / 100.0;
//Serial.print("Percent dec: ");
//Serial.println(PercentData);
break;
case 'd':
char cmdChar[sData.length() + 1];
sData.toCharArray(cmdChar, sizeof(cmdChar));
intDelay = atoi(cmdChar);
//Serial.print("Delay: ");
//Serial.println(intDelay);
break;
} //Switch chInChar
bComplete = false;
strInComm = "";
}
Serial.print("Percent dec: ");
Serial.println(PercentData);
Serial.print("Delay: ");
Serial.println(intDelay);
delay(1000);
}
void serialEvent() {
while (Serial.available() > 0) {
char inChar = (char)Serial.read();
// if the incoming character is an *, set a flag
// so the main loop can do something about it:
if (inChar == '*') {
bComplete = true;
}
else {
strInComm += inChar;
}
}
}
Since I was at a loss, I decided to rewrite the sketch from scratch and found that the lines causing all my woes wre the following:
char cmdChar[sData.length() + 1];
sData.toCharArray(cmdChar, sizeof(cmdChar));
I moved these lines out of the Switch statement and the sketch worked! I made the relevant changes to the full featured sketched and all worked. I am happy. My questions to this forum and its knowledgeable participants are the following:
Why did the code not work when the two statements were in the switch statement? If you run the sketch listed above, does the problem present itself?
Thank you. Salvador
PS: I'll include the functional sketch here:
String strInComm = "";
boolean bComplete = false;
float PercentData;
int intDelay;
void setup()
{
Serial.begin(9600);
// Serial.begin(115200);
}
void loop() //Main Loop
{
String sCmd = "";
String sData = "";
char chInChar;
if (bComplete) {
//The entire line is in, now parse the command and interptret.
//Get the command. The command is 1 char.
sCmd = strInComm.substring(0,1);
//Get the data. This goes from the : to the end.
sData = strInComm.substring(strInComm.indexOf(':') + 1);
//Serial.print("strInComm: ");
//Serial.println(strInComm);
//Serial.print("Cmd: ");
//Serial.println(sCmd);
//Serial.print("Data: ");
//Serial.println(sData);
if (sCmd=="p" or sCmd=="P")
chInChar = 'p';
if (sCmd=="d" or sCmd=="D")
chInChar = 'd';
char cmdChar[sData.length() + 1];
sData.toCharArray(cmdChar, sizeof(cmdChar));
switch (chInChar) {
case 'p':
PercentData = atof(cmdChar) / 100.0;
//Serial.print("Percent dec: ");
//Serial.println(PercentData);
break;
case 'd':
intDelay = atoi(cmdChar);
//Serial.print("Delay: ");
//Serial.println(intDelay);
break;
} //Switch chInChar
bComplete = false;
strInComm = "";
}
Serial.print("Percent dec: ");
Serial.println(PercentData);
Serial.print("Delay: ");
Serial.println(intDelay);
delay(1000);
}
void serialEvent() {
while (Serial.available() > 0) {
char inChar = (char)Serial.read();
// if the incoming character is an *, set a flag
// so the main loop can do something about it:
if (inChar == '*') {
bComplete = true;
}
else {
strInComm += inChar;
}
}
}