Arduino Struct syntax lets you to organize related data into a single variable, so you can easily organise information in a group without having lots of variables all over the place. Programs are therefore easier to understand and maintain.
As your programs become more complex you will find that keeping track
of related data becomes a problem. If you create a struct variable you
can group that data in a logical way allowing you to more easily manage
complex programs.
This introduction for using structs with
any Arduino microcontroller, demonstrates how to declare struct variables, and use them in your own examples.
You will find out how structs make your code more organized and readable for handling interconnected information.
A struct (short for "structure") type in C/C++ is a user-defined datatype that allows grouping of multiple variables of different data types together under a single name.
A struct can can contain many variables of any of the of
fundamental data types like integers, floats, characters. You can even
use other types like arrays, pointers etc.
For example, if you want to store information about a person like
their name, their age, and their salary etc. instead of declaring
separate variables, you can create a struct called person and define the
member variables inside it.
In this case you would use variables of type char array i.e. a string, integer, and float respectively. All this information will be contained in one struct element making the code more organized and readable as all the related data for a person is contained in one variable.
To use a struct in Arduino code, you first need to declare the struct type by specifying the member variables it contains. The general syntax for declaring a struct is:
struct struct_name {member1_data_type member1;member2_data_type member2;member3_data_type member3;...};
For example, to store sensor readings from three sensors, we can declare:
struct sensor_readings {int sensor1;int sensor2;int sensor3;};
This declares a new Arduino struct type called sensor_readings with 3 integer
members - sensor1, sensor2, sensor3 to hold the readings from each
sensor.
After declaring the struct type, you need to define variables of that
struct type to use it. Struct variables are declared similar to basic
variable types.
For example, to define a variable called readings of type sensor_readings:
struct sensor_readings readings;
You can also define multiple struct variables at once:
struct sensor_readings readings1, readings2, readings3;
This defines 3 variables - readings1, readings2, readings3 of type sensor_readings to store separate sets of sensor readings.
To access individual members of a struct variable, use the dot (.) operator followed by the member name.
For example, to store readings in the first variable:
readings.sensor1 = 100;readings.sensor2 = 150;readings.sensor3 = 200;
And print the second reading:
Serial.print("Reading 2: ");Serial.println(readings.sensor2);
You can pass Arduino struct type variables to a function in the same way that
you use any other variable argument. The struct variable is passed by
value, meaning a copy of it is passed instead of the original variable.
It means you can pass a lot of data into a function using a single
"struct" variable.
For example, to average the sensor readings:
struct sensor_readings averageReadings(struct sensor_readings readings) {int total = readings.sensor1 + readings.sensor2 + readings.sensor3;struct sensor_readings avg;avg.sensor1 = total/3;avg.sensor2 = total/3;avg.sensor3 = total/3;return avg;}
And call it:
struct sensor_readings avg = averageReadings(readings);
Here are some additional benefits that structs provide for organizing and working with data in Arduino code:
Encapsulation: Structs allow grouping of related data and functions into one block, hiding unnecessary details from the outside. This makes code more organized and maintainable.
Type safety: Defining a struct creates a new customized type. This prevents incorrect assignments like storing an integer in a string member, adding clarity.
Memory efficiency: Structs allow allocation of multiple variables of different types in contiguous memory blocks, reducing memory overhead compared to individual variables.
Scalability: It's easy to add/remove members from a struct as needs change. This makes the code flexible and future-proof compared to separate variables approach.
Readability: Grouping logically related data into a named datatype (e.g. SensorReadings) makes the code more self-documenting and readable compared to individual variables.
Reusability: Structs containing common data can be defined once and reused across programs and libraries, reducing duplication.
Portability: Structs allow sending blocks of related
data over communications with well-defined interfaces, easier than
sending individual variables.
The following sketch shows a simple database example that defines a Person struct with three elements:
So information that is related to a person is stored in a single variable.
The sketch simply prints out details for each person. It then calculates and shows the average age and salary for all of them.
One disadvantage of using a character array is that it is not dynamic
(it is fixed length). If you had a person's name longer than 50
characters, you would need to re-program the application! You could
remove this problem by using dynamic strings but these come with their own problems (see the link).
struct Person {
char name[50]; // Character array to store the name
int age; // Integer to store the age
float salary; // Float to store the salary
};
void printPersonInfo(const char* personName, const Person& person) {
Serial.print(personName);
Serial.println(":");
Serial.print("Name: ");
Serial.println(person.name);
Serial.print("Age: ");
Serial.println(person.age);
Serial.print("Salary: $");
Serial.println(person.salary);
Serial.println();
}
void setup() {
// Start the serial communication at a baud rate of 115200
Serial.begin(115200);
// Create three Person instances and populate their data
Person person1, person2, person3;
strcpy(person1.name, "John");
person1.age = 30;
person1.salary = 45000.0;
strcpy(person2.name, "Alice");
person2.age = 25;
person2.salary = 63500.0;
strcpy(person3.name, "Bob");
person3.age = 33;
person3.salary = 55000.0;
// Calculate the average age and salary
int totalAge = person1.age + person2.age + person3.age;
float totalSalary = person1.salary + person2.salary + person3.salary;
int numPeople = 3;
float averageAge = totalAge / numPeople;
float averageSalary = totalSalary / numPeople;
// Print out the data for each person using the printPersonInfo function
printPersonInfo("Person 1", person1);
printPersonInfo("Person 2", person2);
printPersonInfo("Person 3", person3);
// Print the average age and salary
Serial.print("Average Age: ");
Serial.println(averageAge);
Serial.print("Average Salary: $");
Serial.println(averageSalary);
}
void loop() {
// Empty loop for demonstration purposes
}
This tutorial showed you how to use Arduino struct variables to organize
related data in Arduino code. Structs provide a clean way to manage multiple pieces of
related information as a single unit.
They make code more readable and maintainable by grouping logically connected variables.They provide organization, type safety, efficiency, flexibility, readability and reusability benefits - all of which aid in managing complex interconnected data sets in your Arduino programs.
Written by John Main who has a degree in Electronic Engineering.
Note: Parts of this page were written using poe & chatgpt as a research assistant.
Comments
Have your say about what you just read! Leave me a comment in the box below.
Don’t see the comments box? Log in to your Facebook account, give Facebook consent, then return to this page and refresh it.