Language: EN

estructuras-puerto-serie-arduino

Sending an Object or Structure via Serial Port in Arduino

We have had several posts delving into the advanced use of the serial port in a processor such as Arduino. We have seen how to send and receive data in the form of bytes, and how to apply it to send and receive identical elements in an array. In this post, we will generalize the concept to send or receive an object or structure via the serial port.

Before we get into the code, let’s explain why we are interested in sending and receiving an object or a structure via the serial port, putting it into context. It is common for us to do a project in which we need two or more processors to communicate, and in which we can define the behavior of both the transmitter and the receiver (it is not a communication imposed on us). For example, controlling a vehicle from a mobile phone or a robotic arm from a computer.

We need the processors to exchange certain information, which depends on the project we are working on. To do this, we define one or more messages that contain this data and that can consist of any grouping of other basic variables or objects.

In addition, as a general rule, we are interested in the messages being sent and received in full and, after verifying that the message is correct, executing an action with the data.

If we define a structure that contains our message, encoded in a consensual manner in the transmitter and receiver, and send the structure via the serial port in the form of bytes, the message is sent and received directly in a simple way, without the need for intermediate conversions or processing.

Remember that different processors may use a different number of bytes to represent basic types, in which case we will have to take it into account in the transmitter or in the receiver.

How complicated is this “pro” way of communication? Interestingly much simpler than dealing with texts, dividing files by commas, and converting variables.

Sending a structure via the serial port is as simple as,

void sendStructure(byte *structurePointer, int structureLength)
{
    Serial.write(structurePointer, structureLength);
}
sendStructure((byte*)&myStruct, sizeof(myStruct));

Receiving the structure via the serial port is similar, simply.

void recieveStructure(byte *structurePointer, int structureLength)
{
    Serial.readBytes(structurePointer, structureLength);
}
recieveStructure((byte*)&myStruct, sizeof(myStruct));

Example of sending a structure via serial port

Simple, right? Let’s see it in a hypothetical example in which we send the position of a servo to a robot, and the time at which we want the movement to occur.

The code for the transmitter would be as follows,

struct servoMoveMessage
{
   int  servoNum;
   int positionGoal;
   float interval;
};
 
struct servoMoveMessage message;

void sendStructure(byte *structurePointer, int structureLength)
{
    Serial.write(structurePointer, structureLength);
}

void setup()
{
  Serial.begin(9600);
  
  message.servoNum = 10;
  message.positionGoal = 1200;
  message.interval = 2.5;  

  sendStructure((byte*)&message, sizeof(message));
}

void loop() 
{
}

And the code for the receiver

struct servoMoveMessage
{
   int  servoNum;
   int positionGoal;
   float interval;
};
 
struct servoMoveMessage message;

void recieveStructure(byte *structurePointer, int structureLength)
{
  if(Serial.available() < sizeof(message)) return;
  Serial.readBytes(structurePointer, structureLength);
}

void setup()
{
  Serial.begin(9600);
  recieveStructure((byte*)&message, sizeof(message));
}

void loop() 
{
}

Of course, we can still improve the process a lot. For example, we can establish mechanisms to verify that the received data is correct (frame delimiters, checksums), a watchdog. We will see all of this in upcoming posts.

Download the code

All the code from this post is available for download on Github. github-full