Table of Contents
Introduction
Arduino boards can simplify creating projects, aided by the rich Arduino libraries out there, for almost any add-on you wish to attach.
Ever wanted to create a custom Arduino library? Me too : ) This blog post goes through the steps that I took, in case it helps others.
I won’t focus on C++ (that’s what Arduino code, and Arduino libraries are written in), but the aim is to describe all the steps needed to create a simple library which extends Arduino projects with a feature called Megatest.
The feature doesn’t do much! For this example, the Megatest library will be used to toggle pins on and off. An end user will be able to type the following in their code:
#define RELAY_PIN 7
Megatest myrelay(RELAY_PIN);
myrelay.togglePin();
myrelay.togglePin();
The above code will toggle a relay pin on, and then off. Obviously, this is very trivial since one may as well just use the existing Arduino functions pinMode and digitalWrite to achieve the same result.
You could use the information in this blog post as a template for creating custom libraries. C++ experts will be able to produce far better code than me.
The blog post also goes through how the Arduino library can be potentially tested without any Arduino at hand. The benefit of this is that time is saved. You could test on your PC, and then when you’re ready, import the new library into the Arduino development environment, and upload example code into a real Arduino. I’ve not seen such an Arduino workflow described anywhere, so I had to create it as I went, it is quite simple and might not suit everyone. I think it’s not a bad approach, however.
If you wish to play along, you don’t need an Arduino. All you need to do is to go to any Linux machine and type the following at the terminal:
mkdir -p development
cd development
git clone https://github.com/shabaz123/simpleArduinoLibProj.git
You now have everything you need to work through the blog post, and learn how to create an Arduino library, and how to test it.
Note that there's no need to copy-paste code from this blog post; it's only shown for explanation, and if you need to copy-paste, you can directly access all the latest code from the simpleArduinoLibProj GitHub page.
Library File Structure
If you look at the code on your Linux machine, you’ll see a few folders and various files as shown below. All the blue folder names and the black files form the Arduino library. If those blue and black items were placed in a zip file, then you could upload that zip file into your Arduino integrated development environment (IDE).
What are the orange items there? They mostly form the test harness so that the Arduino library can be tested directly on a Linux box, saving time before you need to actually test with a real Arduino.
Examining the Library Code
The simplest Arduino library might only need one C++ source file (.cpp suffix) and one header file (.h suffix). If your library was to be called Megatest, then the files would be named Megatest.cpp and Megatest.h as can be seen from the earlier directory listing.
Since I didn’t want the example to be too trivial, there are a couple of additional files that I named extracode.cpp and extracode.h and of course you could rename them, and create as many additional files as desired.
Ordinarily, you’d spend some time designing what you wish the library to look like; for instance, a software developer will want to know what data is to be passed, where the information will be stored, what interfaces you want, and so on. I’m going to skip all that and show what might be the first bit of code the developer may write: the Megatest header file. You could copy that for any custom Arduino library and then edit it to suit your needs. However, please don’t assume I’m writing good C++ code here. Comments to describe the functions and parameters would definitely not go amiss.
Megatest Header File
Here’s an explanation of that Megatest.h file:
The lines containing the text MEGATEST_HEADER_FILE are essential to prevent compilation errors when many source files try to include the same header file.
You’ll almost certainly want to include the Arduino.h file as I have done. There’s no harm adding it even it is not used. The stdint.h line is required to be able to use variable types like uint8_t, so again that can always be included and it will be benign if not required.
The Megatest functionality that is to be exposed to the Arduino coder is listed within the public section of the class definition. Obviously, the togglePin function is needed for the purposes of the feature, but there’s also a function called pinOff just to demonstrate that more than one function can be created there. The first two functions listed under the public keyword are known as constructors. Every time you type something like Megatest mypin; the constructor code will execute. The reason for having two constructors is that the second one allows the user to specify the particular pin number at the time the object is created. The coder would need to type something like Megatest mypin(7); to do that.
Everything under the private keyword are things not exposed to the Arduino coder; the private items are used internally only, within the Megatest functionality. The two things listed are the pin number, and the current state, in variables called mPinNum and mPinState respectively. It’s an optional convention to start the variable names with the character m, to signify ‘member’.
Now that the header file has been created, the Arduino library creator would implement the actual C++ code, in the Megatest.cpp file.
Megatest Source File
The entire Megatest.cpp file contents are shown below.
Following the code above step-by-step; it’s mandatory to include the previously written header file. Next, all public and private functions are implemented. You can see that the default constructor sets member variable mPinNum to LED_BUILTIN. If the user specifies a pin number, then the second constructor executes, so that mPinNum stores the user-desired pin. The constructor sets the pinMode and then sets the pin low using digitalWrite.
The togglePin function checks the value of mPinState and sets the pin HIGH or LOW accordingly.
Finally, the pinOff function calls a new function called pin_off_function, which is just to demonstrate that some functions can be in other source files; pin_off_function resides in the extracode.cpp file as will be seen next.
Additional Code Files
It makes sense to split off code into separate files, to aid in readability and code maintenance. The extracode.h header file contains the pin_off_function definition.
The extracode.cpp file contains the implementation of that function, and it’s self-explanatory:
That’s it! That is essentially all the coding that is needed for the Arduino library. However, it makes sense to also create an example .ino file, to aid newcomers to your new library. That is discussed next.
Example .ino File
When using the Arduino IDE, for each library, it is usually possible to try out a ready-made example, by clicking on File->Examples. Those examples are part of each library bundle. This section of the blog post describes how to create an example for the Megatest library.
The .ino file resides in a folder inside the examples folder, and the folder and file are named according to whatever you wish the example to be called; MegatestExample.ino for instance.
The code shows the user how to use Megatest. First, the user needs to include the Megatest.h header file. The following line is used to create an object:
Megatest led;
Then, in the loop function, the togglePin function is executed for the object.
The above example should be sufficient to run on any Arduino board, since they all contain a default built-in LED. When run, the LED should switch on for a tenth of a second, and then switch off for a second, and then repeat indefinitely.
Properties File
There is one last file that is essential for an Arduino library, it is called library.properties and looks like this:
The name property needs to include the name of the library as the first word. Since I want my library to be called Megatest, I set the name property to Megatest Library.
An e-mail address is used within the maintainer property, you can use a dummy e-mail address.
The category property needs to be set to one of the following:
Display, Communication, Signal Input/Output, Sensors, Device Control, Timing, Data Storage, Data Processing or Other.
Some libraries might not work with all Arduino boards, in which case the architectures property can be modified by consulting the Arduino online documentation. I left it at * since Megatest works on all Arduino boards.
The includes property needs contain the header file name for the functionality that is exposed to the Arduino user. Usually that would be the header file with the same name as the library.
The library contents are now complete. If you zipped up all the files discussed so far, you’d have a finished library. However, it’s not tested! The next part of the blog post explains how to do that.
Testing the Library on a PC
There may be Arduino simulators that could be useful for testing library functionality. However, I’m going to discuss a simpler sort of simulation, that doesn’t require any special software, and instead relies on the user writing their own replacement for each Arduino function that the library makes use of. This method won’t meet all needs, but it does provide for extremely quick testing as you code, until you are ready for more intensive simulation or running on actual Arduino hardware.
In order to test the library in this simpler way, you’ll need a main.cpp file.
Main code
Examining that file, you can see that it includes the Megatest header file, and then constructs an object called mt using the line:
Megatest mt(100);
The above uses a pin number 100 which might not exist on many Arduino boards! It’s of no consequence, because we are not using a real Arduino. Any number can be used.
After that, the main.cpp code simply exercises the togglePin and pinOff functions, and printf statements are used to display what’s happening.
Faking Arduino Library Functionality
As you’ll recall, the Megatest library uses functions such as pinMode and digitalWrite, which require the default Arduino library to be included. On a PC, that library doesn’t exist. To work around that, a cut-down Arduino library file can be DIY’d.
The following code was created in a file called Arduino.h:
The Megatest library only uses pinMode and digitalWrite functions, so those are required to be created. A few standard Arduino definitions such as LED_BUILTIN, HIGH and LOW are also needed. The precise value doesn’t matter, since we are only simulating; there’s no physical LED or GPIO exposed on a PC that can be controlled.
The entire Arduino.cpp file contents are shown below. It’s very simple, all it does is print to the screen whenever pinMode or digitalWrite is executed.
All the code to test the Megatest library is complete. We now need to tell the PC how to compile it all. That’s done with a CMakeLists.txt file.
CMakeLists.txt File
The CMakeLists.txt file is used to tell the PC how to compile all the code. All the source files (.cpp) need to be contained in the file. I’m not very knowledgeable with the cmake system that uses this file, and I’m sure there is a way to automatically add all the .cpp files, but I don’t know it.
Building the Code
Go to the src folder, and then create a build folder within there, if it doesn’t already exist, and go inside the build folder.
cd src
mkdir -p build
cd build
If the build folder already exists, clear out the contents of it, using (make sure you’re in the correct folder!):
rm -rf *
Next, create something known as a Makefile, by typing:
cmake ..
Finally, build the code by simply typing:
make
If all goes well, an executable file called megatest will be created. If you encounter any problems, you may need to install cmake, and/or gcc on your Linux machine.
Running the Test Code
Run the executable file by typing:
./megatest
The main.cpp code described earlier is supposed to toggle a pin several times, and then set the pin low. When the test code is run, since there is no GPIO pin on the PC, text output will be displayed. You’ll see text indicating each time any pin activity occurs.
The tests are complete! Now you are ready to bundle the library into a .zip file, and then import it into the Arduino IDE, and test on a real Arduino.
Bundling up the Library into a Zip File
If you refer back to the earlier directory listing screenshot near the start of the blog post (in the Library File Structure section), everything that is in black and blue in that screenshot needs to be part of a zip file; the orange items must not be a part of it. To make like easier, I wrote some Python code that will automate work of preparing the zip file.
You’ll need to ensure Python is installed on your Linux machine, and also a utility called zip. If you’re using Ubuntu Linux, install zip by typing the following as super-user (or prefix both of these lines with sudo:
apt-get update
apt install zip
To run the Python code, first locate it, it is called make_arduino_library.py. Make sure it has executable permission by typing:
chmod 755 make_arduino_library.py
Run it by typing:
./make_arduino_library.py
If all goes well, you’ll see the following output:
You should now see that a folder called megatest_library-1.0.0 has been created in the development folder, and a zip file will be there too, called megatest_library-1.0.0.zip.
Importing the Library into the Arduino IDE
Click on Sketch->Include Library->Add .ZIP file.
Navigate to the megatest_library-1.0.0.zip file that was created in the previous section. After a brief pause, a message will appear: Library installed!
Running an Example Arduino Program
Click on File->Examples->Megatest Library->MegatestExample and you should see the MegatestExample.ino file appear. Click on the check-mark icon in the Arduino IDE, and the code should successfully build:
If you have an Arduino handy to test with, you can try it out, and the built-in LED should blink, demonstrating that the Megatest library is functioning.
Summary
A lot of the ease-of-use for the Arduino comes from the vast amount of Arduino libraries that are out there. You could create your code to run as a library, allowing you to more easily reuse it, or to offer it to others to make use of.
All that’s required is a single .cpp source code file, and a .h header file, and a library.properties file, all zipped up. Optionally, you can also include an example .ino file to demonstrate to users how to make use of the library.
It is possible to test the library by creating a few more files, and the advantage is that you can quickly test on a PC, without needing to upload to Arduino hardware, until you are fairly sure from these simple tests that you're ready to move on to the testing on real hardware.
A Python script was used to build up the final zip file.
If you have followed along with this blog post by trying it out, then hopefully, you have now successfully created and tested an Arduino library.
Thanks for reading!
Top Comments