Simple code to send a struct between Arduinos using Serial

Prompted by a query elsewhere on the Forum I have created a pair of simple programs to illustrate how a struct can be sent using Serial from one Arduino to another. I used SoftwareSerial on both Arduinos. If you have an Arduino with a spare HardwareSerial port (such as a Mega) it would be better to use it.

Unlike the examples in Serial Input Basics the code in these new examples relies on the fact that the sending program and the receiving program will both use the same struct definition and hence the length of the data being sent will be known to both programs. The examples here also assume the struct will not exceed 60 bytes in length so it plus the start-marker will comfortably fit in the Serial Input Buffer. In my examples the struct being sent is 32 bytes long - the same size as used for I2C by the Wire library and used by the RF24 library for nRF24L01+ transceivers.

These are links to my Arduino to Arduino I2C Tutorial and my Simple nRF24L01+ Tutorial

Sending Program …

//===================
// Using Serial to send and receive structs between two Arduinos

//===================


        // data to be sent
struct TxStruct {
    char textA[16];         // 16 bytes
    int valA;               //  2
    unsigned long valB;     //  4
    byte padding[10];       // 10
                            //------
                            // 32
};

TxStruct txData = {"xxx", 235, 0};

bool newTxData = false;

const byte startMarker = 255;
const byte txDataLen = sizeof(txData);

        // timing variables for sending frequency
unsigned long prevUpdateTime = 0;
unsigned long updateInterval = 500;

#include <SoftwareSerial.h>
SoftwareSerial sendSerial(6,7); // Rx and Tx


//=================================

void setup() {
    Serial.begin(115200);
    Serial.println("\nStarting SerialStructSend.ino\n");

        // set up Serial for communication
    sendSerial.begin(9600); // to match SoftwareSerial on Uno

}

//============

void loop() {

        // this function updates the data in txData
    updateDataToSend();
        // this function sends the data if one is ready to be sent
    transmitData();
}

//============

void updateDataToSend() {

    if (millis() - prevUpdateTime >= updateInterval) {
        prevUpdateTime = millis();
        if (newTxData == false) { // ensure previous message has been sent

            char sText[] = "SendA";
            strcpy(txData.textA, sText);
            txData.valA += 10;
            if (txData.valA > 300) {
                txData.valA = 235;
            }
            txData.valB = millis();
            newTxData = true;
        }
    }
}

//============

void transmitData() {

    if (newTxData == true) {
        sendSerial.write(startMarker);
        sendSerial.write((byte*) &txData, txDataLen);

            // for demo show the data that as been sent
        Serial.print("Sent ");
        Serial.print(txData.textA);
        Serial.print(' ');
        Serial.print(txData.valA);
        Serial.print(' ');
        Serial.println(txData.valB);

        newTxData = false;
    }
}

Receiving program …

//===================
// Using Serial to send and receive structs between two Arduinos
//      the Tx is sending at 500msec intervals
//      it is assumed that this Rx program can loop in less than half that time

//===================


        // data to be received

struct RxStruct {
    char textB[16];         // 16 bytes
    int valC;               //  2
    unsigned long valD;     //  4
    byte padding[10];       // 10
                            //------
                            // 32
};

RxStruct rxData;

bool newData = false;

const byte startMarker = 255;
const byte rxDataLen = sizeof(rxData);

#include <SoftwareSerial.h>
SoftwareSerial recvSerial(6,7); // Rx and Tx


//=================================

void setup() {
    Serial.begin(115200);
    Serial.println("\nStarting SerialStructReceive.ino\n");

        // set up Serial for communication
    recvSerial.begin(9600);
}

//============

void loop() {

    recvStructWithKnownLength();
        // this bit checks if a message has been received
    if (newData == true) {
        showNewData();
        newData = false;
    }
}

//=============

void showNewData() {

    Serial.print("This just in    ");
    Serial.print(rxData.textB);
    Serial.print(' ');
    Serial.print(rxData.valC);
    Serial.print(' ');
    Serial.println(rxData.valD);
}

//============

void recvStructWithKnownLength() {
    static byte recvData[rxDataLen];
    byte rb;
    byte * structStart;
    structStart = reinterpret_cast <byte *> (&rxData);

    if (recvSerial.available() >= rxDataLen + 1 and newData == false) {
        rb = recvSerial.read();

        if (rb == startMarker) {
                // copy the bytes to the struct
            for (byte n = 0; n < rxDataLen; n++) {
                *(structStart + n) = recvSerial.read();
            }
                // make sure there is no garbage left in the buffer
            while (recvSerial.available() > 0) {
                byte dumpTheData = recvSerial.read();
            }

            newData = true;
        }
    }
}

//============

Have fun …

…R

2 Likes