Serial - Issues reading and parsing

Been trying for hours to figure out what I’m doing wrong here. I’ve got a Bluetooth module connected to my Android device. My device sends byte data as follows: s25,50e. My end state project will parse these values to drive motors. However, before I am able to get there, I have an issue with basic parsing. I am using the below sketch to troubleshoot my issue. It reads the bytes and stores them into inData. My issue is that when I am viewing the first byte (for testing purposes) in the Serial Monitor I get what I am expecting. However, it stops at 300 iterations. So, I get a value 300 times, then poof, nothing. Serial.Available is no longer > 0 (tested using an else statement previously). It seems to be that some sort of buffer is filling up? I am using an Android device to send the Bluetooth data, and it is sending the data as text s25,50e.

Edit: I noticed that the more info I try to “Serial.Print” to the Serial Montior, the quicker that Serial.Available seems to stop working (=0). i.e. I added Serial.Prints for inData[2] up to [7] and it crapped out sooner?

Any thoughts on what I am doing wrong? I know I am reading bytes, but it is parsing the correct info into the inData array, and I can see the correct values as iterate through the array?

byte inByte;   // Where to store the Bytes read
char inData[16];  // Allocate some space for the Bytes
byte index = 0;   // Index into array; where to store the Bytes
int i=0;

void setup() {
  Serial.begin(9600);       // start serial communication at 9600bps

}

void loop() {

 if(Serial.available() > 0)
  {
    while (Serial.available() > 0)
    {
      if(index < 15) // One less than the size of the array   (note inData was [10] and this call < 9 before 
        {
	    inByte = Serial.read(); // Read a Byte
	    inData[index] = inByte; // Store it
            if (inData[index] == 'e') break;      
	    index++;
        }   
    }

    index = 0;   
 

   switch(inData[0])
    {
      case 's':
        Serial.print("i=");
        Serial.print(i);
        Serial.print(" ");        
        Serial.print(inData[1]);
        Serial.println();
        break;
    }

    i++;
    // clear serialData array
    memset(inData, 0, sizeof(inData));
  }

 delay(50);
}
 if(Serial.available() > 0)
  {
    while (Serial.available() > 0)

The if test is unnecessary.

        Serial.print("i=");
        Serial.print(i);
        Serial.print(" ");        
        Serial.print(inData[1]);
        Serial.println();

If you send "s25,50e". what are you expecting inData[1] to contain?

It should contain '2'.

That code does not illustrate "iterating through the array" and it does not illustrate parsing.

Yes. inData[1] returns 2. However, the issue is, as this data is being send over Bluetooth, Serial.available stops being available after a number of values are returned. Using the below code as an even simpler example, I am sending data like this: 25,50\n. When I run this in the Serial Monitor, I get 25 and 50 returned with the below code, it continues until a point and then the Serial Monitor stops showing values? My Android app shows that data is still being sent over Bluetooth to the Arduino.

void setup() {
  // initialize serial:
  Serial.begin(9600);
}

void loop() {
  // if there's any serial available, read it:
  while (Serial.available() > 0) {

    // look for the next valid integer in the incoming serial stream:
    int firstNum = Serial.parseInt(); 
    // do it again:
    int secondNum = Serial.parseInt(); 

    // look for the newline. That's the end of your
    // sentence:
    if (Serial.read() == '\n') {
     
     


      // print the three numbers in one string as hexadecimal:
      Serial.print(firstNum);
      Serial.print("  ");
      Serial.println(secondNum);
    }
  }
}
  while (Serial.available() > 0) {

There is at least one byte to read. You then proceed to read as many as you want. Fail.

One byte available enables one read. There is no way around that.

I don’t know how parseInt() behaves and the documentation for it is utterly useless. It might do exactly what you need here, but it might not. What happens if you get extra characters (for example \r) not consumed by parseInt(), or a dropped character, or if the read times out or something? Are you sure your code is going to get back in sync with the incoming stream? It’s hard to know, because I don’t know what the incoming stream contains or what parseInt() actually does - but it’s not at all obvious that it will.

My device sends byte data as follows: s25,50e

Is the e the end of packet marker? Be aware that on the sending end you may need to use a delay to prevent sending data faster than it can be processed on the receiving end.

Thx for the tips... I think it may be an issue with my bluetooth send routine on the Android device. I'm sending a text string (and not by bytes), but to be honest, I'm a bit green on that part. Since I've gotten the above to samples (one of which is pretty much verbatim from Arduino.cc) to receive and show data, I'm going to have to look deeper at how I am sending the data as it seems that at some pt, it just stops sending. Problem is my Android procedures don't show any errors...

How many time are we going to cover this topic? Thanks Nick G for providing that awesome example for handling multiple character with serial communications.
Don

How many time are we going to cover this topic?

At least once more. Today.

No love in the house eh guys... I tried Nick's example, and it too parsed data like the rest of the examples I posted, but it too also craps out after so many iterations through the loop. Serial.Available becomes 0. Not saying there is anything wrong with his code, or the examples I posted above. Just trying to understand what I am missing, so go easy please. It's either the serial buffer is not getting cleared out on the Arduino side, or my Android device stops sending the data but does not throw any errors. Is it possible to fill up the Serial buffer using Nick's example? ie. is it possible for the BT data to come over too quick? I've got my data sending at (what I think is) a reasonable speed of 200ms between packets.

Nicks code wasn't written for your problem. You should read it figure out whats happening and apply it to solve your problem. Try it yourself you have to experiment..

If your data packet is delimited by a e (you failed to answer the question concerning this), then you might try substituting an e for the comma , in the below code.

//zoomkat 3-5-12 simple delimited ',' string parce 
//from serial port input (via serial monitor)
//and print result out serial port
// CR/LF could also be a delimiter

String readString;

void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 1.0"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like wer,qwe rty,123 456,hyre kjhg,
  //or like hello world,who are you?,bye!,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >1) {
        Serial.println(readString); //prints string to serial port out
        //do stuff with the captured readString 
        readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

@zoomkat, thx for the example. Tried it and substituted the 'e' and, as all the other examples it too worked, but again crapped out in the serial window after a number of values showed. Maybe I am missing something, but it seems that everyone thinks that I am not getting results from these samples. I am. The issue is that the serial monitor stops reporting them as Serial.Available is no longer true.

I modified the sample above by adding a counter. The serial window stops about about ~180 iterations each time. Below is a dump of the last few values passed:
178 sX=97,Y=-7
179 sX=97,Y=-7
180 sX=97,Y=-7
181 sX=97,Y=-7
182 sX=97,Y=-7
183 sX=97,Y=-7
184 sX=97,Y=-7
185 sX=97,Y=-7
186 sX=97,Y=-7
187 sX=97,Y=-7

//zoomkat 3-5-12 simple delimited ',' string parce 
//from serial port input (via serial monitor)
//and print result out serial port
// CR/LF could also be a delimiter

String readString;

void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 1.0"); // so I can keep track of what is loaded
}
int i;
void loop() {

  //expect a string like wer,qwe rty,123 456,hyre kjhg,
  //or like hello world,who are you?,bye!,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == 'e') {
      if (readString.length() >1) {
        Serial.print(i);
        Serial.print("  ");
        Serial.println(readString); //prints string to serial port out
        //do stuff with the captured readString 
        readString=""; //clears variable for new input
      }
       i++;
    }  
    else {     
      readString += c; //makes the string readString
    }
    
  }

}
String readString;

Please note that, at present, the String library has bugs as discussed here and here.

In particular, the dynamic memory allocation used by the String class may fail and cause random crashes.

I recommend reworking your code to manage without String. Use C-style strings instead (strcpy, strcat, strcmp, etc.), as described here for example.

Alternatively, install the fix described here: Fixing String Crashes

deejayspinz:
No love in the house eh guys…

We love everyone on the forum. :wink:

Well, some more than others.

PaulS patiently answers lots of questions every day. Sometimes though you sense the smoke coming out of his ears. :slight_smile:

Hi Nick. I was just trying that example. Below is the code I am using. Same result as the others I’ve tried. At some point, Serial.Available becomes false. Also note that I’ve tested my Android app sending to a BT dongle on a laptop and using Putty to view the data. Left it running for over 5 minutes and the data stream never stopped, so I am fairly certain that my Android app is not crashing and is still sending the data. Again, it seems to me that some sort of buffer is filling up? I’ve read the docs on Serial and still don’t understand how it works. If I am sending BT data to the Arduino does Serial every ‘fill up’? I’ve seen a 64 byte limit. If so, how can I ensure it is clear or flushed often enough? Most of the samples I see just read from the Serial and do something with the data without every having to ‘tend’ to it. Or they seem that way.

Thx everyone for your help.

#define SOP 's'
#define EOP 'e'

bool started = false;
bool ended = false;

char inData[20];
byte index;
int xVal=0, yVal=0;




void setup()
{
   Serial.begin(9600);
   // Other stuff...

}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 19)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet



        char *name = strtok(inData, "=");
        while(name)
        {
          char *valToken = strtok(NULL, ",");
          if(valToken)
          {
             int val = atoi(valToken);
             if(strcmp(name, "X") == 0)
                xVal = val;
             else if(strcmp(name, "Y") == 0) 
             yVal = val;
             // More else if's go here
          }
        
          name = strtok(NULL, "=");
        }
       
     Serial.print("Xvalue= ");
     Serial.print(xVal);
     Serial.print("  Yvalue= ");
     Serial.println(yVal);     

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
 
}

What does your debugging show? Or if you can't see it, may as well remove it.

The incoming data is caught by an interrupt and place in an internal buffer (64 bytes sounds right). If you promptly remove it (as you seem to be doing) it won't fill up.

I can't see anything obviously wrong.

If you have a second Arduino you might want to shoot some debugging out SPI or I2C and keep track of what is happening.

deejayspinz:
Edit: I noticed that the more info I try to "Serial.Print" to the Serial Montior, the quicker that Serial.Available seems to stop working (=0). i.e. I added Serial.Prints for inData[2] up to [7] and it crapped out sooner?

It takes time to send the data out, and if you stuff the buffer faster than it can send it, it hangs and waits for the buffer to empty. During that time the incoming buffer might fill up before you get a chance to remove its contents. Try keeping the debugging short.

The issue is that the serial monitor stops reporting them as Serial.Available is no longer true.

Doesn't that sound like something on the sending end has failed?