Odd behavior when statement are inside Switch

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;
    }
  }
  
}

Simple the face that you can not declare variables inside a switch statement. It's part of C.

I moved these lines out of the Switch statement and the sketch worked!

Moved them to where?

Why are you using Strings to receive well defined data? How long are the values in ?

Thank you Grumpy_Mike,

I totally missed that. I am going to tweak it so that the declaration is made outside the switch and reinstate the statements as they were originally. Mind you, this is only for testing, since I like the two statements outside the switch and in fact I see no reason why they should be duplicated inside each case. Salvador

Thank you PaulS,

I moved them outside the switch statement. See the second sketch at the end of my original post. The two statements were relocated to just above where the switch statement begins.

I have no good answer to your second question. I started using one of the serial examples provided with the Arduino IDE which used a string to receive data. I added code to adapt to my needs. I read that it was recommended to first accumulate the full string then parse it, instead of receiving it char by char and parsing it as it came along. I should mention that I had (have) both versions of this.

If you have a recommendation that is better than what I have, please share or point me to where I can research it further. I am always looking to improve code and frankly the solution that I presented was cobbled together using existing examples.

The length of the data varies. It will always be an integer number ranging from 1 to 5 digits long. Regards, Salvador

It will always be an integer number ranging from 1 to 5 digits long.

Then, a char array of 10 elements should be more than enough. Ditch the String class. Learn to use strings (NULL terminated array of chars), instead.

PaulS, thanks for the recommendation. I will look into this. Basically what you are saying is that I should declare an array of chars and then collect the incoming chars into each of the array's elements. When all the serial data is in, process. Salvador