Learning Goals 5 min
You've used dozens of Arduino libraries: Servo, Wire, Adafruit_SSD1306, ArduinoBLE, PubSubClient. Now you write your own. By the end of this lesson you will:
- Identify the four files of a polished Arduino library:
.h,.cpp,keywords.txt,library.properties. - Understand the folder layout for a library that installs cleanly in Arduino IDE.
- Write your first "hello library" that wraps the L03-42 Blinker class into a proper library.
Warm-Up 10 min
Open any installed library's folder (e.g. ~/Documents/Arduino/libraries/Servo/). You'll see:
Servo.h— the public interface (declarations).Servo.cpp(or src/Servo.cpp) — the implementations.keywords.txt— IDE syntax-highlighting hints.library.properties— name, version, dependencies, etc.examples/— sample sketches users can open from Examples menu.README.md— docs.
That's the canonical structure. Match it and your library looks professional.
New Concept · The four files 25 min
1. The header (Blinker.h)
Declares the class, includes guards, public API.
#ifndef BLINKER_H
#define BLINKER_H
#include <Arduino.h>
class Blinker {
public:
Blinker(int pin, unsigned long onMs, unsigned long offMs);
void begin();
void update();
void setRate(unsigned long onMs, unsigned long offMs);
void pause();
void resume();
bool isOn() const;
private:
int pin_;
unsigned long onMs_, offMs_;
unsigned long lastToggle_;
bool state_;
bool paused_;
};
#endifInclude guards (#ifndef ... #define ... #endif) prevent double-inclusion errors when the header gets pulled in twice.
2. The implementation (Blinker.cpp)
#include "Blinker.h"
Blinker::Blinker(int pin, unsigned long onMs, unsigned long offMs)
: pin_(pin), onMs_(onMs), offMs_(offMs),
lastToggle_(0), state_(false), paused_(false) {}
void Blinker::begin() {
pinMode(pin_, OUTPUT);
digitalWrite(pin_, LOW);
state_ = false;
lastToggle_ = millis();
}
void Blinker::update() {
if (paused_) return;
unsigned long now = millis();
unsigned long wait = state_ ? onMs_ : offMs_;
if (now - lastToggle_ >= wait) {
lastToggle_ = now;
state_ = !state_;
digitalWrite(pin_, state_ ? HIGH : LOW);
}
}
void Blinker::setRate(unsigned long onMs, unsigned long offMs) {
onMs_ = onMs; offMs_ = offMs;
}
void Blinker::pause() { paused_ = true; }
void Blinker::resume() { paused_ = false; lastToggle_ = millis(); }
bool Blinker::isOn() const { return state_; }3. keywords.txt
Tells the IDE which words to colour-highlight:
# tab-separated; ONE tab between columns Blinker KEYWORD1 begin KEYWORD2 update KEYWORD2 setRate KEYWORD2 pause KEYWORD2 resume KEYWORD2 isOn KEYWORD2
KEYWORD1 = class names (orange in IDE). KEYWORD2 = methods (brown). LITERAL1 = constants. Critical: tabs, not spaces. Spaces break parsing silently.
4. library.properties
name=Blinker version=1.0.0 author=Your Name <you@example.com> maintainer=Your Name <you@example.com> sentence=Non-blocking LED blinker for Arduino. paragraph=Wraps the millis() blink-without-delay pattern into a reusable class. Supports asymmetric on/off times, pause/resume, and live rate changes. category=Signal Input/Output url=https://github.com/yourname/Blinker architectures=* includes=Blinker.h
Required fields: name, version, author, maintainer, sentence, paragraph, category, url. The IDE shows this metadata when users hover the library in Library Manager.
Folder layout
Blinker/
├── library.properties
├── keywords.txt
├── README.md
├── src/
│ ├── Blinker.h
│ └── Blinker.cpp
└── examples/
└── HelloBlink/
└── HelloBlink.ino
The src/ folder is standard for newer libraries. Older libraries put the .h/.cpp in the root — still works.
Examples folder
A minimal examples/HelloBlink/HelloBlink.ino:
#include <Blinker.h>
Blinker led(LED_BUILTIN, 200, 1800);
void setup() {
led.begin();
}
void loop() {
led.update();
}Users find this under File → Examples → Blinker → HelloBlink after installing the library.
Worked Example · Wrap Blinker as a real library 25 min
Step 1 — make the folder
Create ~/Documents/Arduino/libraries/Blinker/.
Step 2 — write the four files
Use the templates from §3. library.properties, keywords.txt, src/Blinker.h, src/Blinker.cpp.
Step 3 — add an example
examples/HelloBlink/HelloBlink.ino as above.
Step 4 — write a README
# Blinker
Non-blocking LED blink for Arduino. Multiple LEDs at different rates from one sketch.
## Usage
\`\`\`cpp
#include <Blinker.h>
Blinker led(LED_BUILTIN, 200, 1800);
void setup() { led.begin(); }
void loop() { led.update(); }
\`\`\`
See \`examples/HelloBlink\` for more.
Step 5 — restart the IDE
Open Arduino IDE. Sketch → Include Library → Blinker. Now #include <Blinker.h> works in any sketch on your machine.
Step 6 — verify keyword highlighting
Open a sketch, type Blinker led(...). Blinker should colour orange. led.update() should colour brown. If not — check keywords.txt is tabs, not spaces.
Try It Yourself 15 min
Goal: Add a second example: examples/MultiBlink/MultiBlink.ino showing 3 LEDs at 3 rates.
Goal: Convert another reusable class from your library (Motor, SmoothedSensor, Stepper helper, etc.) into a properly-structured library. Same folder layout.
Goal: Add a Doxygen-style comment header to each public method. /// comments before each declaration. Generates polished IDE tooltips and HTML docs.
Mini-Challenge · Audit your local libraries 10 min
- Open
~/Documents/Arduino/libraries/. - Pick 3 installed libraries. Look at their folder structures.
- Compare to your Blinker — what's consistent? What varies?
- Note any patterns to emulate (multi-file split, examples count, README style).
Recap 5 min
A library = .h + .cpp + keywords.txt + library.properties + examples + README. Standard folder layout. Drop in libraries/ and the IDE picks it up. Tomorrow we design the public API — what to expose, what to hide.
- Library
- A reusable bundle of Arduino code that can be included with
#include. - Header file (.h)
- Public declarations. Class definitions, function signatures, constants.
- Implementation file (.cpp)
- Bodies of the functions / methods declared in the header.
- Include guards
#ifndef NAME_H ... #define NAME_H ... #endifwrapping header content. Prevents double-inclusion errors.- keywords.txt
- Tab-separated file listing identifiers and their highlight category. Colors the IDE.
- library.properties
- Metadata: name, version, author, description, etc. Used by the Library Manager.
- examples/ folder
- Sample sketches. Each in its own subdirectory. Shows in File → Examples → <library>.
- src/ folder
- Modern convention for code files. Alternative to .h/.cpp in the library root.
Homework 5 min
- Build the Blinker library on your machine.
- Use it in a fresh sketch via
#include <Blinker.h>. Verify highlighting. - Read ahead to ARD-L04-42 (Your Own Header File).