Using, Modifying, and Creating Libraries

16.0 Introduction

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 Library manager but also from Github. 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.

16.1 Using the Built-in Libraries

Problem

You want to use the libraries provided with the Arduino distribution in your sketch.

Solution

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 SketchInclude 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.

Note

The Arduino IDE updates its list of available libraries only when the IDE is first started on your computer. If you manually install a library after the IDE is running, you need to close the IDE and restart for that new library to be recognized. If you install a library through the Library Manager, you won’t need to restart the IDE.

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 1.8.10 are:

Adafruit Circuit Playground

Supports Adafruit’s Circuit Playground board, which includes many sensors and outputs for quick and easy prototyping

Bridge

This is used by the now-discontinued Arduino Yun, Yun Shield, and TRE. It allows communication between the Linux system and microcontroller on those boards

Esplora

This is used by the now-discontinued Arduino Esplora board, an all-in-one board that included sensors, joystick, LEDs, buzzers, and other inputs and outputs

EEPROM

Used to store and read information in memory that is preserved when power is removed; see Chapter 18

Ethernet

Used to communicate with the Arduino Ethernet shield, compatible modules such as the Adafruit Ethernet FeatherWing, or for use with the Arduino Ethernet board; see Chapter 15

Firmata

A protocol used to simplify serial communication and control of the board

GSM

Supports the now-discontinued Arduino GSM shield, which connected Arduino to cellular data networks

HID

Allows certain boards, such as the Arduino Leonardo and SAMD-based boards, to function as a mouse or keyboard. You won’t use this library directly, but the Keyboard and Mouse libraries depend on it

Keyboard

Allows certain boards, such as the Arduino Leonardo and SAMD-based boards, to function as a USB keyboard

LiquidCrystal

For controlling compatible LCD displays; see Chapter 11

Mouse

Allows certain boards, such as the Arduino Leonardo and SAMD-based boards, to function as a USB mouse

Robot Control

Supports operation of the now-discontinued Arduino Robot’s control board

Robot IR Remote

Supports operation of the now-discontinued Arduino Robot’s infrared remote

Robot Motor

Supports operation of the now-discontinued Arduino Robot’s motor board

SD

Supports reading and writing files to an SD card using external hardware

Servo

Used to control servo motors; see Chapter 8

SoftwareSerial

Enables additional serial ports

SpacebrewYun

This is used by the now-discontinued Arduino Yun to enable WebSocket-based communications

SPI

Used for Ethernet and SPI hardware; see Chapter 13

Stepper

For working with stepper motors; see Chapter 8

Temboo

Connects Arduino to Temboo, a platform for connecting to APIs, databases, and code utilities

TFT

A library to support the now-discontinued Arduino LCD Screen. Third-party boards and modules are available along with custom libraries

WiFi

Supports the now-discontinued Arduino WiFi shield, which has been replaced by Arduino boards with built-in WiFi as well as third-party boards and modules

Wire

Works with I2C devices attached to the Arduino; see Chapter 13

The following two libraries can be found in releases prior to Arduino 1.0 but are no longer included with the Arduino distribution:

Matrix

Helps manage a matrix of LEDs; see Chapter 7

Sprite

Enables the use of sprites with an LED matrix

Discussion

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 that 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.

Libraries included with Arduino (and many contributed libraries) include example sketches that show how to use the library. They are accessed from the FileExamples menu.

See Also

The Arduino reference for libraries: http://arduino.cc/en/Reference/Libraries

16.2 Installing Third-Party Libraries

Problem

You want to use a library created for use with Arduino but not in the standard distribution.

Solution

First, check the Library Manager to see if the library is available. Select ToolsManage Libraries and search for the library you are looking for (or for the name of a component; you can often find libraries that are designed for specific components). Hover over its entry in the list of results, and click Install. It will be ready to use right away.

Installing a library with the Library Manager

If the library is not available in the Library Manager, you will need to download the library. If the library is available on Github, check the README carefully. In most cases, you should be able to download it from the Releases tab just above the list of files or click the Clone or Download button and choose Download Zip. If the library is made available some other way, 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, open Preferences (ArduinoPreferences on macOS; FilePreferences on Windows or Linux) and note the sketchbook location. Navigate to that directory in a file system browser (such as Windows Explorer or macOS Finder) or at the terminal. If no libraries folder exists, create one and put the folder you unzipped inside it.

If the Arduino IDE is still running, quit and restart it. The IDE scans this folder to find libraries only when it is launched. If you now go to the menu SketchImport 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 FileExamples, and the libraries examples will be under the libraries name in a section between the general examples and the Arduino distributed library example listing.

Discussion

A large number of libraries are provided by third parties. Many are very high quality, are actively maintained, and provide good documentation and example sketches. https://www.arduinolibraries.info/ is a great, regularly-updated list of available libraries. The Arduino Playground, although no longer accepting updates, is also 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.

16.3 Modifying a Library

Problem

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).

Solution

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 installed using the Library Manager. If you have trouble finding the Time library, try searching the Library Manager for “timekeeping.”

Once you have the Time and TimeAlarms libraries installed, compile and upload the following sketch on an AVR-based board, which will attempt to create seven alarms—one more than the libraries support (on AVR that is; ARM and ESP8266 boards support more). 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 <TimeLib.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.

Note

You can locate the directory containing the sketchbook folder by clicking on the menu item FilePreferences (on Windows or Linux) or ArduinoPreferences (on macOS) 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 <Arduino.h>
#include "TimeLib.h"

#if defined(__AVR__)
#define dtNBR_ALARMS 6   // max is 255
#else
#define dtNBR_ALARMS 12  // assume non-AVR has more memory
#endif

The maximum number of alarms is specified by the value defined for dtNbr_ALARMS.

Change:

#define dtNBR_ALARMS 6

to:

#define dtNBR_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.

Discussion

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).

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 define statements (or 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.

See Also

Recipe 16.4 has more details on how you can add functionality to libraries.

16.4 Creating Your Own Library

Problem

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.

Solution

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. The library will contain the blinkLED function from that recipe. Here is the sketch that will be used to test the library:

/*
 * blinkLibTest
 */

#include "blinkLED.h" 

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 "Arduino.h"   // use: Wprogram.h for Arduino versions prior to 1.0
#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);
}
Note

Most library authors are programmers who use their favorite programming editor, but you can use any plain text editor to create these files.

Create the blinkLED.h header file as follows:

/*
 * blinkLED.h
 * Library header file for BlinkLED library
 */
#include "Arduino.h"

void blinkLED(int pin, int duration);  // function prototype

Discussion

The library will be named “blinkLED” and will be located in the libraries folder (see Recipe 16.2); create a subdirectory named blinkLED in the libraries folder and move blinkLED.h and blinkLED.cpp into it. Next, create a subdirectory of that folder called examples and a subdirectory under that folder called blinkLibTest. Next, put the contents of the sketch shown earlier into a file named examples/blinkLibTest/blinkLibTest.ino.

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).

Note

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 "Arduino.h"  // Arduino include
#include "blinkLED.h"

The #include "Arduino.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.

Note

Arduino.h was added in Release 1.0 and replaces WProgram.h. If you are compiling sketches using earlier releases, you can use the following conditional include to bring in the correct version:

#if ARDUINO >= 100
#include "Arduino.h  // for 1.0 and later
#else
#include "WProgram.h" // for earlier releases
#endif

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).

Note

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.

Note

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, blinkLED.h, and blinkLibTest.ino files in the correct place within the libraries folder, close the IDE and reopen it. The directory structure should look like this

libraries/
└── blinkLED/
    ├── blinkLED.cpp
    ├── blinkLED.h
    └── examples/
        └── blinkLibTest/
            └── blinkLibTest.ino
Note

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. Although you need to close and restart the IDE when you first add the library to the libraries folder, you do not need to do so after subsequent changes to the library.

Click FileExamples (Examples from Custom Libraries)blinkLEDblinkLibTest to open the example sketch. 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, traditionally put just before the function prototype, 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);
}

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
 */
#include "Arduino.h"

// constants for duration
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
 * simple library to light an LED for a duration given in milliseconds
 */
#include "Arduino.h"
#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 (you’ll need to quit and restart the IDE when you add or modify a keywords.txt file):

#######################################
# Methods and Functions (KEYWORD2)
#######################################
blinkLED  KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
BLINK_SHORT    LITERAL1
BLINK_MEDIUM   LITERAL1
BLINK_LONG     LITERAL1

See Also

See Recipe 16.5 for more examples of writing a library.

“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; search for it on oreilly.com)

  • C++ Primer Plus by Stephen Prata (Sams)

  • C++ Primer by Stanley B. Lippman, Josée Lajoie, and Barbara E. Moo (Addison-Wesley Professional)

16.5 Creating a Library That Uses Other Libraries

Problem

You want to create a library that uses functionality from one or more existing libraries. For example, to use the Wire library to get data from a Wii nunchuck game controller.

Solution

This recipe uses the functions described in Recipe 13.6 to communicate with a Wii Nunchuck using the Wire library.

Create a folder named Nunchuck in the libraries directory (see Recipe 16.4 for details on the file structure for a library). Create a file named Nunchuck.h with the following code:

/*
 * Nunchuck.h
 * Arduino library to interface with wii Nunchuck
 */
 
#ifndef Nunchuck_included
#define Nunchuck_included

// identities for each field provided by the wii nunchuck
enum nunchuckItems { wii_joyX, wii_joyY, wii_accelX, wii_accelY, wii_accelZ, 
                      wii_btnC, wii_btnZ, wii_ItemCount };

// uses pins adjacent to I2C pins as power & ground for Nunchuck
void nunchuckSetPowerpins();
 
// initialize the I2C interface for the nunchuck
void nunchuckInit();
 
// Request data from the nunchuck
void nunchuckRequest();

// Receive data back from the nunchuck, 
// returns true if read successful, else false
bool nunchuckRead();
 
// Encode data to format that most wiimote drivers except
char nunchuckDecode (uint8_t x);
  
// return the value for the given item
int nunchuckGetValue(int item);
 
#endif

Create a file named Nunchuck.cpp in the Nunchuck folder as follows:

/*
 * Nunchuck.cpp
 * Arduino library to interface with wii Nunchuck
 */

#include "Arduino.h"   // Arduino defines

#include "Wire.h"      // Wire (I2C) defines
#include "Nunchuck.h"  // Defines for this library

// Constants for Uno board (use 19 and 18 for mega)
const int vccPin = A3; // +v and gnd provided through these pins
const int gndPin = A2;  
 
const int dataLength = 6;          // number of bytes to request
static byte rawData[dataLength];   // array to store nunchuck data

// uses pins adjacent to I2C pins as power & ground for Nunchuck
void nunchuckSetPowerpins()
{
  pinMode(gndPin, OUTPUT); // set power pins to the correct state
  pinMode(vccPin, OUTPUT);
  digitalWrite(gndPin, LOW);
  digitalWrite(vccPin, HIGH);
  delay(100); // wait for power to stabilize
}
 
// initialize the I2C interface for the nunchuck
void nunchuckInit()
{
  Wire.begin();                // join i2c bus as master
  Wire.beginTransmission(0x52);// transmit to device 0x52
  Wire.write((byte)0x40);      // sends memory address
  Wire.write((byte)0x00);      // sends sent a zero.  
  Wire.endTransmission();      // stop transmitting
}  
 
// Request data from the nunchuck
void nunchuckRequest()
{
  Wire.beginTransmission(0x52);// transmit to device 0x52
  Wire.write((byte)0x00);// sends one byte
  Wire.endTransmission();// stop transmitting
}

// Receive data back from the nunchuck, 
// returns true if read successful, else false
bool nunchuckRead()
{
  byte cnt=0;
  Wire.requestFrom (0x52, dataLength);// request data from nunchuck
  while (Wire.available ()) 
  {
    byte x = Wire.read(); 
    rawData[cnt] = nunchuckDecode(x);
    cnt++;
  }
  nunchuckRequest();  // send request for next data payload
  if (cnt >= dataLength) 
    return true;   // success if all 6 bytes received
  else
    return false; // failure
}

// Encode data to format that most wiimote drivers except
char nunchuckDecode (byte x)
{
   return (x ^ 0x17) + 0x17;
}
  
// return the value for the given item
int nunchuckGetValue(int item)
{
  if( item <= wii_accelZ)
    return (int)rawData[item]; 
  else if(item  == wii_btnZ) 
    return bitRead(rawData[5], 0) ? 0: 1;
  else if(item  == wii_btnC) 
    return bitRead(rawData[5], 1) ? 0: 1;   
}

Connect the nunchuck as shown in Recipe 13.6 but use the following sketch to test the library (if Arduino was running while you created the previous two files, quit and restart it so it will see the new library). If you’d like, you can create this as the file WiichuckSerial.ino in the folder examples/WiichuckSerial underneath the Nunchuck library folder to make it available as an example program.

/*
 * WiichuckSerial
 *
 *  Uses Nunchuck library to sends sensor values to serial port
 */

#include <Wire.h>
#include "Nunchuck.h"

void setup()
{
  Serial.begin(9600);
  nunchuckSetPowerpins();
  nunchuckInit(); // send the initialization handshake
  nunchuckRead(); // ignore the first time
  delay(50);
}

void loop()
{
  nunchuckRead();
  Serial.print("H,");       // header
  for(int i=0; i <  5; i++) // print values of accelerometers and buttons
  {
     Serial.print(nunchuckGetValue(wii_accelX+ i), DEC);
     Serial.write(',');
  }
  Serial.println();
  delay(20); // the time in milliseconds between sends
}

Discussion

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.

The major difference between the library code and the sketch from Recipe 13.6 is the addition of the Nunchuck.h header file that contains the function prototypes (Arduino sketch code silently creates prototypes for you, unlike Arduino libraries which require explicit prototypes).

Here is another example of creating a library; this one uses a C++ class to encapsulate the library functions. A class is a programming technique for grouping functions and variables together and is commonly used for most Arduino libraries.

This library can be used as a debugging aid by sending print output to a second Arduino board using the Wire library. This is particularly useful when the hardware serial port is not available and software serial solutions are not appropriate due to the timing delays they introduce. Here the core Arduino print functionality is used to create a new library that sends printed output I2C. The connections and code are covered in Recipe 13.5. The following description shows 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
 */
#ifndef i2cDebug_included
#define i2cDebug_included

#include <Arduino.h>
#include <Print.h>   // the Arduino print class

class i2cDebugClass : public Print
{
  private:
    int i2cAddress;
    byte count;
    size_t write(byte c);
  public:
    i2cDebugClass();
    bool begin(int id);
};

extern i2cDebugClass i2cDebug;   // the i2c debug object
#endif

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()
{
}

bool i2cDebugClass::begin(int id)
{
  i2cAddress = id;  // save the slave's address
  Wire.begin(); // join I2C bus (address optional for master)
  return true;
}

size_t i2cDebugClass::write(byte c)
{
  if( count == 0)
  {
    // here if the first char in the transmission
    Wire.beginTransmission(i2cAddress); // transmit to device
  }
  Wire.write(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;
  }
  return 1; // one character written 
}

i2cDebugClass i2cDebug;   // Create an I2C debug object
Note

The write method returns size_t, a value that enables the print function to return the number of characters printed. This is new in Arduino 1.0—earlier versions did not return a value from write or print. If you have a library that is based on Stream or Print then you will need to change the return type to size_t.

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 details on creating a library.

Upload the slave I2C sketch onto another Arduino board and wire up the boards as described in Recipe 13.5, and you should see the output from the Arduino board running your library displayed on the second board.

The following references provide an introduction to classes if C++ classes are new to you :

  • Programming Interactivity by Joshua Noble (O’Reilly; search for it on oreilly.com)

  • C++ Primer by Stanley B. Lippman, Josée Lajoie, and Barbara E. Moo (Addison-Wesley Professional)

16.6 Updating Third-Party Libraries for Arduino 1.0

Problem

You want to use a third-party library created for Arduino releases previous to 1.0.

Solution

Most libraries should only require the change of a few lines to work under Arduino 1.0. For example, any one or more of these header file includes:

  #include "wiring.h"
  #include "WProgram.h"
  #include "WConstants.h"    
  #include "pins_arduino.h"

should be changed to a single include of:

  #include "Arduino.h"
Note

The file names may be enclosed in either angle brackets or quotes

Discussion

Older libraries that don’t compile under Arduino 1.0 will usually generate one or more of these error messages:

source file: error: wiring.h: No such file or directory
source file: error: WProgram.h: No such file or directory
source file: error: WConstants.h: No such file or directory
source file: error: pins_arduino.h: No such file or directory

Source file is the full path the library file that needs to be updated. There will be a list of other errors following this due to the indicated file not being found in the 1.0 release, but these should disappear after you have replaced the old header names with Arduino.h. The definitions in these files are now included in Arduino.h and the solution is to replace includes for all of the above files with a single include for Arduino.h

If you want to run current versions of Arduino alongside earlier versions, you can use a conditional define (see Recipe 17.6):

#if ARDUINO >= 100
#include "Arduino.h"
#else
// These are the filenames that are used in the original version of library
#include "wiring.h"
#include "pins_arduino.h"
#endif

See Also

Third-party libraries that use Serial, Ethernet or other functionality that has changed syntax in Arduino 1.0 may require additional code changes.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.134.78.106