Simple codes to transfer multiple variables between Arduinos

So after trying for hours i've finally figured out how to send multiple integers and long variables between Arduinos over a serial connection and have written a fairly simple code for both sender and receiver:

Sender

#include <AltSoftSerial.h>

long val = 88888888;
byte valueinbytes[4];

int val2 = 30888;
byte value2inbytes[2];

int val3 = 333;
byte value3inbytes[2];



AltSoftSerial mySerial;


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

}

void loop() {

  //values are split into multiple bytes using bitshift
  
  valueinbytes[0] = val >> 24;          //highest byte stored here
  valueinbytes[1] = val >> 16;
  valueinbytes[2] = val >> 8;
  valueinbytes[3] = val;                //lowest byte stored here

  value2inbytes[0] = val2 >> 8;
  value2inbytes[1] = val2;

  value3inbytes[0] = val3 >> 8;
  value3inbytes[1] = val3;

  //0xAB is the header/start byte and 0xCD the footer
  //So the receiver knows when the packet starts and ends
  //They can be any value but must be defined the same on sender and receiver
  
  byte packet[10] = {0xAB, valueinbytes[0], valueinbytes[1], valueinbytes[2], valueinbytes[3], value2inbytes[0], value2inbytes[1], value3inbytes[0], value3inbytes[1], 0xCD};

  mySerial.write(packet, 10);
  
  delay(50);

}

Receiver

#include <AltSoftSerial.h>

AltSoftSerial mySerial;

long val;
int val2;
int val3;

void setup() {
  Serial.begin(9600);                 //must be the same baudrate
  mySerial.begin(9600);               //must be the same baudrate

}

void loop() {

  if (mySerial.available() > 10 ) {   //wait for 10 bytes in serial buffer

    byte head = mySerial.read();      //read fisrt byte in buffer
    if (head != 0xAB) return;         //check if this byte is the predefined header/start byte - if not return to loop

    byte b0 = mySerial.read();        //read 4 bytes of user data (long)
    byte b1 = mySerial.read();
    byte b2 = mySerial.read();
    byte b3 = mySerial.read();

    byte i0 = mySerial.read();        //read 2 bytes of user data (int)
    byte i1 = mySerial.read();

    byte z0 = mySerial.read();        //read 2 bytes of user data (int)
    byte z1 = mySerial.read();

    byte foot = mySerial.read();      //read the 6th and last byte of the serial buffer
    if (foot != 0xCD) return;         //if this byte does not match the predefined footer then something is wrong with this package

    val = b0;                         //put first byte in long variable
    val <<= 8;                        //shift the bits in the variable by 8 bits to make room for next byte
    val |= b1;                        //put second byte in the long variable
    val <<= 8;                        //shift the bits in the variable by 8 bits to make room for next byte
    val |= b2;                        //put third byte in the long variable
    val <<= 8;                        //shift the bits in the variable by 8 bits to make room for next byte
    val |= b3;                        //put fourth and last byte into long variable


    val2 = (i0 << 8) + i1;

    val3 = (z0 << 8) + z1;

    Serial.println(val, DEC);
    Serial.println(val2, DEC);
    Serial.println(val3, DEC);

  }
}

I tested the codes with the AltSoftwareSerial library on two Arduino nanos and confirmed it working. AltSoftSerial only allows Pin 8 as RX and Pin 9 as TX on Arduino nanos.

Setup:
Sender Pin 9 TX --------> Receiver Pin 8 RX
Sender Pin 8 RX --------> Receiver Pin 9 TX
Common Ground and power via USB for both Nanos

I hope this example is helpful for people looking to reliably transfer variables between Arduinos. :slight_smile:

Learn to use pointers or unions and you won't have to shift bits (1 cycle per bit).

Have you seen Serial Input Basics - simple reliable ways to receive data.

The technique in the 3rd example will be the most reliable. It is what I use for Arduino to Arduino and Arduino to PC communication.

You can send data in a compatible format with code like this (or the equivalent in any other programming language)

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker

...R

@OP

Thank you for you efforts to establish a working UART Communication link between two Arduinos. I have few queries just out of curiosity.

1. You have
(1) long val = 88888888; //(054C5638 in hex); where, val is 32-bit wide.

(2) You have 'valueinbytes[0]' variable, and it is 8-bit wide.

(3) You have done the following operation:

vlaueinBytes[0] = val >> 24;

As a result, val (a 32-bit variable) has shifted to the right by 24-bit positions; you have come up with 00000005 which is still a 24-bit data. Do you think that it will fit in the 8-bit variable 'valueinbytes[0]'? You need only the last 8-bit of 00000005 which is 05. The above operation will, of course, store 05 into the variable -- valueinbytes[0] although you have not asked for it. Do you think that you should tell the compiler explicitly to store only the last 8-bit (last byte) into your target variable. If yes, how do want to do it?

2. You have the following three data items of varying size:

long val = 88888888; //054C5638
int val2 = 30888;       //8140
int val3 = 333;           //014D

3. There are various ways/methods of sending/receiving the data items of Step-2 between two Arduinos. It is good to remain familiar with various methods of doing the same job.
(1) Your method. In this method you are sending 'binary values' and not 'ASCII values'. The 'beginning marker (0xAB)' and the 'end marker (0xCD)' are codes for non-printable characters. There are also no data separators among data items.

(2) @Robin2's Method which is similar to yours; but, it has not split up the data items into their respective bytes as you have done. This methods sends the ASCII values for the digits of your data items. In this method, the 'beginning marker ('<') and the 'end marker ('>')' are printable charcaters. there are data separators (the ,s) among the data items. According to this method, the transmission frame is:

<val,val2,val3>
< is the Beginning marker, and it is equivalent to your 0xAB.
val forms 8 consecutive UART Frames for the data 88888888.
, (comma) is data iitem separator.
and so on...!

Sender Codes: (tested between NANO and UNO)

#include<SoftwareSerial.h>
SoftwareSerial SUART(8, 9); //SRX = DPin-8; STX=DPin-9

long val = 88888888;   //54C5638
int val2 = 30888;   //78A8
int val3 = 333;       //014D

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

void loop()
{
  Serial.print('<'); 
  Serial.print(val); Serial.print(',');
  Serial.print(val2);Serial.print(',');
  Serial.print(val3);Serial.print('>');
  Serial.println();
  //-------------------------------------------
  SUART.print('<');
  SUART.print(val); SUART.print(',');
  SUART.print(val2);SUART.print(',');
  SUART.print(val3);SUART.print('>');
  //------------------------------------
  delay(1000);    //testing
}

Receiver Codes (tested between NANO and UNO)

#include<SoftwareSerial.h>
SoftwareSerial SUART(8, 9);

long val;
int val1;
int val2;
char dataArray[50] = "";
byte valArray[10] = "";
byte val1Array[10] = "";
byte val2Array[10] = "";
int i = 0, j = 0;

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

void loop()
{
  if (SUART.available())
  {
    SUART.readBytesUntil('>', dataArray, 50);
    Serial.print(dataArray);
    Serial.println('>');
    dataItems();
  }
}

void dataItems()
{
  for (i = 0, j = 1; i < 8, j < 9 ; i++, j++)
  {
    valArray[i] =  dataArray[j];
  }
  val = atol(valArray);
  Serial.println(val);
  //-----------------------
  for (i = 0, j = 10; i < 5, j < 15; i++, j++)
  {
    val1Array[i] =  dataArray[j];
  }
  val1 = atoi(val1Array);
  Serial.println(val1);
  //----------------------------
  for (i = 0, j = 16; i < 3, j < 19; i++, j++)
  {
    val2Array[i] =  dataArray[j];
  }
  val2 = atoi(val2Array);
  Serial.println(val2);
  //----------------------------
}

BTW: You may work to see if the receiver codes could be optimized!