Read Serial causing reboots corrupt variables

Hi all,

I'm slowly building my Arduino project and learning as I go, I've been struggling to get my Arduino reading in the Serial port and actioning the data. I finally got it working the way I want it today, however depending on When and how Frequent I input data via serial, it can cause the Arduino to reboot, lockup or corrupt other variables (I think anyway). Basically, I'm reading in a serial.read, dropping it into an array based on a delimiter and then displaying the content on a small LCD screen. When I input the data in quickly (as in repeat the feed a number of times quickly, which is a real scenario for me) I'm seeing artifacts elsewhere on the screen or it reboots.

I'm pretty certain its a timing issue and I'm causing a race condition or something like that, but I'm at a loss on where to start looking.

Bellow is an excerpt of the Serial section of my script, the total script is about 800 lines, more than happy to post it but it was working fine without the serial.read functions.

Please note I am also printing back out to serial as well, just not displayed in my excerpts below.

I would appreciate any help or guidance to see if there is anything wrong with my code. Again, happy to post full program if needed.

Cheers,
Matt

Sample serial feed would be:

Streaming/10.0.0.1/10.0.0.2\n
//Declare strings and array used in pulling in serial input
String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete
String streamstat = "Stopped";
String hostip = "***.***.***.***";
String broadcastip = "***.***.***.***";
String infoarray[2];


void setup()   {  

  //set serial communication speed
  Serial.begin(9600);
}


void loop(){

  // print the string when a newline arrives:
  if (stringComplete) {
    streamstat = (infoarray[0]); 
    hostip = (infoarray[1]); 
    broadcastip = (infoarray[2]); 
    //reset marker
    stringComplete = false;
  }
  
}


void serialEvent() {
  //Declare Integer
  int i;
  //Reset Intgeger
  i = 0;
  //Start reading in serial stream
  while (Serial.available()) {
    
      //Read in the new byte:
      char inChar = (char)Serial.read(); 
      //Serial.println(inChar);
      
      //Look for delimeter which is /
          if (inChar == '/'){
            
           //Put completed string into array
           infoarray[i] = inputString;
           
           //Reset input string
           inputString = "";
           
           //Increment array integer
           i = i + 1;
           }
           else {
             
            //Add char to the inputstring
            inputString += inChar;
           }
           
     //Wait for the end of line
    if (inChar == '\n') {
      
      //Input last string into the array
      infoarray[i] = inputString;
      inputString = "";
      i = i + 1;
      
      //Set marker for StringComplete
      stringComplete = true;
    } 
  }
}
           infoarray[i] = inputString;

infoarray is any array of 2 Strings . If i is ever greater than 1 you over write other data some where in memory with strange effects. Including random chars and crashes.

Mark

thanks for the quick reply mark, just to make sure I understand you,

I'm setting up my array as infoarray[2] now I had assumed that the array being 0 based that would mean the array should allow 3 indexes or am I use the array incorrectly?

I will only ever be using infoarray[0], [1] and [2] so I thought that was correct?

Should I declare it as infoarray[3]? Or not includ a limit at all? or does setting the array as infoarray[2] not do what I think it does?

Thanks again.
Matt

I don't like the 'String' object. Why don't you use instead array of chars?

const int ledPin = 30;

char str[3];
char count = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  if (Serial.available()) {
    str[count++] = Serial.read();
    if (count == 2) {
       str[count] = '\0';
       count = 0;
       if (strcmp(str, "A0") == 0) {
          Serial.println("code OK.");
          digitalWrite(ledPin, HIGH);
       }
       else {
          Serial.println("wrong code.");
          digitalWrite(ledPin, LOW);
       }
    }
  }
}

This is a little example based in this basic example. Look how I work with strings.

BTW, what you really want to do?

2 if the number of entrys in the array, there indexes are 0 and 1.

Mark

pazu:
thanks for the quick reply mark, just to make sure I understand you,

I'm setting up my array as infoarray[2] now I had assumed that the array being 0 based that would mean the array should allow 3 indexes or am I use the array incorrectly?

I will only ever be using infoarray[0], [1] and [2] so I thought that was correct?

Should I declare it as infoarray[3]? Or not includ a limit at all? or does setting the array as infoarray[2] not do what I think it does?

Thanks again.
Matt

I missed a critical bit in the documentation for arrays:

Note that when declaring an array of type char, one more element than your initialization is required, to hold the required null character.

So I increased it to 3 and it now seems better, I've also edited the loop to stop at 3 and ignore anything else, seems to be more stable, but if I still send a lot of commands it still corrupts and locks up after a while?

Current code is:

void serialEvent() {
  //Declare Integer
  int i;
  //Reset Intgeger
  i = 0;
  //Start reading in serial stream
  while (Serial.available()) {
    
      //Read in the new byte:
      char inChar = (char)Serial.read(); 
      //Serial.println(inChar);
      
      //Look for delimeter which is /
          if (inChar == '/'){
            
             //Put completed string into array
             if (i <= 2){
             infoarray[i] = inputString;
           
              //Reset input string
               inputString = "";
           
               //Increment array integer
               i = i + 1;
             }
           }
           else {
             
            //Add char to the inputstring
            inputString += inChar;
           }
           
     //Wait for the end of line
    if (inChar == '\n') {
      
      //Input last string into the array
      if (i <= 3){
      infoarray[i] = inputString;
      }
      inputString = "";
      i = i + 1;
      
      //Set marker for StringComplete
      stringComplete = true;
      
    } 
  }
}

luisilva:
I don't like the 'String' object. Why don't you use instead array of chars?

const int ledPin = 30;

char str[3];
char count = 0;

void setup()
{
 Serial.begin(9600);
 pinMode(ledPin, OUTPUT);
}

void loop() {
 if (Serial.available()) {
   str[count++] = Serial.read();
   if (count == 2) {
      str[count] = '\0';
      count = 0;
      if (strcmp(str, "A0") == 0) {
         Serial.println("code OK.");
         digitalWrite(ledPin, HIGH);
      }
      else {
         Serial.println("wrong code.");
         digitalWrite(ledPin, LOW);
      }
   }
 }
}



This is a little example based in [this](http://www.arduino.cc/en/Tutorial/Dimmer) basic example. Look how I work with strings. 

BTW, what you really want to do?

Hi luisilva, I did originally try with char but I couldn't get it working correctly. What is the issue/major difference with char vs string? Will have a good look at this example though, cheers.

In regards to your other question, this is part of a video streaming solution with GPS, weather station info that i'm building, it couples with a Raspberry Pi which will be doing the video streaming. Basically the Arduino is handling the sensors and displaying config data back from the raspberry pi (IP, whether the stream is running and the repeater IP for the video stream)

Hi luisilva, I just tried this in my loop code but it doesn't seem to pick up anything from serial?

   //Declare Integer
  int i;
  //Reset Intgeger
  i = 0;
 if (Serial.available()){

   //while (Serial.available()) {
   //Read in the new byte:
       char inChar = (char)Serial.read(); 
      
      //Look for delimeter which is
          if (inChar == '/'){
            if (i == 1){
              streamstat = inputString;
              inputString = "";
              i = i + 1;
            }
             else if (i == 2){
              hostip = inputString;
              inputString = "";
              i = i + 1;
            }
             else if (inChar == '\n'){
              broadcastip = inputString;
              inputString = "";
              i = i + 1;
            }
          }
          
             else {
             
            //Add char to the inputstring
            inputString += inChar;
           }
         

 }

Only with the information you give, I can't understand what is the problem. I don't see the variable definition, the function etc. If you post more code I can try to understand what you have wrong.

Sorry, full excerpt relevant to this function is:

char str[3];
char count = 0;

//Declare strings and array used in pulling in serial input
String streamstat = "Stopped";
String hostip = "***.***.***.***";
String broadcastip = "***.***.***.***";


void setup()   {  

  //set serial communication speed
  Serial.begin(9600);
}



void loop(){
 //Declare Integer
  int i;
  //Reset Intgeger
  i = 0;
 if (Serial.available()){

   //while (Serial.available()) {
   //Read in the new byte:
       char inChar = (char)Serial.read(); 
      
      //Look for delimeter which is
          if (inChar == '/'){
            if (i == 1){
              streamstat = inputString;
              inputString = "";
              i = i + 1;
            }
             else if (i == 2){
              hostip = inputString;
              inputString = "";
              i = i + 1;
            }
             else if (inChar == '\n'){
              broadcastip = inputString;
              inputString = "";
              i = i + 1;
            }
          }
          
             else {
             
            //Add char to the inputstring
            inputString += inChar;
           }
         

 }
}

I don't see that you are using char str or count variables.

Take a look to this thread where the user are doing something like this but only using C strings.