Nov 16, 2014

How to Create an Arduino Library

How to Create an Arduino Library

In order to re-use arduino code and to make it more easily shared, I wanted to learn to create libraries for Arduino environment. There is an example of making a library for arduino on the arduino site, but there were several questions I had after studying the page and trying to use it as an example. Here are some additional details and notes about how I went about it. I focus on little details of syntax and naming, as these were the source of the problems in getting the library to be recognized and to run without errors.

If you want to download the the latest verion of this tutorial's code
   Get TextGraph_howto library here. (generates an ascii text graph directly to the arduino's monitor.)
   For the more complete (non-tutorial) library, use TextGraph, found here (updated 2014-12-30).

Writing the function: what language?

Libraries are generally written in C++, but they can also be written directly in Wiring (the arduino's sketch language), with only a single modification. The code goes in the mylibraryname.cpp file, but supporting pieces to define the functions must go in the mylibraryname.h file and follow the C++ class syntax. The function(s) defined should also be included in the keywords.txt file so that they show as highlighted keywords in the sketch that uses the library. I found a good explanation of types of keywords in Spencer Blevin's post.

I have based my example on a graphing function I use frequently to visualize data from analog inputs where the output is a text (ascii character) graph displayed to the monitor or to a terminal program. I describe this code in another post.

I thought this would be a good candidate for a library because its function was simple to understand and it did not depend on specific shield hardware. I implemented this as two functions: dotgraph() to make the graph elements, and spc() to generate a string of n characters (spaces in the graph pictured above). Note that the purpose is to add the graph after an existing column of numbers so that it is uncomplicated by the type or formatting of the numbers and is easily disabled in the output.


Library Parts

A typical library has a .h and .cpp file at minimum,  but a complete library has a keywords.txt file and one or more examples.
 
Folder contents within the library folder

Once a working library is created and placed within the library folder, you must re-launch the Arduino IDE to see the newly added library. If there are examples, they will show up in the library menu.

Two example files supplied with the "howto" library show in the menu.

Creating the library code

I first wrote a sketch that included the graphing code. Once that worked, I copied the functions into the .cpp file using a plain text editor. The debugging process required updating the .h and .cpp files to get them syntactically correct, saving and then re-running my sketch.

While creating an example sketch, note that the file must be located somewhere other than its final destination within the library folder, because it is write-protected while in that location. I moved mine to the Arduino folder while writing; then put back in the examples folder when completed. I then opened each from the the examples menu to verify that they worked properly.

The collection of one or more functions resides in a class which is named TextGraph_howto. It is used only to reference the class within your sketch, making the internal functions accessible (line 14 of the Arduino sketch). The folder name, the .h file and .cpp file share the same name. The convention is to capitalize the library name and embedded words. The functions are camel case (no initial cap): in this example, there are two functions defined which could be used in the sketch: dotGraph() and barGraph(). (Note that I have violated the library name convention with the "_howto" to distinguish the tutorial files.)

Note on the same line in the sketch, the class is given a name. I selected a short name "TG" for this example.
In line 32, the function dotgraph() is called. "TG." is added as a prefix to indicate that the function is located in the library rather than in the sketch.

Include the function names in the keywords.txt file so that they will show up with syntax coloring as though they were defined key words in the sketch. Format is functionName keywordtype.

The code listings are below for the .h and .cpp files and a minimal sketch to use the library. (Recommend using the link to the code rather than extracting from post, as the link will likely be more current.)

The .h file

This defines the structure, indicating the functions and their arguments

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 *** This version is a tutorial for creating an Arduino Library and is more limited;
     For a more complete one, see "TextGraph" at engineeringnotes.blogspot.com
 
 TextGraph_howto - simple vertical graphing using text in monitor or a terminal window.
 Created by David Smith, 2014
 Released into the public domain.

 - arduino library is a C++ Class
 - has a definition portion in the .h file
 - and code in the .cpp file
 */

#ifndef TextGraph_howto_h  // avoid invoking more than once
#define TextGraph_howto_h
#include "Arduino.h" // provide access to core functions

class TextGraph_howto
// Makes simple ascii-based streaming dot and bar graphs to the monitor or terminal
{
public:
  TextGraph_howto(int nn);

  void dotGraph(int nn);                 // graph an integer as a dot (or vertical line)
  void barGraph(int nn);                 // graph an integer as a horizontal bar

private:
  void spc(byte n, char c);
};

#endif

The .cpp file

This contains the code of the functions. Take care that the naming match exactly for all of the files.
Things to note: Line 14 is the constructor. The syntax is className::className. The same name is used in the function definitions className::functionName(arguments).

To convert your arduino code to .cpp library code, the only modifications are to add the class constructor (lines 14-16) and to add the className:: in front of each of the functions (lines 19, 24, 30).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*
 *** This version is a tutorial for creating an Arduino Library and is more limited;
     For a more complete one, see "TextGraph" at engineeringnotes.blogspot.com
    
 - arduino library is a C++ Class
 - has a definition portion in the .h file
 - and code in the .cpp file
 */

#include "Arduino.h"
#include "TextGraph_howto.h"

// mini ascii vertical "dot" graph
TextGraph_howto::TextGraph_howto(int nn) {     // <<constructor>>
  ;
}
// <<NO destructor>>

void TextGraph_howto::dotGraph(int nn) {
  spc(byte(nn),' ');            // local fctn prints a row of n chars
  Serial.print("*\r\n");     // character for the graph
}

void TextGraph_howto::barGraph(int nn) { // default chars
  spc(byte(nn),'-');                  
  Serial.print("*\r\n");      // character for the graph
}

//--- print n characters in a row (spaces usually)
void TextGraph_howto::spc(byte numchars, char rowchar) {
  byte i;
  byte maxWidth = 110;  // this can be adjusted as desired
  if (numchars > 0 && numchars < maxWidth) {
    for (i = 0; i < numchars; i++) {
      Serial.print(rowchar);
    }
  }
}

An Arduino example sketch to use the library

This sketch calculates values for a sine wave and then calls the dotGraph() function from the TextGraph_howto library to display it in the monitor window.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// generate an ascii graph to the monitor, Example sketch for dotGraph()
// David Smith, 2014. This example is released to the public domain

// Starting with an arduino sketch, to use the library function you must:
// 1. Import the library (that's the #include line)
// 2. Create and name an instance of the library (this makes all of the internal public functions of the lib available)
// 3. call the library function with the name of the library instance: often called "myLibName" (I used "TG" here for brevity).

#include <TextGraph_howto.h>

// global variables
static char cbuf[16];

TextGraph_howto TG(1);  // create an instance of TextGraph_howto and give it a name. 
// -----------------------------------------------------------------------
void setup(void) {
  Serial.begin(9600);  // set preferred baudrate
  Serial.println("\nPrint a numerical value and add a graph");
}

void loop(void) {
  unsigned int i;
  static float tstep = 0.01;
  static float t = 0;
  float y;  
  int y_scaled;

  y = 1.0 * sin(6.2832 * 3.0 * t);  // a simple function to graph
  dtostrf(y, 8, 4, cbuf);           // -nnnnnn.nn for consistent format  //dtostrf(FLOAT,WIDTH,PRECISION,BUFFER); gist.github.com/2343665 
  Serial.print(cbuf);               // print the actual function's value
  y_scaled = 50*(y + 1);            // scale function to fit Monitor window: set window at least as wide as graph range
  TG.dotGraph(y_scaled);            // dotGraph function, simplest form (Adding the "TG." in front means to look for dotGraph() fctn in library
  t = t + tstep;
  delay(200);                       //control output rate to screen
}