4.0 Structuring Code with Functions and Data
Well-structured code is maintainable, reusable, and significantly easier to debug. As sketches grow in complexity, it becomes essential to move beyond a single block of code in the loop() function. Functions, arrays, and strings are the primary tools in the Arduino environment for achieving this organization, allowing you to create modular code and manage complex data sets efficiently.
4.1 Functions
A function is a self-contained segment of code designed to perform an individual task. By breaking a large program into smaller, specialized functions, you gain several advantages:
- Organization: Functions help conceptualize the program by separating different tasks.
- Code Reuse: A function can be called multiple times from different parts of your sketch, eliminating redundant code.
- Reduced Errors: By codifying an action in one place, you only need to debug it once. Changes or fixes only need to be applied in one location.
- Smaller Sketch Size: Reusing code through functions often results in a more compact and efficient program.
- Improved Readability: Functions with descriptive names make the code easier to read and understand.
There are two common ways to declare a function in an Arduino sketch:
- Define the entire function before setup() and loop(): The simplest method is to write the complete function definition above the point where it is first called.
- Use a function prototype: You can declare a prototype of the function before setup(), which tells the compiler the function’s name, return type, and parameters. The full function definition can then be placed anywhere else in the file, typically after the loop() function.
Method 1: Full Definition Before Call
int sum_func (int x, int y) // function declaration
{
int z = 0;
z = x+y ;
return z; // return the value
}
void setup()
{
// Statements
}
void loop()
{
int result = 0;
result = sum_func (5, 6); // function call
}
Method 2: Using a Function Prototype
int sum_func (int , int); // function prototype
void setup()
{
// Statements
}
void loop()
{
int result = 0;
result = sum_func (5, 6); // function call
}
int sum_func (int x, int y) // function declaration
{
int z = 0;
z = x+y ;
return z; // return the value
}
4.2 Arrays
An array is a collection of variables of the same type that are stored in a consecutive group of memory locations. Each element in the array is accessed via a common name and a numerical index (or subscript). This structure is ideal for managing lists of related data, such as sensor readings or LED pin numbers.
In Arduino (as in C/C++), arrays use zero-based indexing, meaning the first element is at index 0, the second at index 1, and so on. The last element is at an index one less than the size of the array.
The syntax for declaring an array is: type arrayName [ arraySize ];
Example 1: Declaring and Initializing an Array with a Loop This example declares a 10-element integer array and uses a for loop to initialize each element to 0.
int n[10]; // n is an array of 10 integers
void loop() {
for (int i = 0; i < 10; ++i) {
n[i] = 0; // set element at location i to 0
}
}
Example 2: Initializing an Array with an Initializer List An array can be initialized at the time of declaration using a comma-separated list of values enclosed in braces.
int n[10] = { 32, 27, 64, 18, 95, 14, 90, 70, 60, 37 };
Example 3: Summing the Elements of an Array Arrays are often used to hold a series of values for a calculation. This code sums the values in a 10-element integer array.
const int arraySize = 10;
int a[arraySize] = { 87, 68, 94, 100, 83, 78, 85, 91, 76, 87 };
int total = 0;
void loop() {
// sum contents of array a
for (int i = 0; i < arraySize; ++i) {
total += a[i];
}
// total will be 849
}
4.3 Strings
Strings are used to store and manipulate text, which is essential for tasks like displaying information on an LCD screen, communicating via the Serial Monitor, or storing user input. Arduino supports two primary types of strings.
4.3.1 Character Arrays (C-style strings)
The first type of string is a simple array of char variables. By convention, C-style strings are null-terminated, meaning the final element of the array is always the null character (\0, which has an ASCII value of 0). This special character signals the end of the string to functions that process it.
Example: Declaring a Character Array
void setup() {
char my_str[] = “Hello”;
Serial.begin(9600);
Serial.println(my_str);
}
void loop() {}
Result:
Hello
The C language library provides several functions for manipulating these string arrays.
| Function | Description |
| strlen() | Returns the length of the string, excluding the null terminator. |
| sizeof() | An operator that returns the total size of the array in memory, including the null terminator. |
| strcpy() | Copies one string into another. |
| strcat() | Appends one string to the end of another (concatenation). |
Warning: When using character arrays, it is critical to not write beyond the bounds of the array. Overrunning the array can corrupt adjacent memory, leading to unpredictable behavior or sketch crashes.
4.3.2 The String Object
The Arduino core library provides a String object, which offers a more powerful and intuitive way to work with text. An object is a construct that contains both data (the text itself) and functions (called methods) that operate on that data.
Example: Using the String Object
void setup() {
String my_str = “This is my string.”;
Serial.begin(9600);
// (1) print the string
Serial.println(my_str);
// (2) change the string to upper-case
my_str.toUpperCase();
Serial.println(my_str);
// (3) overwrite the string
my_str = “My new string.”;
Serial.println(my_str);
// (4) replace a word in the string
my_str.replace(“string”, “Arduino sketch”);
Serial.println(my_str);
// (5) get the length of the string
Serial.print(“String length is: “);
Serial.println(my_str.length());
}
void loop() {}
Result:
This is my string.
THIS IS MY STRING.
My new string.
My new Arduino sketch.
String length is: 22
The String object is much easier to use than a character array, with built-in methods for concatenation, replacement, and other complex operations. However, this convenience comes at a cost. The String object uses more memory and can cause memory fragmentation, which can be a critical issue on resource-constrained microcontrollers like the Arduino UNO. Character arrays, while more complex to manage, offer precise control over memory usage. The choice between them depends on the complexity of your text manipulation needs and the available memory of your target board.
With a solid understanding of how to structure code, the next step is to use that code to interact with the physical world through the Arduino’s input and output pins.