2

I'm trying to do something seemingly simple, but I'm running into difficulties. I want to send about 5 separate integers between two Arduinos over software serial. I have written the following, but I rarely get the two numbers on the receiving end - they're usually garbled or in the wrong order. I'm sure that I'm missing something obvious, but I can't work it out no matter how hard I try. Any help would be greatly appreciated.

Sender:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

int val, val2;

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

void loop()
{
  val = 123;
  val2 = 456;
  if(mySerial.read()=='#')
  {
    mySerial.write(highByte(val));
    mySerial.write(lowByte(val));
    delay(3);
  }
  if(mySerial.read() == '~')
  {
    mySerial.write(highByte(val2));
    mySerial.write(lowByte(val2));
    delay(3);
  }
}

Receiver:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

byte val;
byte low, high;

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

void loop()
{
  mySerial.write('#');
  byte h = mySerial.read();
  byte l = mySerial.read();
  int y = word(h, l);
  delay(2);
  mySerial.write('~');
  byte h2 = mySerial.read();
  byte l2 = mySerial.read();
  int z = word(h2, l2);

  Serial.println(y);
  Serial.println(z);
  Serial.println();
}
  • Have you tried doing a loopback test on both ends. That is, disconnect the serial link between the Arduinos and test them one at a time: Connect the Tx to Rx, send some characters and make sure you receive the characters you sent. – sa_leinad Mar 27 '17 at 14:47
  • On your system have you connected the Tx line of one to the Rx line of the other. Ie crossed over the cables? – sa_leinad Mar 27 '17 at 14:48
  • I have had a brief look at your code and you need to add a delay to the Receiver software immediately after you send the '#' and the '~' characters. The delay is needed so the microcontroller has enough time to send the character out of the serial port, have it processed by the other side and then the new data sent back. – sa_leinad Mar 27 '17 at 14:54
  • Thanks sa_leinad. Those extra delays seem to have done the trick and everything is working as it should so far. – VaughanJB Mar 27 '17 at 15:11
0

You need to add a delay to the Receiver software immediately after you send the # and the ~ characters.

void loop()
{
  mySerial.write('#');
  delay(8);    // <<<<<<<< Line added
  byte h = mySerial.read();
  byte l = mySerial.read();
  int y = word(h, l);
  delay(2);
  mySerial.write('~');
  delay(8);    // <<<<<<<< Line added
  byte h2 = mySerial.read();
  byte l2 = mySerial.read();
  int z = word(h2, l2);

  Serial.println(y);
  Serial.println(z);
  Serial.println();
}

The delay is needed so the microcontroller has enough time to send the character out of the serial port, have it processed by the other side and then the new data sent back.

Using 9600 baud, the time for each bit is around 104 microseconds. So a byte of data sent will take about 1.04 milliseconds. One byte sent + processing time + 2 bytes back is about 4 milliseconds. Adding a bit of margin, 8 ms delay would be a good value to use.

Using if (mySerial.Available() > 0) will not work on its own unfortunately, as Matt's answer suggests. What would happen is that you send the first # and then immediately it would check for any data recieved. From the calculation above we know it would take about 4 ms to get data back. So it just skips the if statement and goes onto the 2ms delay and then sending the ~. It then checks if serial is available. By this time the first response 'may' be back, so if it is, it then saves the data into h1 and l1. It then finishes the serial prints and loops back to the beginning. In this time the second response has come back, so after it sends # for the second time, the response to the ~ gets saved into h and l. This will continue forever.

  • 1
    Thanks. I was trying it with smaller delays (about 3ms), which didn't work. I just changed it to 8ms as suggested and it worked perfectly. I've managed to bring that down to 5ms, which seems to be the minimum before it fails. – VaughanJB Mar 29 '17 at 11:34
1

You are being too impatient.

The receiver needs to wait until there is some data available. if (mySerial.Available() > 0). So before every read add that line and it should work.

  • Thanks @Matt. That seems to have cut down on the random numbers somewhat, but I still don't get a reliable stream of data. Often the two values are swapped, for example. Any other ideas? – VaughanJB Mar 27 '17 at 14:46
  • I can't see a reason why the bytes would be swapped. Try slowing it down make the delay between characters 500ms and see if that helps. An alternative would be to send a byte array. – Code Gorilla Mar 27 '17 at 15:29

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.