Arduino Functions Basics
Introduction
Functions are one of the most powerful concepts in programming. They allow you to organize your Arduino code into manageable, reusable blocks, making your projects cleaner and easier to understand. Think of functions as mini-programs within your main program – they perform specific tasks whenever you call them.
In this tutorial, you'll learn how to create and use functions in Arduino, understand their benefits, and see practical examples of how they can improve your projects.
Why Use Functions?
Before diving into the syntax, let's understand why functions are essential:
- Code Organization: Break complex programs into smaller, manageable parts
- Reusability: Write code once and use it multiple times
- Readability: Make your code easier to understand
- Maintenance: Fix or modify code in one place instead of multiple places
- Abstraction: Focus on what a piece of code does rather than how it does it
Function Basics
Function Structure
An Arduino function has the following structure:
returnType functionName(parameterType parameterName) {
// Function code goes here
return value; // Optional, depends on returnType
}
Let's break down each component:
- returnType: The type of data the function returns (int, float, void, etc.)
- functionName: A descriptive name for your function (following camelCase convention)
- parameters: Input values the function needs to perform its task (optional)
- function body: The code that executes when the function is called
- return statement: Sends a value back to where the function was called (optional)
The void
Return Type
Many Arduino functions use the void
return type, which means the function doesn't return any value:
void blinkLED() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
Functions with Return Values
Functions can also return values:
int addNumbers(int a, int b) {
int sum = a + b;
return sum;
}
Creating Your First Arduino Function
Let's create a simple function that blinks an LED a specified number of times:
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
blinkLED(3); // Blink LED 3 times
delay(2000); // Wait 2 seconds
}
// Function to blink LED a specific number of times
void blinkLED(int times) {
for (int i = 0; i < times; i++) {
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
delay(200);
}
}
How This Works:
- We define a function called
blinkLED
that takes one parameter: the number of times to blink - In our
loop()
function, we callblinkLED(3)
to blink the LED 3 times - The function executes its code, then returns control to the
loop()
Function Declarations vs. Definitions
For larger programs, you might want to declare your functions at the top of your code and define them later:
// Function declaration
void blinkLED(int times);
int readSensor(int sensorPin);
void setup() {
// Setup code
}
void loop() {
// Loop code
}
// Function definitions
void blinkLED(int times) {
// Function code
}
int readSensor(int sensorPin) {
// Function code
return analogRead(sensorPin);
}
This approach is especially useful for larger projects with many functions.
Advanced Function Concepts
Parameters and Arguments
- Parameters are the variables listed in the function declaration
- Arguments are the values you pass to the function when calling it
Example:
// temperature and humidity are parameters
void displayWeather(float temperature, int humidity) {
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.print("°C, Humidity: ");
Serial.print(humidity);
Serial.println("%");
}
void loop() {
// 23.5 and 65 are arguments
displayWeather(23.5, 65);
}
Default Parameter Values
You can provide default values for parameters:
void blinkLED(int pin = LED_BUILTIN, int times = 1, int duration = 500) {
for (int i = 0; i < times; i++) {
digitalWrite(pin, HIGH);
delay(duration);
digitalWrite(pin, LOW);
delay(duration);
}
}
// These all work:
blinkLED(); // Uses all defaults
blinkLED(10); // Custom pin, default times and duration
blinkLED(10, 5); // Custom pin and times, default duration
blinkLED(10, 5, 200); // All custom values
Practical Examples
Example 1: Temperature Monitoring
This example uses functions to read a temperature sensor and respond accordingly:
const int sensorPin = A0;
const int ledPin = 13;
void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
}
void loop() {
float temperature = readTemperature();
displayTemperature(temperature);
checkTemperatureAlert(temperature);
delay(1000);
}
float readTemperature() {
// Read the voltage from the TMP36 sensor
int sensorValue = analogRead(sensorPin);
// Convert the voltage to temperature in Celsius
float voltage = sensorValue * (5.0 / 1023.0);
float temperatureC = (voltage - 0.5) * 100;
return temperatureC;
}
void displayTemperature(float temperature) {
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" °C");
}
void checkTemperatureAlert(float temperature) {
if (temperature > 30) {
alertHighTemperature();
} else {
digitalWrite(ledPin, LOW);
}
}
void alertHighTemperature() {
digitalWrite(ledPin, HIGH);
Serial.println("ALERT: Temperature too high!");
}
Example 2: Interactive Light Display
This example uses functions to create an interactive light display with multiple modes:
const int buttonPin = 2;
const int ledPins[] = {3, 4, 5, 6, 7};
const int numLeds = 5;
int displayMode = 0;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
for (int i = 0; i < numLeds; i++) {
pinMode(ledPins[i], OUTPUT);
}
}
void loop() {
// Check if button is pressed to change mode
if (isButtonPressed()) {
displayMode = (displayMode + 1) % 3;
clearAllLEDs();
delay(300); // Debounce
}
// Run the selected light pattern
switch (displayMode) {
case 0:
runChasePattern();
break;
case 1:
runBlinkAllPattern();
break;
case 2:
runFadePattern();
break;
}
}
boolean isButtonPressed() {
return digitalRead(buttonPin) == LOW;
}
void clearAllLEDs() {
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
}
void runChasePattern() {
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
delay(100);
digitalWrite(ledPins[i], LOW);
}
}
void runBlinkAllPattern() {
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
}
delay(500);
clearAllLEDs();
delay(500);
}
void runFadePattern() {
// Simplified fade pattern (in real code, you would use analogWrite())
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
}
delay(100);
clearAllLEDs();
delay(900);
}
Function Design Best Practices
To make your Arduino functions more effective:
- Use Descriptive Names: Names like
readTemperature()
andblinkLED()
clearly explain what the function does - Single Responsibility: Each function should do one thing and do it well
- Keep Functions Short: Aim for 20-30 lines or less
- Consistent Level of Abstraction: Don't mix high-level and low-level operations in the same function
- Limit Parameters: Try to keep the number of parameters to 4 or fewer
- Document Your Functions: Add comments explaining what your functions do
The Function Call Stack
When you call a function, Arduino sets aside memory for its variables. When functions call other functions, this information is stored in a structure called the "stack":
Be careful with recursive functions (functions that call themselves) as they can cause a "stack overflow" if they don't have a proper exit condition.
Summary
Functions are the building blocks of organized, reusable Arduino code. They allow you to:
- Break complex problems into smaller, manageable parts
- Reuse code instead of duplicating it
- Make your programs more readable and maintainable
- Create abstractions that hide complexity
As you develop more complex Arduino projects, functions will become an essential tool in your programming toolkit.
Exercises
- Create a function that fades an LED from off to on and back again
- Write a function that converts a temperature from Celsius to Fahrenheit
- Create a set of functions to control a traffic light sequence
- Modify the temperature monitoring example to add a low-temperature alert
- Create a function that plays a simple melody on a piezo buzzer
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)