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

  1. Example: Read a sensor
    1. A Simple Task
    2. Add Averaging
    3. Settle and Slow Down
  2. Function definition
  3. Input Parameters
  4. Return Values

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