Two way serial communication between Arduinos using SerialTransfer.

Hello

I'm trying to wrap my head around bi-directional serial communication. I tried to include that functionality in a project, and i used the SerialTransfer library so that i could easily send Stucts or Arrays between two Arduinos.
That didn't work as one of the boards would stop receiving after 1-2 loops but it would continue to transmit to the other one. The other board would continue to transmit and receive normally.

In order to figure it out, i wrote this oversimplified code, that's supposed to work both ways. It creates two structs containing three ints each. One is sent over to the other after it's filled with random zeros or ones and vice-versa. I'm using the zeros and ones of the received structs to blink three LEDs on both ends. The system works for 1-2 minutes and after that, one of the Arduinos (random one), stops receiving and stays with the LEDS of it's last state on. The other one continues to transmit/receive as expected (I left it untouched for over two hours).

It's obvious that i'm doing something very wrong, but every tip to help me understand how the "uninterrupted serial two way communication" is supposed to work, is greatly appreciated.

*Note that in my first project's code there is no delay(), maybe that's why it fails so fast?

#include "SerialTransfer.h"
SerialTransfer stream;

struct msg{  //
  int led1=0;
  int led2=0;
  int led3=0;
  };
msg TXdata;
msg RXdata;

void setup() {
  Serial.begin(115200);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  stream.begin(Serial);
}
void loop() {
TXdata.led1=random(0,2);
TXdata.led2=random(0,2);
TXdata.led3=random(0,2);


sndtx();
recrx();
delay(500);

}

void sndtx(){
  stream.txObj(TXdata, sizeof(TXdata));
  stream.sendDatum(TXdata);
  Serial.flush();
}

void recrx(){
  if(stream.available()){
    stream.rxObj(RXdata);
  }
  digitalWrite(5,RXdata.led1);
  digitalWrite(6,RXdata.led2);
  digitalWrite(7,RXdata.led3); 
}

Any kind of delay() in the main loop causes problems for all communications libraries.

The routine that reads the rx serial buffer needs to be called many times per second otherwise it will overflow and the data will be corrupted.

Ok

I removed the delay() and i used millis. Keep in mind that both the arduinos are running the same code and delaying reading also means that writting is delayed too for the same amount of time.

With the millis flashing the leds instead of a delay in the loop, both the arduinos fail after 3-4 seconds now.

#include "SerialTransfer.h"
SerialTransfer stream;
unsigned long previousMillis = 0;
const long interval = 500;
struct msg{  //
  int led1=0;
  int led2=0;
  int led3=0;
  };
msg TXdata;
msg RXdata;

void setup() {
  Serial.begin(115200);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  stream.begin(Serial);
}
void loop() {
TXdata.led1=random(0,2);
TXdata.led2=random(0,2);
TXdata.led3=random(0,2);

sndtx();
recrx();
leds();
//delay(500);

}
void sndtx(){
  stream.txObj(TXdata, sizeof(TXdata));
  stream.sendDatum(TXdata);
  Serial.flush();
}

void recrx(){
  if(stream.available()){
    stream.rxObj(RXdata);
  }
}

void leds(){
  unsigned long currentMillis=millis();
  if (currentMillis - previousMillis >= interval) {
  previousMillis = currentMillis;
  digitalWrite(5,RXdata.led1);
  digitalWrite(6,RXdata.led2);
  digitalWrite(7,RXdata.led3); 
}
}

Mission half accomplished.

You can now reliably receive messages but as a side effect you are also sending hundreds or thousands of messages per second so neither Arduino can cope with the flood of data.

To do two tasks that operate at different time scales you need the code in the "blink without delay" example

Replace the LED on/off code in the example with your sndtx() function call.

mikb55 thank you very much for your input.

I removed the call of the sndtx() function from my loop and now i'm calling the sndtx() from inside the leds() function. So it gets executed every time the leds turn ON/OFF (every 500ms) with a non-blocking delay.

This seems to be a working example now, with three leds flashing in a random combination every 500ms.

#include "SerialTransfer.h"
SerialTransfer stream;
unsigned long previousMillis = 0;
const long interval = 500;
struct msg{  //
  int led1=0;
  int led2=0;
  int led3=0;
  };
msg TXdata;
msg RXdata;

void setup() {
  Serial.begin(115200);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  stream.begin(Serial);
}
void loop() {
TXdata.led1=random(0,2);
TXdata.led2=random(0,2);
TXdata.led3=random(0,2);

//sndtx();
recrx();
leds();
//delay(500);

}
void sndtx(){
  stream.txObj(TXdata, sizeof(TXdata));
  stream.sendDatum(TXdata);
  Serial.flush();
}

void recrx(){
  if(stream.available()){
    stream.rxObj(RXdata);
  }
}

void leds(){
  unsigned long currentMillis=millis();
  if (currentMillis - previousMillis >= interval) {
  previousMillis = currentMillis;
  sndtx();
  digitalWrite(5,RXdata.led1);
  digitalWrite(6,RXdata.led2);
  digitalWrite(7,RXdata.led3); 
}
}

I have some questions though, for anyone willing to answer any them.

1. Why does the code with the delay() fail and why does it fail on only one of the Arduinos while the other one keeps working as expected?
Both of them try to send and read data every couple of hundred ms so there is not such a big flood of data.

2. Are there two distinct buffers for Serial read and Serial Write, or is there just one serving both purposes?

3. In my final project i would like to have a "real time" constant bi-directional stream of data. A small struct consisting of 2-3 floats plus 2-3 ints on each side.
Is that technically possible? Or would i be better off, having Arduino1 constantly transmitting and Arduino2 transmitting back at set intervals?

4. I thought that overfloat problems would be avoided by using the Serial.flush() command in my transmitting code. I was obviously wrong, but is there a short answer why?

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.