Go Down

Topic: Serial.available() vs. Serial.print() (Read 14865 times) previous topic - next topic

Frogeraie

I have two boards communicating serially through Xbees. On board #1 I have the following code:
Code: [Select]
int inByte = 0;         // incoming serial byte
int outputPin = 13;
void setup()
{
 // start serial port at 9600 bps:
 Serial.begin(9600);
 pinMode(outputPin, OUTPUT);
 }

void loop()
{
 if (Serial.available() > 0) {
   // get incoming byte:
   inByte = Serial.read();
   if (inByte == 'E') {
   digitalWrite(outputPin, HIGH);
   }else if (inByte == 'F') {
   digitalWrite(outputPin, LOW);
   }
  }else{
  Serial.print('H');
 delay(1000);
 Serial.print('L');
 delay(1000);            
 }
}

On board #2 I have the following code:
Code: [Select]
int inByte = 0;         // incoming serial byte
int outputPin = 13;
void setup()
{
 // start serial port at 9600 bps:
 Serial.begin(9600);
 pinMode(outputPin, OUTPUT);
 }

void loop()
{
 if (Serial.available() > 0) {
   // get incoming byte:
   inByte = Serial.read();
   if (inByte == 'H') {
   digitalWrite(outputPin, HIGH);
   }else if (inByte == 'L') {
   digitalWrite(outputPin, LOW);
   }
  }else{
  Serial.print('E');
 delay(2000);
 Serial.print('F');
 delay(2000);            
 }
}

The leds on pin 13 are blinking at the right frequency when delays are short, 100 - 200 msec. For values around 1 sec, as in the case above, only one led blinks - #1 - at about a 2000 msec pulse, #2 is constantly lit.
Maybe my aproach is not the best one to have a board both receiving and sending serial data?
Any suggestions?
Thanks!

PaulS

#1
Jan 23, 2011, 03:10 pm Last Edit: Jan 23, 2011, 03:12 pm by PaulS Reason: 1
Serial data transmission is relatively slow, particularly at 9600 baud. Since the two Arduinos are directly connected, they can communicate MUCH faster than that. Try increasing the baud rate, to the maximum supported speed, 115200. That's 12 times as fast, so will take 1/12th as long.

Also, one of your Arduinos is waiting half as long as the other. The faster one will eventually overflow the serial buffer on the slower one.

Frogeraie

Don't you think it could help to introduce a Serial.flush() somewhere to prevent the overflowing of the serial buffer on the slower Arduino?
I will try to increase the speed.
Thanks.

PaulS

Quote
Don't you think it could help to introduce a Serial.flush() somewhere to prevent the overflowing of the serial buffer on the slower Arduino?

No, I don't. I figure that is the sender thinks the data is important enough to send that it is important enough to receive and process. Whatever needs to be done to ensure that that can happen should be done.

If the receiver can not be made fast enough, the sender and receiver need to implement handshaking, so that the sender doesn't send data until the receiver is ready to process it.

If that can't happen, there is no benefit to calling flush() to dump random amounts of data as opposed to dumping random amounts of data because the receive buffer is full.

I suspect that this is more than just theoretical work on your part. If you fill us in on what that larger picture looks like, perhaps we could be more helpful.

Frogeraie

I set the speed on both Xbees and Arduinos to 115200, there was no change: I could see on the serial monitors (I have the boards hooked up to two different PCs) both sequences of EFEFEF and HLHLHL generated at apparently the right frequencies but only the led on board #1 pulses. If I change the delays on board #2 from 2000 to 500, then it is the led #2 which is blinking. This confirms what you said before:
Quote
The faster one will eventually overflow the serial buffer on the slower one.
.
Now my question is: how to manage not to get this buffer to be overflown?

AWOL

Quote
Now my question is: how to manage not to get this buffer to be overflown?

1) Make sure you read data out faster than it is written in.
2) Implement handshaking. (which is another way of saying 1)  )
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Frogeraie

Alright, here is what I am looking for.
A mobile automata carries an Arduino board #1 with an Xbee module and a PCB with an embedded Atmega. The Atmega drives the motors and controls different sensors, among them an ultrasonic transmitter which is turned on when the Arduino #1 receives an 'A'  and off when it is a 'B' .
Code: [Select]

if (Serial.available()) {
   valUS = Serial.read();
   if (valUS == 'A') {
     digitalWrite(outputPin, HIGH);
   }
   if (valUS == 'B') {
     digitalWrite(outputPin, LOW);
   }
 }

Connected to the PC there is another Arduino board (#2) also with an Xbee, it computes from the ultrasonic receiver signals the time-of-flight th1, i.e., it trigers the US transmitter with an 'A' and then computes the time before receiving an US pulse with a while():
Code: [Select]
Serial.print('A');
 t = micros();
 while (val1 == LOW){
   val1 = digitalRead(inUS1);
   th1 = micros() - t;
}
   Serial.print(th1);
 Serial.print(10, BYTE);
   Serial.print('B');  
 Serial.print(10, BYTE);

This works fine.
Now, I would like the mobile to be able to send a signal to the PC when it encounters an obstacle. So, I would like to add on the Arduino #1 something like this:
Code: [Select]
valMoteur1 = digitalRead(inPin9);
 if(valMoteur1 == HIGH) {
   Serial.print('H');
 }else if(valMoteur1 == LOW){
   Serial.print('I');
 }

and the Arduino #2 will receive these 'H' and 'L' and use them to pass 1 and -1 to the PC:
Code: [Select]
if (Serial.available()) {
   valRF = Serial.read();
   if (valRF == 'H') {
    Serial.println('E');
    Serial.print(1);
    Serial.print(10, BYTE);
   }
   if (valRF == 'L') {
    Serial.println('E');
    Serial.print(-1);
    Serial.print(10, BYTE);
   }

Unfortunately this doesn't work!
As I said in my previous posts I am unable to get both Arduinos to send and receive serial data.

PaulS

Quote
A mobile automata carries an Arduino board #1 with an Xbee module

This is the first mention of another device in the serial data path. It is quite likely that all of your issues involve the XBees, not the serial communication.

Which XBees do you have?

If you replace the two XBees with a pair of wires, connecting TX to RX and vice versa (as well as grounds), do you have the same problem?

Frogeraie

Sorry, you didn't realize I was using Xbees, Although I mentioned it in my first post:
Quote
I have two boards communicating serially through Xbees.

The Xbees I use are the 802.15.4.
I tried to replace them with cables, as suggested by PaulS, to no avail!

PaulS

Quote
The Xbees I use are the 802.15.4

I missed that you were using XBees in the first post. All XBees transmit using the 802.15.4 protocol. There are series 1 and series 2.5 XBees that are used for different purposes. Which do you have?

It doesn't really matter if direction connection does not solve the problem.

Rereading what you want to do, I think I see the problem. You are trying to have the XBees AND the PC communicate with the Arduino using the hardware serial port. It looks like you want to send data to the serial port, from the Arduino, and have the serial port know whether to send the message to the XBee or the PC. That won't work. The serial port is a dumb device. Both the XBee and the PC can be connected to the serial port, and both will see the same incoming and outgoing data.

However, it really looks like you should be using the hardware serial port to talk to the PC and NewSoftSerial to talk to the XBee on another pair of pins. If you are using a shield (probably not with a homemade PCB), that could prove difficult.

Go Up