Libraries add functionality to the Arduino environment. They extend the commands available to provide capabilities not available in the core Arduino language. Libraries provide a way to add features that can be accessed from any of your sketches once you have installed the library.
The Arduino software distribution includes built-in libraries that cover common tasks. These libraries are discussed in Recipe 16.1.
Libraries are also a good way for people to share code that may be useful to others. Many third-party libraries provide specialized capabilities; these can be downloaded from the Arduino Playground and other sites. Libraries are often written to simplify the use of a particular piece of hardware. Many of the devices covered in earlier chapters use libraries to make it easier to connect to the devices.
Libraries can also provide a friendly wrapper around complex code to make it easier to use. An example is the Wire library distributed with Arduino, which hides much of the complexity of low-level hardware communications (see Chapter 13).
This chapter explains how to use and modify libraries. It also gives examples of how to create your own libraries.
This recipe shows you how to use Arduino library functionality in your sketch.
To see the list of available libraries from the IDE menu, click Sketch→Import Library. A list will drop down showing all the available libraries. The first dozen or so are the libraries distributed with Arduino. A horizontal line separates that list from the libraries that you download and install yourself.
Clicking on a library will add that library to the current sketch, by adding the following line to the top of the sketch:
#include <nameOfTheLibrarySelected.h
>
This results in the functions within the library becoming available to use in your sketch.
The Arduino IDE updates its list of available libraries only when the IDE is first started on your computer. If you install a library after the IDE is running, you need to close the IDE and restart for that new library to be recognized.
The Arduino libraries are documented in the reference at http://arduino.cc/en/Reference/Libraries and each library includes example sketches demonstrating their use. Chapter 1 has details on how to navigate to the examples in the IDE.
The libraries that are included with Arduino as of version 0022 are:
Used to store and read information in memory that is preserved when power is removed; see Chapter 18
Used to communicate with the Arduino Ethernet shield; see Chapter 15
A protocol used to simplify serial communication and control of the board
For controlling compatible LCD displays; see Chapter 11
Helps manage a matrix of LEDs; see Chapter 7
Supports reading and writing files to an SD card using external hardware
Used to control servo motors; see Chapter 8
Used for Ethernet and SPI hardware; see Chapter 13
For working with stepper motors; see Chapter 8
Works with I2C devices attached to the Arduino; see Chapter 13
Libraries that work with specific hardware within the Arduino
controller chip only work on predefined pins. The Wire and SPI
libraries are examples of this kind of library. Libraries that allow
user selection of pins usually have this specified in setup
; Servo, LiquidCrystal, and Stepper are
examples of this kind of library. See the library documentation for
specific information on how to configure the library.
Including a library adds the library code to your sketch behind the scenes. This means the size of your sketch, as reported at the end of the compilation process, will increase, but the Arduino build process is smart enough to only include the code your sketch is actually using from the library, so you don’t have to worry about the memory overhead for methods that are not being used. Therefore, you also don’t have to worry about unused functions reducing the amount of code you can put into your sketch.
The Arduino reference for libraries: http://arduino.cc/en/Reference/Libraries
Download the library. It will often be a .zip file. Unzip it and you will have a folder that has the same title as the name of the library. This folder needs to be put inside a folder called libraries inside your Arduino document folder. To find the Arduino document folder, launch Arduino and choose Sketch→Show Sketch Folder. Go up to the parent directory of the folder that appears, and you’ll be in the Arduino document folder. If no libraries folder exists, create one and put the library inside it.
If the Arduino IDE is running, quit the program and restart it. The IDE scans this folder to find libraries only when it is launched. If you now go to the menu Sketch→Import Library, at the bottom, below the gray line and the word Contributed, you should see the library you have added.
If the libraries provide example sketches, you can view these from the IDE menu; click File→Examples, and the libraries examples will be under the libraries name in a section between the general examples and the Arduino distributed library example listing.
A large number of libraries are provided by third parties. Many are of very high quality, are actively maintained, and provide good documentation and example sketches. The Arduino Playground is a good place to look for libraries: http://www.arduino.cc/playground/.
Look for libraries that have clear documentation and examples. Check out the Arduino forums to see if there are any threads (discussion topics) that discuss the library. Libraries that were designed to be used with early Arduino releases may have problems when used with the latest Arduino version, so you may need to read through a lot of material (some threads for popular libraries contain hundreds of posts) to find information on using an older library with the latest Arduino release.
If the library examples do not appear in the Examples menu or you get a message saying “Library not found” when you try to use the library, check that the libraries folder is in the correct place with the name spelled correctly. A library folder named <LibraryName> (where <LibraryName> is the name for the library) must contain a file named <LibraryName>.h with the same spelling and capitalization. Check that additional files needed by the library are in the folder.
You want to change the behavior of an existing library, perhaps to extend its capability. For example, the TimeAlarms library in Chapter 12 only supports six alarms and you need more (see Recipe 12.5).
The Time and TimeAlarms libraries are described in Chapter 12, so refer to Recipe 12.5 to familiarize yourself with the standard functionality. The libraries can be downloaded from the website for this book, or from http://www.arduino.cc/playground/uploads/Code/Time.zip (this download includes both libraries).
Once you have the Time and TimeAlarms libraries installed,
compile and upload the following sketch, which will attempt to create
seven alarms—one more than the libraries support. Each
Alarm
task simply prints its task
number:
/* multiple_alarms sketch has more timer repeats than the library supports out of the box - you will need to edit the header file to enable more than 6 alarms */ #include <Time.h> #include <TimeAlarms.h> int currentSeconds = 0; void setup() { Serial.begin(9600); // create 7 alarm tasks Alarm.timerRepeat(1, repeatTask1); Alarm.timerRepeat(2, repeatTask2); Alarm.timerRepeat(3, repeatTask3); Alarm.timerRepeat(4, repeatTask4); Alarm.timerRepeat(5, repeatTask5); Alarm.timerRepeat(6, repeatTask6); Alarm.timerRepeat(7, repeatTask7); //7th timer repeat } void repeatTask1() { Serial.print("task 1 "); } void repeatTask2() { Serial.print("task 2 "); } void repeatTask3() { Serial.print("task 3 "); } void repeatTask4() { Serial.print("task 4 "); } void repeatTask5() { Serial.print("task 5 "); } void repeatTask6() { Serial.print("task 6 "); } void repeatTask7() { Serial.print("task 7 "); } void loop() { if(second() != currentSeconds) { // print the time for each new second // the task numbers will be printed when the alarm for that task is triggered Serial.println(); Serial.print(second()); Serial.print("->"); currentSeconds = second(); Alarm.delay(1); //Alarm.delay must be called to service the alarms } }
Open the Serial Monitor and watch the output being printed. After nine seconds of output, you should see this:
1->task 1 2->task 1 task 2 3->task 1 task 3 4->task 1 task 2 task 4 5->task 1 task 5 6->task 1 task 2 task 3 task 6 7->task 1 8->task 1 task 2 task 4 9->task 1 task 3
The task scheduled for seven seconds did not trigger because the library only provides six timer “objects” that you can use.
You can increase this by modifying the library. Go to the libraries folder in your Arduino Documents folder.
You can locate the directory containing the sketchbook folder by clicking on the menu item File→Preferences in the IDE. A dialog box will open, showing the sketchbook location.
If you have installed the Time and TimeAlarms libraries (both libraries are in the file you downloaded), navigate to the LibrariesTimeAlarms folder. Open the TimeAlarms.h header file (for more details about header files, see Recipe 16.4). You can edit the file with any text editor; for example, Notepad on Windows or TextEdit on a Mac.
You should see the following at the top of the TimeAlarms.h file:
#ifndef TimeAlarms_h #define TimeAlarms_h #include <inttypes.h> #include "Time.h" #define dtNBR_ALARMS 6
The maximum number of alarms is specified by the value defined
for dtNbr_ALARMS
.
Change:
#define dtNBR_ALARMS 6
to:
#define dtNMBR_ALARMS 7
and save the file.
Upload the sketch to your Arduino again, and this time the serial output should read:
1->task 1 2->task 1 task 2 3->task 1 task 3 4->task 1 task 2 task 4 5->task 1 task 5 6->task 1 task 2 task 3 task 6 7->task 1 task 7 8->task 1 task 2 task 4 9->task 1 task 3
You can see that task 7 now activates after seven seconds.
Capabilities offered by a library are a trade-off between the resources used by the library and the resources available to the rest of your sketch, and it is often possible to change these capabilities if required. For example, you may need to decrease the amount of memory used for a serial library so that other code in the sketch has more RAM. Or you may need to increase the memory usage by a library for your application. The library writer generally creates the library to meet typical scenarios, but if your application needs capabilities not catered to by the library writer, you may be able to modify the library to accommodate them.
In this example, the TimeAlarms library allocates room (in RAM) for six alarms. Each of these consumes around a dozen bytes and the space is reserved even if only a few are used. The number of alarms is set in the library header file (the header is a file named TimeAlarms.h in the TimeAlarms folder). Here are the first few lines of TimeAlarms.h:
#ifndef TimeAlarms_h #define TimeAlarms_h #include <inttypes.h> #include "Time.h" #define dtNBR_ALARMS 6
In the TimeAlarms library, the maximum number of alarms is set
using a #define
statement. Because
you changed it and saved the header file when you recompiled the
sketch to upload it, it uses the new upper limit.
Sometimes constants are used to define characteristics such as the clock speed of the board, and when used with a board that runs at a different speed, you will get unexpected results. Editing this value in the header file to the correct one for the board you are using will fix this problem.
If you edit the header file and the library stops working, you can always download the library again and replace the whole library to return to the original state.
Recipe 16.4 has more details on how you can add functionality to libraries.
You want to create your own library. Libraries are a convenient way to reuse code across multiple sketches and are a good way to share with other users.
A library is a collection of methods and variables that are combined in a format that enables users to access functions and variables in a standardized way.
Most Arduino libraries are written as a class. If you are familiar with C++ or Java, you will be familiar with classes. However, you can create a library without using a class, and this recipe shows you how.
This recipe explains how you can transform the sketch from Recipe 7.1 to move the BlinkLED
function
into a library.
See Recipe 7.1 for the wiring diagram and an explanation of the circuit. Here is the sketch that will be the starting point for the library:
/* * blinkLibTest */ const int firstLedPin = 3; // choose the pin for each of the LEDs const int secondLedPin = 5; const int thirdLedPin = 6; void setup() { pinMode(firstLedPin, OUTPUT); // declare LED pins as output pinMode(secondLedPin, OUTPUT); // declare LED pins as output pinMode(thirdLedPin, OUTPUT); // declare LED pins as output } void loop() { // flash each of the LEDs for 1000 milliseconds (1 second) blinkLED(firstLedPin, 1000); blinkLED(secondLedPin, 1000); blinkLED(thirdLedPin, 1000); }
The blinkLED
function from
Recipe 7.1 should be removed from
the sketch and moved into a separate file named blinkLED.cpp (see the Discussion for more
details about .cpp files):
/* blinkLED.cpp * simple library to light an LED for a duration given in milliseconds */ #include <WProgram.h> // Arduino includes #include "blinkLED.h" // blink the LED on the given pin for the duration in milliseconds void blinkLED(int pin, int duration) { digitalWrite(pin, HIGH); // turn LED on delay(duration); digitalWrite(pin, LOW); // turn LED off delay(duration); }
Create the blinkLED.h header file as follows:
/* * blinkLED.h * Library header file for BlinkLED library */ void blinkLED(int pin, int duration); // function prototype
The library will be named blinkLED and will be located in the libraries folder (see Recipe 16.2).
The blinkLED
function from
Recipe 7.1 is moved out of the
sketch and into a library file named blinkLED.cpp (the .cpp extension stands for “C plus plus” and
contains the executable code).
The terms functions and
methods are used in Arduino library
documentation to refer to blocks of code such as blinkLED
. The term
method was introduced to refer to the
functional blocks in a class. Both terms refer to the named
functional blocks that are made accessible by a library.
The blinkLED.cpp file
contains a blinkLED
function that
is identical to the code from Recipe 7.1 with the following two lines
added at the top:
#include <WProgram.h> // Arduino includes #include "blinkLED.h"
The #include
<WProgram.h>
line is needed by a library that uses any
Arduino functions or constants. Without this, the compiler will report
errors for all the Arduino functions used in your sketch.
The next line, #include
"blinkLED.h"
, contains the function definitions (also known
as prototypes) for your library. The Arduino
build process creates prototypes for all the functions within a sketch
automatically when a sketch is compiled—but it does not create any
prototypes for library code, so if you make a library, you must create
a header with these prototypes. It is this header file that is added
to a sketch when you import a library from the IDE (see Recipe 16.1).
Every library must have a file that declares the names of the functions to be exposed. This file is called a header file (also known as an include file) and has the form <LibraryName>.h (where <LibraryName> is the name for your library). In this example, the header file is named blinkLED.h and is in the same folder as blinkLED.cpp.
The header file for this library is simple. It declares the one function:
void blinkLED(int pin, int duration); // function prototype
This looks similar to the function definition in the blinkLED.cpp file:
void blinkLED(int pin, int duration)
The difference is subtle but vital. The header file prototype contains a trailing semicolon. This tells the compiler that this is just a declaration of the form for the function but not the code. The source file, blinkLED.cpp, does not contain the trailing semicolon and this informs the compiler that this is the actual source code for the function.
Libraries can have more than one header file and more than one implementation file. But there must be at least one header and that must match the library name. It is this file that is included at the top of the sketch when you import a library.
A good book on C++ can provide more details on using header and .cpp files to create code modules. This recipe’s See Also section lists some popular choices.
With the blinkLED.cpp and blinkLED.h files in the correct place within the libraries folder, close the IDE and reopen it.
The Arduino IDE updates its list of available libraries only when the IDE is first started on your computer. If you create a library after the IDE is running, you need to close the IDE and restart for that library to be recognized.
Upload the blinkLibTest sketch and you should see the three LEDs blinking.
It’s easy to add additional functionality to the library. For example, you can add some constant values for common delays so that users of your libraries can use the descriptive constants instead of millisecond values.
Add the three lines with constant values to your header file as follows:
// constants for duration const int BLINK_SHORT = 250; const int BLINK_MEDIUM = 500; const int BLINK_LONG = 1000; void blinkLED(int pin, int duration); // function prototype
Change the code in loop
as
follows and upload the sketch to see the different blink rates:
void loop() { blinkLED(firstLedPin, BLINK_SHORT); blinkLED(secondLedPin, BLINK_MEDIUM); blinkLED(thirdLedPin, BLINK_LONG); }
You need to close and restart the IDE when you first add the library to the libraries folder, but not after subsequent changes to the library. Libraries included in Arduino release 0017 and later are recompiled each time the sketch is compiled. Arduino releases earlier than 0017 required the deletion of the library object files to make the library recompile and for changes to be included.
New functions can be easily added. This example adds a function
that continues blinking for the number of times given by the sketch.
Here is the loop
code:
void loop() { blinkLED(firstLedPin,BLINK_SHORT,5 ); // blink 5 times blinkLED(secondLedPin,BLINK_MEDIUM,3 ); // blink 3 times blinkLED(thirdLedPin, BLINK_LONG); // blink once }
To add this functionality to the library, add the prototype to blinkLED.h as follows:
/* * BlinkLED.h * Header file for BlinkLED library */ const int BLINK_SHORT = 250; const int BLINK_MEDIUM = 500; const int BLINK_LONG = 1000; void blinkLED(int pin, int duration); // new function for repeat count void blinkLED(int pin, int duration, int repeats);
Add the function into blinkLED.cpp:
/* * BlinkLED.cpp */ #include <WProgram.h> // Arduino includes #include "BlinkLED.h" // blink the LED on the given pin for the duration in milliseconds void blinkLED(int pin, int duration) { digitalWrite(pin, HIGH); // turn LED on delay(duration); digitalWrite(pin, LOW); // turn LED off delay(duration); } /* function to repeat blinking void blinkLED(int pin, int duration, int repeats) { while(repeats) { blinkLED(pin, duration); repeats = repeats -1; } }
You can create a keywords.txt file if you want to add syntax highlighting (coloring the keywords used in your library when viewing a sketch in the IDE). This is a text file that contains the name of the keyword and the keyword type—each type uses a different color. The keyword and type must be separated by a tab (not a space). For example, save the following file as keywords.txt in the blinkLED folder:
####################################### # Methods and Functions (KEYWORD2) ####################################### blinkLED KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### BLINK_SHORT LITERAL1 BLINK_MEDIUM LITERAL1 BLINK_LONG LITERAL1
“Writing a Library for Arduino” reference document: http://www.arduino.cc/en/Hacking/LibraryTutorial
Also see the following books on C++:
Practical C++ Programming by Steve Oualline (O’Reilly)
C++ Primer Plus by Stephen Prata (Sams)
C++ Primer by Stanley B. Lippman, Josée Lajoie, and Barbara E. Moo (Addison-Wesley Professional)
You want to create a library that uses functionality from one or more existing libraries. For example, you want to create a library to aid debugging that sends print output to a second Arduino board using the Wire library.
This recipe uses the Wire library discussed in Chapter 13 and the core Arduino print functionality to create a new library that sends printed output to another Arduino board connected using I2C. The connections and code are covered in Recipe 13.9. This recipe describes how that code can be converted into a library.
Create a folder named i2cDebug in the libraries directory (see Recipe 16.4 for details on the file structure for a library). Create a file named i2cDebug.h with the following code:
/* * i2cDebug.h */ #include <WProgram.h> #include <Print.h> // the Arduino print class class I2CDebugClass : public Print { private: int I2CAddress; byte count; void write(byte c); public: I2CDebugClass(); boolean begin(int id); }; extern I2CDebugClass i2cDebug; // the i2c debug object
Create a file named i2cDebug.cpp in the i2cDebug folder as follows:
/* * i2cDebug.cpp */ #include <i2cDebug.h> #include <Wire.h> // the Arduino I2C library I2CDebugClass::I2CDebugClass() { } boolean I2CDebugClass::begin(int id) { I2CAddress = id; // save the slave's address Wire.begin(); // join I2C bus (address optional for master) return true; } void I2CDebugClass::write(byte c) { if( count == 0) { // here if the first char in the transmission Wire.beginTransmission(I2CAddress); // transmit to device } Wire.send(c); // if the I2C buffer is full or an end of line is reached, send the data // BUFFER_LENGTH is defined in the Wire library if(++count >= BUFFER_LENGTH || c == ' ') { // send data if buffer full or newline character Wire.endTransmission(); count = 0; } } I2CDebugClass i2cDebug; // Create an I2C debug object
Load this example sketch into the IDE:
/* * i2cDebug * example sketch for i2cDebug library */ #include <Wire.h> // the Arduino I2C library #include <i2cDebug.h> const int address = 4; //the address to be used by the communicating devices const int sensorPin = 0; // select the analog input pin for the sensor int val; // variable to store the sensor value void setup() { Serial.begin(9600); i2cDebug.begin(address); } void loop() { // read the voltage on the pot(val ranges from 0 to 1023) val = analogRead(sensorPin); Serial.println(val); i2cDebug.println(val); }
Remember that you need to restart the IDE after creating the library folder. See Recipe 16.4 for more detail on creating a library.
Upload the slave I2C sketch onto another Arduino board as described in Recipe 13.9, and you should see the output from the Arduino board running your library displayed on the second board.
To include another library, use its include
statement in your code as you would
in a sketch. It is sensible to include information about any
additional libraries that your library needs in documentation if you
make it available for others to use, especially if it requires a
library that is not distributed with Arduino.
This recipe provides an example of how to use a class when creating a library. A class is a programming technique for grouping functions and variables together. The following references provide an introduction to classes:
Programming Interactivity by Joshua Noble (O’Reilly)
C++ Primer by Stanley B. Lippman, Josée Lajoie, and Barbara E. Moo (Addison-Wesley Professional)
3.142.97.219