Introduction
When it comes to computer programming (or microcontrollers), the choice of the data structure can turn a complicated problem in a simple solution or VICE VERSA!
The Arduino platform provides in its API a set of composite data types that can be used by the programmer like, for example: Arrays
, Strings
, Structs
, etc. However, sometimes these structures are not enough to solve certain types of problems, then we need seek solutions in external libraries.
In this tip, we demonstrate the use of a well-known data structure between PHP programmers: The Associative arrays, also known as HashMaps or dictionaries. We will see how they can make our lives easier.
Before that, let us remember some basic types of structured data from the Arduino platform ...
Arrays
Arrays or Vectors are data structures that represent a set of variables with the same name, individually identified by an numerical index.
In the Arduino programming language, the arrays have the following characteristics:
- All elements must have the same type.
- The number of elements is immutable.
- The index is a sequential number that starts at 0 (zero) and goes to (N-1), where N is the number of array elements.
Therefore, to declare an array, we need to inform 3 things:
- The array name
- The maximum number of elements it will contain
- The data type of the elements
For example, in the following statement, we're creating an array with three integer elements:
mypin int [] = {2, 4, 8};
Where mypin [0] = 2
, mypin [1] = 4
, mypin [2] = 8
.
Strings
A String
in the Arduino language is a class that represents a set of characters and provides various methods for manipulating texts.
Each character of the String
can be accessed by a numeric index that starts at 0 (zero) and goes to (N-1), where N
is the size of String
.
Example: The following command creates a String
of seven characters with the value "Arduino
":
Board String = "Arduino";
Where:
board.length() = 7 → The size of String
board.indexOf(0) = "A" → First Letter String
board.indexOf ("i") = 4 → Position of the letter "i" in the String
board.toUpperCase () = "ARDUINO" → Turns the letters to upper case
Associative Arrays
It is a type of array where the elements are formed by a key and a value (key-value pairs) in which each key has an associated value. This key can take on any value, including Strings
. The keys are user-defined and stored in the structure. The relationship between the keys and their values is called mapping. Therefore, to find a value, the key is used like search index.
The main advantage in using associative arrays is the ease of performing searches for values, which is more intuitive.
There are some HashMap
s implementations that can be used with the Arduino. We highlight the following frameworks:
- Wiring - An open-source programming framework for microcontrollers
- STL - The Standard Template Library
In this tip, we'll give examples in the Wiring
platform that includes an implementation of HashMaps
developed by Alexander Brevig. You'll need to "import
" the countable.h and hashmap.h files for the libraries folder of Arduino.
Here's an example where we create an associative array with three integer elements with keys of type String
and associated values of integer type:
CreateHashMap (mypin, char *, int, 3);
mypin ["Sensor"] = 2;
mypin ["Led"] = 4;
Mypin ["Buzzer"] = 8;
Notice that, in this example, the associating of the key "Sensor
" to the value 2
. The advantage of this implementation is that we can identify the first element by your key "Sensor
" or by its index which is 0
(zero).
To better understand these concepts, we'll develop a simple project and solve it in three different ways:
- No Data Structures
- Using Arrays and Strings
- Using Associative Arrays
Case Study
Our project consists of 3 colored LEDs connected to pins 5, 7, 9 and 11 of Arduino, as shown below:
The application will read a String
through the Arduino serial port in an infinite loop. For each value read, the following action is taken:
- If reading = "red" → Red LED Lighting
- If reading = "yellow" → Yellow LED Lighting
- If reading = "green" → Green LED Lighting
- If reading = "blue" → Blue LED Lighting
Sketches
Solution One: No Data Structures
String reading = "";
int redPin = 5;
int greenPin = 7;
int bluePin = 9;
int yellowPin = 11;
void setup() {
Serial.begin(9600);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
pinMode(yellowPin, OUTPUT);
}
void loop() {
reading = readSerial(); ledsOff(); if (reading == "red") {
digitalWrite(redPin,HIGH);
}
else if (reading == "green") {
digitalWrite(greenPin,HIGH);
}
else if (reading == "blue"){
digitalWrite(bluePin,HIGH);
}
else if (reading == "yellow"){
digitalWrite(yellowPin,HIGH);
}
}
String readSerial() {
String retVal = "";
char c;
while(!Serial.available()){ delay(10);
}
while(Serial.available() > 0) { c = Serial.read();
if (c != '\n'){
retVal.concat(c);
}
delay(10);
}
retVal.toLowerCase(); return retVal;
}
void ledsOff(){
digitalWrite(redPin,LOW);
digitalWrite(greenPin,LOW);
digitalWrite(bluePin,LOW);
digitalWrite(yellowPin,LOW);
}
Solution Two: With Arrays and Strings
String reading = "";
int pins[] = {5,7,9,11};
String commands = "red green blue yellow ";
void setup() {
Serial.begin(9600);
for(int i = 0; i < 4; i++){
pinMode(pins[i], OUTPUT);
}
}
void loop() {
reading = readSerial(); ledsOff(); int i = commands.indexOf(reading);
if (i >= 0) {
digitalWrite(pins[(i / 10)],HIGH);
}
}
String readSerial() {
String retVal = "";
char c;
while(!Serial.available()){ delay(10);
}
while(Serial.available() > 0) { c = Serial.read();
if (c != '\n'){
retVal.concat(c);
}
delay(10);
}
retVal.toLowerCase(); return (retVal);
}
void ledsOff(){
for(int i = 0; i < 4; i++){
digitalWrite(pins[i],LOW);
}
}
Solution Three: With Associative Arrays
#include <HashMap.h>
String reading = "";
CreateHashMap(ledPins, String, int, 4);
void setup() {
Serial.begin(9600);
ledPins["red"] = 5;
ledPins["green"] = 7;
ledPins["blue"] = 9;
ledPins["yellow"] = 11;
for (int i = 0; i < ledPins.size(); i++){
pinMode(ledPins.valueAt(i), OUTPUT);
}
}
void loop() {
reading = readSerial();
ledsOff();
if(ledPins.contains(reading)){
digitalWrite(ledPins[reading],HIGH);
}
}
String readSerial() {
String retVal = "";
char c;
while(!Serial.available()){ delay(10);
}
while(Serial.available() > 0) { c = Serial.read();
if (c != '\n'){
retVal.concat(c);
}
delay(10);
}
retVal.toLowerCase(); return retVal;
}
void ledsOff(){
for (int i = 0; i < ledPins.size(); i++){
pinMode(ledPins.valueAt(i), LOW);
}
}
Points of Interest
- The
readSerial
function will wait and read a String
value through the serial port. - The
ledsOFF
function serves to turn off all the LEDs before lighting the LED requested by serial command. - Notice that, by comparing the
loop
function of the 3 solutions, the alternative using associative arrays is much more readable, compact and maintainable. - The Alternative 2 with
arrays
and Strings
has the advantage of not needing to use any external libraries.
Resources
Conclusion
In this tip, we try to show that the choice of appropriate data structures can result in more intuitive and compact programs, facilitating the work of the programmer.
Thank you for reading. See you ...