Arduino Style Guide for Writing Libraries – Arduino Reference
This is a style guide to writing library APIs in an Arduino style.
Some of these run counter to professional programming practice. We’re aware of that, but it’s what’s made it possible for so many beginners to get started with Arduino easily.
So please code with these principles in mind. If you have suggestions on how to make Arduino libraries clearer for that core audience, please jump in the discussion. This is a work in progress.
Be kind to the end user.
Assume you are writing an API for an intelligent person who has not programmed before. Come up with a clear mental model of the concept you’re working with, and the terms and functions you will use.
Match your API to the underlying capabilities. You don’t want to expose implementation details to the user but you also don’t want an API that suggests an inaccurate mental model of the possibilities. For example, if there are only a few possible options for a particular setting, don’t use a function that takes an int, as it implies you can use any value you want.
Organize your public functions around the data and functionality that the user wants.
Quite often, the command set for a particular electronic module is overly complicated for the most common uses, or can be re-organized around higher level functionality.
Think about what the average person thinks the thing does, and try to organise your API functions around that.
Adafruit’s BMP085 library is a good example. The readPressure() command performs all the necessary steps to get the final pressure.
The library wraps this commonly executed series of functions into a high-level single command which returns the value the user’s looking for in a format she expects.
It abstracts away not only the low-level I2C commands, but also the mid-level temperature and pressure calculations, while still offering those mid-level functions as public functions for those who want them.
Use full, everyday words.
Don’t be terse with your function names or variables.
Use everyday terms instead of technical ones.
Pick terms that correspond to popular perception of the concept at hand. Don’t assume specialized knowledge.
For example, this is why we used analogWrite() rather than pwm().
Abbreviations are acceptable, though, if they’re in common use or are the primary name for something.
For example, “HTML” is relatively common and “SPI” is effectively the name of that protocol (“serial-peripheral interface” is probably too long). (“Wire” was probably a mistake, as the protocol it uses is typically called “TWI” or “I2C”.)
Avoid words that have different meanings to the general public. For example, to programmers, an error is a notification that something happened. To the general public, errors are bad things.
When you have to use a domain-specific term, write a sentence or two describing it to the general public FIRST. You’ll likely come across a better term, and if not, you’ll have started the documentation on your library.
Document and comment as you go. When writing examples and documentation, follow this style guide:
Use the established core libraries and styles.
Use read() to read inputs, and write() to write to outputs, e.g. digitalRead(), analogWrite(), etc.
Use the Stream.h and Print.h libraries when dealing with byte streams. If it’s not appropriate, at least try to use its API as a model.
For more on this, see below
For network applications, use the Client and Server libraries as the basis.
Use begin() to initialize a library instance, usually with some settings. Use end() to stop it.
Use camel case function names, not underscore.
For example, analogRead, not analog_read.
Or myNewFunction, not my_new_function. We’ve adopted this from Processing.org for readability’s sake.
LONG_CONSTANT_NAMES_FULL_OF_CAPS are hard to read. Try to simplify when possible, without being terse.
Try to avoid boolean arguments.
Instead, consider providing two different functions with names the describe the differences between them.
Don’t assume knowledge of pointers.
Beginning users of C find this the biggest roadblock, and get very confused by & and *, so whenever you can avoid having them hanging out in the API, do so.
One way is to pass by reference using array notation rather than * notation,
void printArray( char* array);
can be replaced by
void printArray(char[ ] array);
Though there are some libraries where we pass pointers by using structures like const chars, avoid anything that requires the user to pass them. For example,rather than:
foo.readAccel(&x, &y, &z);
use something like this:
xAxis = adxl.readX();
yAxis = adxl.readY();
zAxis = adxl.readZ();
When using serial communication, allow the user to specify any Stream object, rather than hard-coding “Serial”.
This will make your library compatible all serial ports on Mega and the Due, and can also use alternate interfaces like SoftwareSerial.
The Stream object can be passed to your library’s constructor or to a begin() function (as a reference, not a pointer). See Firmata 2.3 or XBee 0.4 for examples of each approach.
When writing a library that provides byte-stream communication, inherit Arduino’s Stream class, so your library can be used with all other libraries that accept Stream objects.
If possible, buffer incoming data, so that read() immediately accesses data the buffer but does not wait for more data to arrive.
If possible, your write() method should store data to a transmit buffer, but write() must wait if the buffer does not have enough space to immediately store all outgoing data.
The yield() function should be called while waiting.
Here are a few libraries that are exemplary from Adafruit.
She breaks the functions of the devices down into their high-level activities really well.
This does a nice job of abstracting from the Wire (I2C) library: https://github.com/adafruit/RTClib Reference Home
Corrections, suggestions, and new documentation should be posted to the Forum.
The text of the Arduino reference is licensed under a Creative Commons Attribution-ShareAlike 3.0 License. Code samples in the reference are released into the public domain.
Arduino IDE 1.5: Library specification – Arduino
Cristian Maglie edited this page on Feb 26 · 24 revisions Pages 4
Arduino IDE 1.5 3rd party Hardware specification
Arduino IDE 1.5 from command line
Arduino IDE 1.5: Library specification
Clone this wiki locally
Clone in Desktop
The updated (rev. 2) 1.5.x library format is implemented from IDE 1.5.6. We don’t expect to make any major changes but it may be tweaked while the 1.5.x releases remain in beta.
If you want to join the conversation subscribe to the Arduino developers list: https://groups.google.com/a/arduino.cc/forum/#!forum/developers
This specification is a proposal for a new 3rd party library format to be used in the Arduino IDE 1.5.x series.
rev.1 has been implemented starting with version 1.5.3 (now suprseded by rev.2)
rev.2 will be implemented starting from version 1.5.6.
This new library format is intended to be used in tandem with an automatic Library Manager, that will be implemented in future versions of the Arduino IDE. The Library Manager will allow users to automatically download and install the libraries needed in their projects, taking care of dependencies between libraries, with an easy to use graphic interface. Eventually, there will be an online centralized repository, provided by Arduino, where contributed libraries will reside.
Arduino 1.5.x supports multiple microcontroller architectures (e.g. AVR, SAM, etc), meaning that libraries may need to work on multiple architectures. The new 1.5.x library format doesn’t contain special support for cross-architecture libraries, but it does provide a pre-processor based mechanism for libraries to target sections of code to specific architectures.
The Arduino library style guide is here : http://arduino.cc/en/Reference/APIStyleGuide
The style guide for examples is here : http://arduino.cc/en/Reference/StyleGuide
1.5 library format (rev. 2)
The most significant addition to the format is the ability to add information about the library itself through a properties file called library.properties.
This file will allow the future Library Manager to search and install a library and its dependencies in an easy and automated way.
library.properties file format
The library.properties file is a key=value properties list. Every field in this file is UTF-8 encoded. The available fields are:
name – the name of the library
version – version of the library
author – name/nickname of the authors and their email addresses (not mandatory) separated by comma “,”
maintainer – name and email of the maintainer
sentence – a sentence explaining the purpose of the library
paragraph – a longer description of the library. The value of sentence always will be prepended, so you should start by writing the second sentence here
url – the URL of the library project, for a person to visit. Can be a github or similar page as well
architectures – a comma separated list of architectures supported by the library. If the library doesn’t contain architecture specific code use “*” to match all architectures
author=Cristian Maglie <email@example.com>, Pippo Pluto <firstname.lastname@example.org>
maintainer=Cristian Maglie <email@example.com>
sentence=A library that makes coding a Webserver a breeze.
paragraph=Supports HTTP1.1 and you can do GET and POST.
Layout of folders and files
Arduino libraries will be composed of a number of folders. Each folder has a specific purpose (sources, examples, documentation, etc). Folders not covered in this specification may be added as needed to future revisions.
For 1.5.x-only libraries, the source code resides in the src folder. For example:
The source code found in src folder and all its subfolders is compiled and linked in the user’s sketch. Only the src folder is added to the include search path (both when compiling the sketch and the library). When the user imports a library into their sketch (from the “Tools > Import Library” menu), an #include statement will be added for all header (.h) files in the src/ directory (but not its sub-folders). As a result, these header files form something of a de-facto interface to your library; in general, the only header files in the root src/ folder should be those that you want to expose to the user’s sketch and plan to maintain compatibility with in future versions of the library. Place internal header files in a sub-folder of the src/ folder.
For backward compatibility with Arduino 1.0.x, the library author may opt to not place source code into a folder called src. In this case the 1.0 library format is applied and the source code is searched from the library root folder and the utility folder, for example:
This will allow existing 1.0.x libraries to compile under 1.5.x as well and vice-versa. If a library only needs to run on 1.5.x, we recommend placing all source code in the src/ folder. If a library requires recursive compilation of nested source folders, its code must be in the src/ folder (since 1.0.x doesn’t support recursive compilation, backwards compatibility wouldn’t be possible anyway).
Library examples must be placed in the examples folder. Note that the examples folder must be written exactly like that (with lower case letters).
Sketches contained inside the examples folder will be shown in the Examples menu of the IDE.
An extras folder can be used by the developer to put documentation or other items to be bundled with the library. Remember that files placed inside this folder will increase the size of the library, so putting a 20MB PDF in a library that weights a few kilobytes may be not a good idea.
The content of the extras folder is totally ignored by the IDE; you are free to put anything inside such as supporting documentation, etc.
The list of highlighted keywords must be placed in a file called keywords.txt. The format of this file is the same as the 1.0 libraries
A complete example
A hypothetical library named “Servo” that adheres to the specification follows:
Working with multiple architectures
In 1.5.x, libraries placed in the user’s sketchbook folder (in the libraries/ sub-folder) will be made available for all boards, which may include multiple different processor architectures. To provide architecture-specific code or optimizations, library authors can use the ARDUINO_ARCH_XXX preprocessor macro (#define), where XXX is the name of the architecture (as determined by the name of the folder containing it), e.g. ARDUINO_ARCH_AVR will be defined when compiling for AVR-based boards. For example,
// AVR-specific code
// SAM-specific code
// generic, non-platform specific code
Alternatively, if a library only works on certain architectures, you can provide an explicit error message (instead of allowing the compilation to fail in an difficult to understand way):
// AVR-specific code
// SAM-specific code
#error “This library only supports boards with an AVR or SAM processor.”
Old library format (pre-1.5)
In order to support old libraries (from Arduino 1.0.x), the Arduino 1.5.x will also compile libraries missing a library.properties metadata file. As a result, these libraries should behave as they did in Arduino 1.0.x, although they will be available for all boards, including non-AVR ones (which wouldn’t have been present in 1.0.x).