Pages: [1]   Go Down
Author Topic: Problem reading serial data (Arduino to Arduino)  (Read 2491 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I have two Arduino UNOs communicating (one way) via serial (xBee). They communicate perfectly fine until I add a delay to the receiving Arduino code. I need to find a bulletproof way of receiving the correct integers in the correct order. Right now I get some good and some bad data after adding a delay to the code.

The Arduino sender code:

Code:
// Dummy values to send over serial
int value1 = 10;
int value2 = 100;
int value3 = 1000;

void setup(){
  Serial.begin(9600);
}

void loop(){
  sendData(value1, value2, value3);
}

void sendData(int value1, int value2, int value3){
  Serial.print('H');             // 'H' defines start of transfer
  Serial.print(value1,DEC); // First value to send
  Serial.print(",");            // Comma-separated
  Serial.print(value2,DEC);
  Serial.print(",");
  Serial.print(value3,DEC);
  Serial.print(",");        
}

The Arduino receiver code:

Code:
int value1, value2, value3 = 0;

void setup(){
  Serial.begin(9600);
}

void loop(){
  // delay to simulate other code that will be running
  delay(500);
  Serial.println("0.5 sec");
  readData();
}

void readData(){
  while(Serial.available()){
    // Serial.find is supposed to read from the serial buffer till it hits "H"
    Serial.find("H");
    // parseInt reads the first number it encounters (long) until it hits a comma
    value1 = Serial.parseInt();

    Serial.find("I");
    verdi2 = Serial.parseInt();  

    Serial.find("J");
    verdi3 = Serial.parseInt();  

    Serial.println(value1);
    Serial.println(value2);
    Serial.println(value3);
    
    break;
  }
}

If I remove the delay(500) part of the code the data received is fine. The console prints:

0.5 sec
10
100
1000


However as soon as I add a delay (of any length) the data is sometimes fine and sometimes messed up:

0.5 sec
10
100
1000
0.5 sec
0
1000
10000
0.5 sec
10
1100
100
0.5 sec
10
100
1000
0.5 sec
10
1
-26008


I have no idea why the data received is fine without a delay and is basically unreliable as soon as there is a delay in the code.
I have read through and tried several ways of sending and receiving data as described in "Arduino Cookbook 2. edition". They all have this same problem.

In the example I added here I experimented with Serial.parseInt() and serial.find() so I am not sure if I have used them correctly.

Any ideas on how to create a robust and reliable code for receiving serial data?

 gb smiley


Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 642
Posts: 50397
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Right now I get some good and some bad data after adding a delay to the code.
Don't use delay(). There are alternatives for making things happen on a periodic basis. See the blink without delay example.

Your sending code is not sending I and J that the receiver is looking for. Why not?

Your sender is sending data as fast as possible. Any delay on the receiver is going to cause the serial buffer to fill up, causing lost data.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Your sending code is not sending I and J that the receiver is looking for. Why not?

Oops! I pasted the wrong sender code. The code I am working on is sending I and J as well.

Quote
Your sender is sending data as fast as possible. Any delay on the receiver is going to cause the serial buffer to fill up, causing lost data.

I can live with 10-15 complete transmissions per second from the sender Arduino if that helps. About the serial buffer I had the impression that using while(Serial.available()) would flush the buffer so I would only receive fresh data. I have seen references to it as an alternative to Serial.flush() which used to accomplish the same thing (in older versions of Arduino). If this is not the case then do you have any suggestions on how to accomplish this?

Quote
Don't use delay(). There are alternatives for making things happen on a periodic basis. See the blink without delay example.
In the final receiver code I will not use delay(). However there will be a lot of other code consuming processing resources and I am using delay() in this code to simulate that behavior. This is the core of the problem I am having with receiving serial data - the data is unreliable as soon as it is only read on a periodic basis. If I read it constantly the data is fine, if I don´t the data is mangled.

I can´t find any answers on this online so it does not seem like a common problem. I am just so confused by this as (in my opinion) the code should search for a certain character and then print whatever numbers comes after it. But it doesn´t.  smiley-confuse
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 642
Posts: 50397
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
About the serial buffer I had the impression that using while(Serial.available()) would flush the buffer so I would only receive fresh data. I have seen references to it as an alternative to Serial.flush() which used to accomplish the same thing (in older versions of Arduino). If this is not the case then do you have any suggestions on how to accomplish this?
Whether the while loop accomplishes what you want, or not, depends on what is in the body of the while loop.

Dumping random amounts of unread data, though, doesn't really seem like the best idea, does it?

Either implement handshaking, so the sender doesn't send data until the receiver is ready, or be prepared to receive data as fast as it arrives, which means NO delay()s.

Quote
This is the core of the problem I am having with receiving serial data - the data is unreliable as soon as it is only read on a periodic basis. If I read it constantly the data is fine, if I don´t the data is mangled.
Because the serial buffer fills up while you are diddling around, and unknown amounts of data are silently discarded. See the comment above about handshaking.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Dumping random amounts of unread data, though, doesn't really seem like the best idea, does it?

For this particular application it is essential that the data is as fresh as possible so I only care about the lastest data.

Quote
Either implement handshaking, so the sender doesn't send data until the receiver is ready, or be prepared to receive data as fast as it arrives, which means NO delay()s.

OK. Handshaking it is then. I thought I could get away with one-way communication but you have proven me wrong.

Thank you  smiley
Logged

Rome, Italy
Offline Offline
Sr. Member
****
Karma: 20
Posts: 442
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Or use a different protocol: I2C is particularly good for sending small amounts of data fast and reliably. It is based on a request/response paradigm so you don't have to implement any handshaking function yourself.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 503
Posts: 19095
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Right now I get some good and some bad data after adding a delay to the code.

Don't use delay?

http://www.gammon.com.au/serial
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@Spatula Thanks for the tip. We are already using I2C for other purposes so it seems better to use serial. Will look into using I2C for communication in other projects.

@Nick Thank you for the informative link. For now I have written a handshake code that seems to work whatever delays I throw at the sender or receiver. I will come back to your site and implement some of your strategies if my code ends up failing.
Logged

Pages: [1]   Go Up
Jump to: