100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Using and Writing Arduino Libraries

How to install and use third-party Arduino libraries, and how to package your own reusable code into a proper library with headers, source files, and examples.

Communication & LibrariesIntermediate10 min readJul 10, 2026
Analogies

What a Library Gives You

A library is a bundle of reusable code that hides the messy details of a device or algorithm behind a clean interface. Instead of writing hundreds of lines to talk to a DHT22 sensor over its custom one-wire timing protocol, you include a library, create an object, and call temperature(). Libraries let you build on the work of thousands of contributors, keep your sketches short and readable, and reuse the same driver across many projects. The Arduino ecosystem's real power is less the boards themselves and more this enormous, curated collection of ready-made drivers.

🏏

Cricket analogy: Using a library is like a batter trusting a coach's pre-planned game plan instead of reinventing footwork against every bowler from scratch.

Installing and Including Libraries

The easiest way to add a library is the Library Manager (Sketch > Include Library > Manage Libraries), which searches a curated index and handles downloads and updates for you. For libraries not in the index, you can add a ZIP through Sketch > Include Library > Add .ZIP Library, or drop the folder into your sketchbook's libraries directory manually. Once installed, you make its API available with an #include directive at the top of your sketch, such as #include <Adafruit_SSD1306.h>. Angle brackets tell the compiler to search the libraries path; the library then contributes its own compiled objects to your build.

🏏

Cricket analogy: The Library Manager is the selection committee: it maintains a vetted squad list so you pick proven players instead of unknowns off the street.

cpp
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>

Adafruit_SSD1306 display(128, 64, &Wire, -1);

void setup() {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // I2C address
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Hello, library!");
  display.display();
}

void loop() {}

Writing Your Own Library

When you find yourself copy-pasting the same helper functions between sketches, it is time to write a library. The minimal structure is a folder in the libraries directory containing a header file (.h) that declares a class and its public methods, and a source file (.cpp) that implements them. The header uses include guards (#ifndef/#define/#endif) to prevent double inclusion, and typically wraps functionality in a class so users create an object and call methods. Adding a keywords.txt file colors your API in the editor, and an examples folder gives newcomers a working sketch to copy. A library.properties file lets the Library Manager recognize and version your work.

🏏

Cricket analogy: Packaging your own library is like formalizing your net-practice drills into a coaching manual others can follow verbatim.

cpp
// Blinker.h
#ifndef BLINKER_H
#define BLINKER_H
#include <Arduino.h>

class Blinker {
  public:
    Blinker(uint8_t pin, unsigned long interval);
    void begin();
    void update();   // call from loop()
  private:
    uint8_t _pin;
    unsigned long _interval;
    unsigned long _last;
    bool _state;
};
#endif

// Blinker.cpp
#include "Blinker.h"

Blinker::Blinker(uint8_t pin, unsigned long interval)
  : _pin(pin), _interval(interval), _last(0), _state(false) {}

void Blinker::begin() { pinMode(_pin, OUTPUT); }

void Blinker::update() {
  if (millis() - _last >= _interval) {
    _last = millis();
    _state = !_state;
    digitalWrite(_pin, _state);
  }
}

A well-formed library.properties file (name, version, author, sentence, paragraph, category, architectures) is what turns your folder into something the Library Manager can list and version. Follow semantic versioning so users can trust that a minor bump won't break their sketches.

Avoid putting heavy work like delay() or blocking loops inside a library method that users call from loop(). Blocking code freezes every other task in the sketch. Prefer the non-blocking millis() pattern shown above so your library plays well alongside sensors, displays, and network code.

Keeping Libraries Maintainable

Good libraries expose a small, well-named public API and keep implementation details private, so users depend only on the parts you intend to support. Document each public method with a comment, ship at least one example sketch, and keep memory use lean because Arduino boards have kilobytes, not gigabytes, of RAM. Versioning matters: publishing to GitHub with tagged releases and a clear README lets others trust and contribute to your code. Treating your library as a product, not a scratch file, is what separates code that survives across projects from code that rots after one.

🏏

Cricket analogy: A tight public API is like a captain sharing only the agreed field plan while keeping the dressing-room tactics private and stable.

  • Libraries package reusable driver or algorithm code behind a clean, simple API.
  • Install via the Library Manager for curated libraries, or add a ZIP for others.
  • Use #include <Name.h> to bring a library's API into your sketch.
  • A minimal custom library needs a .h header with include guards and a .cpp implementation.
  • Add keywords.txt, an examples folder, and library.properties to make it Library-Manager-ready.
  • Prefer non-blocking millis() patterns over delay() inside library methods.
  • Keep the public API small, document it, version it, and ship an example sketch.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#ArduinoProgrammingStudyNotes#UsingAndWritingArduinoLibraries#Writing#Arduino#Libraries#Library#StudyNotes#SkillVeris#ExamPrep