Functions in Arduino Programming
Functions are blocks of code that are isolated in a way that gives the larger code a modular structure. As your sketch grows in complexity, it is almost always a good idea to use functions to make your code more modular, and therefore easier to maintain. You may also find that functions developed in one application can be reused in other applications.
Table of contents
Example: Read a sensor
A Simple Task
Here is a bare bones function that uses the built-in analogRead
function to
return an integer value corresponding to the voltage on a pin with analog-to-digital
capability.
int sensorInput(int channel) {
int r = analogRead(channel);
return(r);
}
This function would be used with the following line elsewhere in the Arduino sketch
int v = sensorInput(A3);
which uses sensorInput
to read the value on pin A3
.
The sensorInput
function doesn’t really simplify the code because the single line
int v = analogRead(A3);
would just as easily obtain the same result.
Add Averaging
Consider a slightly more complicated example. Suppose to reduce the noise on
an analog reading, you wanted to compute the average of several readings. The
sensorInputAve
function does the work
float sensorInputAve(int channel, int nreadings) {
int i,r;
float ave, sum;
sum = 0.0;
for ( i=1; i<=nreadings; i++ ) {
r = analogRead(channel);
sum += r
}
ave = sum/float(nreadings);
return(ave);
}
With sensorInputAve
available, you can replace
int v = sensorInput(A3);
with
int v = sensorInputAve(A3);
in the main code and achieve a better result without littering the main code with the several lines required to compute the average.
The preceding examples demonstrate some of the advantages of using functions
- Isolating blocks of code that perform detailed tasks, which
- Makes the main part of your code more compact and easier to read. Those advantages amount to the benefits of hiding details.
Other significant advantages of using functions are
- Reusing code
- Reducing the length of the main program, for example, if you had to read multiple sensors
- Providing a way to upgrade the code without (usually) disturbing the main code.
Settle and Slow Down
As an example of the benefits of upgrading, consider this modified version of
the sensorInputAve
function.
float sensorInputAveStable(int channel, int nreadings) {
int i,r,waitTime=10;
float ave, sum;
r = analogRead(channel); // Throw away 1st reading to allow channel to settle
sum = 0.0;
for ( i=1; i<=nreadings; i++ ) {
wait(waitTime); // Add slight delay to slow down reading rate
r = analogRead(channel);
sum += r
}
ave = sum/float(nreadings);
return(ave);
}
This function adds two features that, in some situations, increases the stability of an analog input reading. Before any readings are kept, the function makes a reading that might cause the analog channel to settle at a more stable value. Then, inside the loop, a slight delay – in this case 10 milliseconds – is introduced to spread the readings out over a longer period of time. This might be useful if the signal were fluctuating slowly.
Whether or not the changes introduced in sensorInputAveStable
make a difference
in a particular application, the point of the example is to show that the body
of the function can be improved without necessarily affecting the way that function
is called. To take advantage of the changes, the user would replace
int v = sensorInputAve(A3);
with
int v = sensorInputAveStable(A3);
in the calling code. Of course, we could also have just changed the code
in sensorInputAve
and then no change to the calling code would be necessary.
Function definition
Functions must have the following components
- Type
- Name
Functions can also have the following useful, but optional, components
- Input arguments
- Return values
Input Parameters
Input parameters must have a type and a name. In the following example, the
input arguments are v1
and v2
, and both are of type int
.
int add_two(int v1, int v2) {
int r = v1 + v2;
return(r);
}
Suppose instead we wanted to add two floating point values. We would need to change the input parameter types and return types. Here is a function that adds two floats and returns the result as a float.
float add_twof(float v1, float v2) {
float r = v1 + v2;
return(r);
}
Return Values
In the preceding example, add_two
, the function type is int
, which means that
when the function ends, an integer value is returned to the line where the function
was called. Similarly, the add_twof
function returns a floating point value.
Notice that in both the add_two
and add_twof
functions, the internal value v
is declared to be the same