Create Libraries

From Wiring

Jump to: navigation, search

The Wiring core is very focused and minimal, but is easily extended to match additional desires and needs. If you write your own libraries for Wiring, please consider sharing this code with the community. Current libraries are listed online .

Contents

How to write libraries for Wiring?

So you want to write a Library for Wiring? -Great!

Here is a little tutorial on how to write one.

You will learn the basic syntax rules for c++ class declaration and definition and I will summarize the conventional Wiring function and variable naming.

For this tutorial we will implement a library called WiringLED 'we will do some fun stuff with the built-in LED on your Wiring board' We will make it turn on, off and make it blink.

What is a Library?

A Library is a collection of instructions that are designed to execute a specific task. Good libraries describe the tasks it tries to solve by the name of the library itself, and the names of the functions associated to the library.

This is because the library should be intuitive to use, and all names should describe, in an efficient way, all questions regarding what, when, and where, but should conceal the how.

On Wiring the libraries often serve as a wrapper around the Wiring Framework language to enhance code readability and user experience.

What are the Wiring conventions?

The Wiring libraries uses a UppercaseUppercase convention for Library names, and lowercaseUppercase naming convention for the functions. What this means is that our library has/should get the name WiringLED (not wiringLED for instance), and the functions will be named on() and off(). I could've selected turnOn() and turnOff(), but I've selected the shortest because it is as descriptive, but in addition it is shorter. [short code == less probability for typos]

It is important to remember that you do not need a Library. It is just a way to make some code easiy to use again if you need to.

Why do we have libraries?

  • Simplify usage and/or organization of code
  • Enhance code readability
  • Decentralize logic
    • Main sketch can now simply state library.action() instead of coding the equivalent in the sketch.

How do we write libraries?

Define the functionality your Library has to provide

For our Library we've decided on these functions:

  • on()
  • off()
  • blink(int time)

This should be the premise for our library. At this point, we do not care how the on() should work, only that it should exist.

Make a proof of concept sketch

Before implementing a new class I usually find it very useful to test the idea in a sketch. Try a few different implementations, see what uses the least amount of space, and what seems simplest in use. Select the solution that compromises these two in a suitable way.

An experience I've made is that if one has something slightly similar to work from, that is often beneficial. For our Library, one immediatly thinks of the Blink right? The Hello World! of µCs. So, go ahead and start the Wiring IDE and open the File->Sketchbook->Examples->Digital->Blink.

The first thing we'll do, is to cut the code inside loop(), and paste it into a new function called void blink(). I suspect this is not surprising, being that we know this code will blink the LED connected to pin WLED. Now, write blink(); inside the loop, so that the code that once was inside the loop() and now is located inside blink, gets executed (because loop calls blink).

Now, you should have a sketch looking like this:

int ledPin = WLED;                // LED connected to digital pin WLED
 
void setup()                    // run once, when the sketch starts
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
}
 
void loop()                     // run over and over again
{
  blink(); //call the code that makes the LED blink
}
 
//make the LED blink
void blink(){
  digitalWrite(ledPin, HIGH);   // sets the LED on
  delay(1000);                  // waits for a second
  digitalWrite(ledPin, LOW);    // sets the LED off
  delay(1000);                  // waits for a second
}

The next two steps will be to add the void on(); and the void off();. These will be really simple functions, becuase they will actually just 'wrap' digitalWrite(WLED,HIGH) and digitalWrite(WLED,LOW) respectively.

Go ahead and try to write these functions. You should end up with something like:

//turn the LED on
void on(){
  digitalWrite(ledPin,HIGH); //set the pin HIGH and thus turn LED on
}
 
//turn the LED off
void off(){
  digitalWrite(ledPin,LOW); //set the pin LOW and thus turn LED off
}

We have one more thing to fix. As the code is now, the blink() will always use two seconds, but we wanted to pass the number of microseconds as an argument. Additionally we'll want to remove the redundant code that turns a led on and off. We'll replace those redundant calls with on() and off(). You probably know how to write functions that has parameters, but here it is:

//make the LED blink
void blink(int time){
  on();						    // sets the LED on
  delay(time/2);                // waits for a second
  off();					    // sets the LED off
  delay(time/2);                // waits for a second
}

Now you have enough code to implement all the desired functionality.

Complete Concept Sketch

int ledPin = WLED;                // LED connected to digital pin WLED
 
void setup()                    // run once, when the sketch starts
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
}
 
void loop()                     // run over and over again
{
  blink(2000);  //call the code that makes the LED blink
}
 
//turn the LED on
void on(){
  digitalWrite(ledPin,HIGH); //set the pin HIGH and thus turn LED on
}
 
//turn the LED off
void off(){
  digitalWrite(ledPin,LOW); //set the pin LOW and thus turn LED off
}
 
//make the LED blink
void blink(int time){
  on();						    // sets the LED on
  delay(time/2);                // waits for a second
  off();					    // sets the LED off
  delay(time/2);                // waits for a second
}

Download the source for this tutorial

The next step is to:

Learn c++ class syntax

There are a lot of resources on this topic, but generally the class are split into two files.

  1. The declaration, referred to as the header file. 'WiringLED.h' will indicate that the file declared the class WiringLED. Declaration is the process of defining what the class should do.
  2. The implementation, referred to as the source file. 'WiringLED.cpp' indicates that the file implement the declared functions and variables from "WiringLED.h". Implementation is the process of writing the code, that determines how the declared functions are imlemented.

WiringLED Header

#ifndef WiringLED_H
#define WiringLED_H
 
#include <Wiring.h>
 
class WiringLED {
public:
	WiringLED();
	~WiringLED();
	void on();
	void off();
	void blink(int time);
};
 
#endif

'Code Analysis:'

  • Lines 1 and 2 are referred to as an guard

It basically prevents the code to get included into the program binary multiple times.

  • Line 4 includes the Wiring code to our library. This enables us to use the pinMode, digitalWrite, delay etc.
  • Line 6 is the beginning of the class itself.
  • Line 7 uses the public keyword
  • Line 8 and 9 are called constructor and destructor, they are responsible for setting up your library (construct), and delete it (deconstruct)
  • Line 10 declares the function 'void on();' , this will turn the LED on
  • Line 11 declares the function 'void off();' , this will tudn the LED off
  • Line 12 declares the function 'void blink(int time);' , this will blink the LED in 'time' milliseconds.
  • Line 13 is the end of the class.
  • Line 15 ends the #ifndef preprocessor directive

WiringLED Source

You will see that this source will be very much like the concept sketch. However, I've changed some datatypes, and the rest is just the c++ syntax.

[++Notice the :: , it is called the 'scope resolution operator'++]

#include "WiringLED.h" //include the declaration for this class
 
const byte LED_PIN = WLED; //use the LED @ Wiring pin WLED, this should not change so make it const (constant)
 
//<<constructor>> setup the LED, make pin WLED an OUTPUT
WiringLED::WiringLED(){
    pinMode(LED_PIN, OUTPUT); //make that pin an OUTPUT
}
 
//<<destructor>>
WiringLED::~WiringLED(){/*nothing to destruct*/}
 
//turn the LED on
void WiringLED::on(){
	digitalWrite(LED_PIN,HIGH); //set the pin HIGH and thus turn LED on
}
 
//turn the LED off
void WiringLED::off(){
	digitalWrite(LED_PIN,LOW); //set the pin LOW and thus turn LED off
}
 
//blink the LED in a period equal to paramterer -time.
void WiringLED::blink(int time){
	on(); 			//turn LED on
	delay(time/2);  //wait half of the wanted period
	off();			//turn LED off
	delay(time/2);  //wait the last half of the wanted period
}

Implementation

Selecting public, protected or private

A common 'rule of thumb' is to make all data as private as possible. For Wiring that will often result in all variables declared private, and most functions defined public.

Selecting datatypes / returntypes

Since Wiring boards have limited resources, it is recommended to select the 'smallest' variables that fits the bill. An Wiring pin will (probably) never become above 255. So in that case using a byte is sufficient, and preferable.

Selecting variable- / functionnames

The Wiring API has established some cues for how to name a variable or function. Start lower case, and indicate new words with an upper case letter. 'myDescriptiveVariable'

Writing examples

Be sure to create examples that are as self describing as possible. Additionally it should be made an effort to demo most of the functions.

Blink Example
#include <WiringLED.h>
 
WiringLED led;//initialize an instance of the class
 
void setup(){/*nothing to setup*/}
 
void loop(){
  led.blink(2000);//stay one second on, then a second off
}

keywords.txt

Remember to implement this file, as it makes using your library a lot easier. Our library has four names that needs highlighting. Those are:

  • WiringLED
  • on
  • off
  • blink

And they are implemented in keywords.txt as:

WiringLED	KEYWORD1
on	KEYWORD2
off	KEYWORD2
blink	KEYWORD2

Debugging

Remember #include <Wiring.h>

You will get a series of errors if you've forgot to include the Wiring core, and trying to use some of the Wiring functions or datatypes. It is only necessary to include the Wiring.h in you library .h, your .cpp will include it because it includes your header.

Delete object file and recompile between each alteration of header and/or source

When changes are made in the header or the source, those changes are not automatically incorporated in the object file of you library. To be sure that your changes are compiled and used, delete the WiringLED.o and recompile a sketch in the Wiring IDE.

Learn to interpret the Wiring IDE debugger / compiler.

It can be a timesaver to take an hour for testing, and create errors deliberately, so you know what the error messages are caused by for later reference.

Personal tools