1

I have two Arduino boards and want to make them communicate with each other over serial. The code I have used for the two boards is almost identical.

  • Every one second the "A" board sends a "ping" message over serial.
  • The "B" board receives the "ping" message and responds with a "pong" one.
  • The "A" board receives the "pong" message and prints it on screen.

Board A - ping code

String inputString = "";         
boolean stringComplete = false;  

void setup() {
  Serial.begin(9600);
  inputString.reserve(200);
}

void loop() {

  Serial.print("ping");

  if (stringComplete) {
    Serial.println(inputString);
    inputString = "";
    stringComplete = false;
  }
  delay(1000);
}

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    inputString += inChar;
    if (inChar == 'g') {
      stringComplete = true;
    }
  }
}

Board B - pong code

String inputString = "";         
boolean stringComplete = false;  

void setup() {
  Serial.begin(9600);
  inputString.reserve(200);
}

void loop() {

  if (stringComplete) {
    Serial.println("pong");
    inputString = "";
    stringComplete = false;
  }
}

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    inputString += inChar;
    if (inChar == 'g') {
      stringComplete = true;
  }
 }
} 

The code seems to work, but not exactly as expected. I initiate the serial monitor of the board "A" and expect to see every one second:

pingpong

Instead I see this:

pingpong

pong

pong

....

which means that the pong message is repeated more than one time per second. But I want the "B" board to transmit the "pong" message only when it receives the "ping" one.

Why is this happening? Is there an error in the code? Is there a detail about the serial protocol which escapes me?

Any thoughts would be appreciated.

  • You should output every log message directed to human-programmer with a prefix like "#" or ... and so in your program you don't interprete any line beginning by a "#" ... – Alexandre Mazel May 22 '15 at 20:20
  • @AlexandreMazel Using a separate port for debugging and communication would be one more solid, less software option? – Paul Mar 15 '16 at 10:10
  • @user3060854 you might even want to make one piece of code, for two devices. And that you can select if it's master or slave by pulling a pin low setting it high. Or with some setting in EEPROM. Or at startup/button. Would be easier to maintain and is quite an usefull trick to learn. – Paul Mar 15 '16 at 10:13
  • @user3060854 if you can hook up some displays and/or buttons, you can actually make them play ping-pong :D (I'm curious to see what you'll make out of this project) – Paul Mar 15 '16 at 10:15
4

The problem is with your protocol and also with how you are using the serial.

You are using the same serial channel both for your communication protocol and for the reporting of the results. What you see the B end sees.

So A sends ping, and when it sees the letter g it responds with pong. You then print that pong to the serial, so end B sees pong. It gets the character g and thinks "That was a ping, I'll respond with a pong", so it does - it sends pong, which you then receive and duly print - starting the sequence over yet again.

You either need to separate out the communication and the reporting, or make your protocol look for the whole string "ping" so it never inadvertently responds to a "pong" when it shouldn't.

Here's a good resource about reading serial strings on the Arduino: http://hacking.majenko.co.uk/reading-serial-on-the-arduino

  • I changed the code accordingly to your answer and works fine. Thank you. – user3060854 May 22 '15 at 17:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.