Lesson: Creating and Using Header Files in C++/
Arduino
1. Introduction & Motivation
Welcome! In this lesson, you’ll learn how to create and use header files in Arduino/C++. This skill helps you
write cleaner, more organized, and more reusable code.
Why this matters
Modular code lets you: - Keep projects clean and readable - Reuse logic for sensors/actuators easily - Work
like a professional developer - Debug faster and maintain large projects
Arduino sketches often grow messy—everything ends up in one .ino file. Header files solve this by
separating what the code does (declarations) from how it works (definitions).
2. What a Header File Is
A header file is a .h file containing: - Function prototypes - Constants - Type definitions - (Optional) small
inline functions
It tells the compiler what exists, not how it works.
The implementation lives in a matching .cpp file.
3. When and Why to Use Header Files
Use header files when: - Your sketch becomes long - You have sensor/actuator code that can be reused -
You want to separate hardware logic from program logic - Multiple .cpp files need access to the same
declarations
Example: LED functions → LED module. Sensor readings → Sensor module.
4. Structure of a Typical Header File
A clean header contains:
1
#ifndef LEDMODULE_H
#define LEDMODULE_H
// Declarations go here
#endif
Includes: - Include guards ( #ifndef , #define , #endif ) - Function prototypes - Optional constants
Not allowed: - Full function definitions (except inline) - Large blocks of code
5. Step-by-Step: From One File to Modular Design
We start with everything in one .ino file, then later refactor it into modules.
This helps students see: - What belongs together - What can be reused - What should be separated
6. Example: Creating the LED Module
Below is how to create a real module.
Step 1 — Create LEDModule.h
#ifndef LEDMODULE_H
#define LEDMODULE_H
// Function prototypes for LED module
void initLED(int pinNumber);
void turnLEDOn();
void turnLEDOff();
#endif
Step 2 — Create [Link]
#include <Arduino.h>
#include "LEDModule.h"
static int ledPin; // only visible to this file
void initLED(int pinNumber) {
2
ledPin = pinNumber;
pinMode(ledPin, OUTPUT);
}
void turnLEDOn() {
digitalWrite(ledPin, HIGH);
}
void turnLEDOff() {
digitalWrite(ledPin, LOW);
}
Step 3 — Use the module in [Link]
#include "LEDModule.h"
int ledPin = 13;
void setup() {
initLED(ledPin);
}
void loop() {
turnLEDOn();
delay(1000);
turnLEDOff();
delay(1000);
}
Visual Diagram
+----------------+ +--------------------+
| LEDModule.h | <------> | [Link] |
| (Declarations) | | (Implementation) |
+----------------+ +--------------------+
| |
v v
+----------------------+
| [Link] |
| (Uses the module) |
+----------------------+
3
7. Understanding Preprocessor Directives
Students will see these: - #include — copy another file into this file - #ifndef / #define / #endif
— protect against double inclusion
Think of the preprocessor like a photocopier:
#include "LEDModule.h" = "Paste the contents of LEDModule.h here before compiling."
Why two include syntaxes?
#include <Arduino.h> — library/system search path
• < > tells the compiler: look in Arduino’s built‑in libraries.
#include "LEDModule.h" — project search path
• " " tells the compiler: look in the current sketch folder first.
Rule of thumb: - <...> → official library - "..." → your own files
8. Practice Exercise: Refactor a Monolithic Sketch
Below is a single‑file Arduino sketch. Your task is to refactor it into: - [Link] - LEDModule.h +
[Link] - ButtonModule.h + [Link]
Monolithic Version (Before Modularization)
// Monolithic sketch: LED + Button in one file
// ----- Pin configuration -----
const int LED_PIN = 13;
const int BUTTON_PIN = 2;
int ledState = LOW;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50; // ms
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
[Link](9600);
}
4
void loop() {
int reading = digitalRead(BUTTON_PIN);
// ----- Button debounce logic -----
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading == LOW) { // button pressed
toggleLED();
[Link]("Button pressed, LED toggled.");
delay(200);
}
}
lastButtonState = reading;
}
// ----- LED functions (currently mixed into main file) -----
void turnLEDOn() {
ledState = HIGH;
digitalWrite(LED_PIN, ledState);
}
void turnLEDOff() {
ledState = LOW;
digitalWrite(LED_PIN, ledState);
}
void toggleLED() {
if (ledState == LOW) {
turnLEDOn();
} else {
turnLEDOff();
}
}
Your Tasks
1. Move LED logic into LEDModule.h/.cpp .
2. Move button logic into ButtonModule.h/.cpp .
3. Keep setup() and loop() in [Link] .
4. Include modules:
5
#include <Arduino.h>
#include "LEDModule.h"
#include "ButtonModule.h"
5. Ensure headers contain only declarations.
Sources
• Arduino Documentation – Programming Techniques
• C++ Reference – Header Files and Separate Compilation
• GeeksforGeeks – C++ Header File Basics