• Worldwide Shipping

  • 24/7 Customer Support

  • FAQ
  • Worldwide Shipping

  • 24/7 Customer Support

  • FAQ

How to write your own Arduino library?

Introduction

In the previous tutorial, we've met with 7 segment displays. Among everything else, we've learned why libraries are useful. Now is the time to write our own. We will sort out this lesson in files that need to be made to make the library functional and transparent.

The thing we want, and will do, are functions that write numbers from 0 to 9, a function that will shut down all segments on the display and a function that will turn the point on and off. Let's go...

The header file is saved with an .h extension, it's one of the two necessary files to make the library function. Bearing in mind that Arduino doesn't do that by itself, here we will define everything that we use in a library. We create a class that we can call in later on in Arduino IDE with all the variables and functions that we want to make available to the user (public)  and those internal ones that we will use to make the library functional (private).

class

What is a class? If you haven't met with the term class by now, it's basically a group of all functions and variables for a certain object. For example, let's take a male human as an object. Every male has or hasn't got certain characteristics like IQ, height, mass, height or moustaches. Looking from the programmers' point of view, IQ is a whole number variable int, height and mass can be float, and moustaches which you either have or you don't are going to be boolean.

With all that behind us,  let's get back to creating a library. Open your favorite text editor and let's get into it:

// creating a class that we will call in Arduino IDE
class Segment  
{
  // functions that user of the library works with
  public:
  // here we will set up a connection with Croduino/Arduino and display
  Segment(uint8_t pin1, uint8_t pin2, uint8_t pin3, uint8_t pin4, uint8_t pin5, uint8_t pin6, uint8_t pin7, uint8_t pin8);  
  void Broj(int n);  // function "broj" will have one parameter, number "n" which we want to show up
  void Tocka();  // function "tocka" will turn the dot on and off 
  void Ocisti();  // function "ocisti" turns off remaining segments
  // internal variables
  private:
  uint8_t _pin1;
  uint8_t _pin2;
  uint8_t _pin3;
  uint8_t _pin4;
  uint8_t _pin5;
  uint8_t _pin6;
  uint8_t _pin7;
  uint8_t _pin8;
  bool b;
};

Don't worry if you have some uncertainties, main part is located in the source file which we will get to in a second. Except for the above, the Header file has to have some more parts. It certainly is necessary to implement Arduino.h, which is automatically added when we compile the code, but not in the process of writing the library itself.

#include "Arduino.h"

This part greatly depends on the version of Arduino IDE which the user has installed. So you need to pay much more attention to this part, however, this will be enough for now.

It's a custom to add a small piece of code into the Header file that checks if the library has been added only once to the sketch. It is supposed to look like this:

#ifndef Segment_h
#define Segment_h

 // part for code

#endif

Finally, our Header looks like this:

/*
	Segment.h - Library for 7 segment display common cathode
	Created by e-radionica.com, 2016.
	*/

	#ifndef Segment_h
	#define Segment_h


 #include "Arduino.h"

	class Segment
	{
		public:
			Segment(uint8_t pin1, uint8_t pin2, uint8_t pin3, uint8_t pin4, uint8_t pin5, uint8_t pin6, uint8_t pin7, uint8_t pin8);
			void broj(int n);
			void tocka();
			void ocisti();
		private:
			uint8_t _pin1;
			uint8_t _pin2;
			uint8_t _pin3;
			uint8_t _pin4;
			uint8_t _pin5;
			uint8_t _pin6;
			uint8_t _pin7;
			uint8_t _pin8;
			bool b;
	};
#endif

Now we just need to save it. Let's make a new folder in, for  Windows OS, Documents - Arduino - Libraries and call it Segment, or pick your own name, it's optional. Arduino libraries are explained in detail here. It's important that all signs in the name ar in ASCII standard. Save the written code in the created folder and add the extension .h,  so the name looks something like this Segment.h. Make sure that the name has no other extensions besides .h, like .txt and simmilar.

Source files

Source file is a part where we store all of our code/logic, and it's written in C++ language. Even tho we've already explained the logic we want to write, feel free to take a peak in the 7 segment displays tutorial and remind yourself how to work with that. For starters we need to include Arduino.h and  Segment.h  which we  have just created. Again, ofcourse we write in a text editor.

#include "Arduino.h"
"include "Segment.h"

Great. It's time to write the logic for constructors created in  Header.

//CLASS  ::konstruktor (parametri) 
  Segment::Segment(uint8_t pin1, uint8_t pin2, uint8_t pin3, uint8_t pin4, uint8_t pin5, uint8_t pin6, uint8_t pin7, uint8_t pin8)
  {
	pinMode(pin1, OUTPUT);
	pinMode(pin2, OUTPUT);
	pinMode(pin3, OUTPUT);
	pinMode(pin4, OUTPUT);
	pinMode(pin5, OUTPUT);
	pinMode(pin6, OUTPUT);
	pinMode(pin7, OUTPUT);
	pinMode(pin8, OUTPUT);
	//
	_pin1 = pin1;
	_pin2 = pin2;
	_pin3 = pin3;
	_pin4 = pin4;
	_pin5 = pin5;
	_pin6 = pin6;
	_pin7 = pin7;
	_pin8 = pin8;
	//
	b = false;
  }

The first constructor "Segment" is classified as a Segment. He's being used to define on which pins of Croduino/Arduino are pins from the 7 segment display being connected on. If the display is connected in the same way as in the 7 segment display tutorial, this constructor in Arduino IDE will be called in like this:

/*
Konstruktor proizvoljno ime      pinovi displaya
                            (pin1, pin2, ...         )
                                 pinovi Croduina
---------------------------------------------------- */
Segment         segment     (  2,    3,   4,5,6,7,8,9);

pin is defined because we want to separate private variables from those which the user of the libraries uses. So, if the user makes some changes in public varijables it won't interfere with the library's functionality.

b = false; is used to turn on or turn off the dot on the display. Its constructor will look like this:

void Segment::tocka()
{
	b = !b; // saves switched value
	digitalWrite(_pin8, b);  // it will turn on the dot if it's off and vice versa
} 

We've left with the constructor named broj. It's gonna take a number between 0 and 9 as a parameter and write it on the display. It looks like this:

void Segment::broj(int n)
{

  switch(n)
  {
    case 0:
	digitalWrite(_pin1, 0);
	digitalWrite(_pin2, 1);
	digitalWrite(_pin3, 1);
	digitalWrite(_pin4, 1);
	digitalWrite(_pin5, 1);
	digitalWrite(_pin6, 1);
	digitalWrite(_pin7, 1);
	digitalWrite(_pin8, 0);
	break;

//... etc. we write it for every single number
   }
}

In Arduino IDE we call it in the following way:

// turn on number 0
segment.broj(0);

segment is an object that we created with the help of Segment constructors couple of lines above
broj is a constructor that we've just created
0 is a number that we want to show on the screen

When we write all of the .cpp, the file looks like this:

/*
	Segment.cpp - Library for 7 segment display common cathode
	Created by e-radionica.com, 2016.
	*/

#include "Arduino.h"
#include "Segment.h"

Segment::Segment(uint8_t pin1, uint8_t pin2, uint8_t pin3, uint8_t pin4, uint8_t pin5, uint8_t pin6, uint8_t pin7, uint8_t pin8)
{
	pinMode(pin1, OUTPUT);
	pinMode(pin2, OUTPUT);
	pinMode(pin3, OUTPUT);
	pinMode(pin4, OUTPUT);
	pinMode(pin5, OUTPUT);
	pinMode(pin6, OUTPUT);
	pinMode(pin7, OUTPUT);
	pinMode(pin8, OUTPUT);
	//
	_pin1 = pin1;
	_pin2 = pin2;
	_pin3 = pin3;
	_pin4 = pin4;
	_pin5 = pin5;
	_pin6 = pin6;
	_pin7 = pin7;
	_pin8 = pin8;
	//
	b = false;
}

void Segment::broj(int n)
{

switch(n)
{
case 0:
	digitalWrite(_pin1, 0);
	digitalWrite(_pin2, 1);
	digitalWrite(_pin3, 1);
	digitalWrite(_pin4, 1);
	digitalWrite(_pin5, 1);
	digitalWrite(_pin6, 1);
	digitalWrite(_pin7, 1);
	digitalWrite(_pin8, 0);
	break;

case 1:
	digitalWrite(_pin1, 0);
	digitalWrite(_pin2, 0);
	digitalWrite(_pin3, 0);
	digitalWrite(_pin4, 1);
	digitalWrite(_pin5, 0);
	digitalWrite(_pin6, 0);
	digitalWrite(_pin7, 1);
	digitalWrite(_pin8, 0);
	break;

case 2:
	digitalWrite(_pin1, 1);
	digitalWrite(_pin2, 0);
	digitalWrite(_pin3, 1);
	digitalWrite(_pin4, 1);
	digitalWrite(_pin5, 1);
	digitalWrite(_pin6, 1);
	digitalWrite(_pin7, 0);
	digitalWrite(_pin8, 0);
	break;

case 3:
	digitalWrite(_pin1, 1);
	digitalWrite(_pin2, 0);
	digitalWrite(_pin3, 1);
	digitalWrite(_pin4, 1);
	digitalWrite(_pin5, 0);
	digitalWrite(_pin6, 1);
	digitalWrite(_pin7, 1);
	digitalWrite(_pin8, 0);
	break;

case 4:
	digitalWrite(_pin1, 1);
	digitalWrite(_pin2, 1);
	digitalWrite(_pin3, 0);
	digitalWrite(_pin4, 1);
	digitalWrite(_pin5, 0);
	digitalWrite(_pin6, 0);
	digitalWrite(_pin7, 1);
	digitalWrite(_pin8, 0);
	break;

case 5:
	digitalWrite(_pin1, 1);
	digitalWrite(_pin2, 1);
	digitalWrite(_pin3, 1);
	digitalWrite(_pin4, 0);
	digitalWrite(_pin5, 0);
	digitalWrite(_pin6, 1);
	digitalWrite(_pin7, 1);
	digitalWrite(_pin8, 0);
	break;

case 6:
	digitalWrite(_pin1, 1);
	digitalWrite(_pin2, 1);
	digitalWrite(_pin3, 1);
	digitalWrite(_pin4, 0);
	digitalWrite(_pin5, 1);
	digitalWrite(_pin6, 1);
	digitalWrite(_pin7, 1);
	digitalWrite(_pin8, 0);
	break;

case 7:
	digitalWrite(_pin1, 0);
	digitalWrite(_pin2, 0);
	digitalWrite(_pin3, 1);
	digitalWrite(_pin4, 1);
	digitalWrite(_pin5, 0);
	digitalWrite(_pin6, 0);
	digitalWrite(_pin7, 1);
	digitalWrite(_pin8, 0);
	break;

case 8:
	digitalWrite(_pin1, 1);
	digitalWrite(_pin2, 1);
	digitalWrite(_pin3, 1);
	digitalWrite(_pin4, 1);
	digitalWrite(_pin5, 1);
	digitalWrite(_pin6, 1);
	digitalWrite(_pin7, 1);
	digitalWrite(_pin8, 0);
	break;

case 9:
	digitalWrite(_pin1, 1);
	digitalWrite(_pin2, 1);
	digitalWrite(_pin3, 1);
	digitalWrite(_pin4, 1);
	digitalWrite(_pin5, 0);
	digitalWrite(_pin6, 1);
	digitalWrite(_pin7, 1);
	digitalWrite(_pin8, 0);
	break;
}
}

void Segment::tocka()
{
	b = !b;
	digitalWrite(_pin8, b);
} 

void Segment::ocisti()
{
	digitalWrite(_pin1, 0);
	digitalWrite(_pin2, 0);
	digitalWrite(_pin3, 0);
	digitalWrite(_pin4, 0);
	digitalWrite(_pin5, 0);
	digitalWrite(_pin6, 0);
	digitalWrite(_pin7, 0);
	digitalWrite(_pin8, 0);
}

The only thing that remains is to save the file in the same way as Header. We save it in the same folder, but this time with .cpp extension.

Keywords

Keywords is a  .txt file that allows Arduino IDE to recognize keywords from our library and changes their color in the editor to make it easier to work with. It would look something like this:

Segment KEYWORD1
broj 	KEYWORD2
ocisti	KEYWORD2
tocka	KEYWORD2

We save it in the same folder as the previous two files with  .txt extension.

Arduino IDE and example of a code

If we want the example of libraries used to appear in Arduino IDE File-Examples we need to create a subfolder called examples. This is how it will look like in Windows OS:

Arduino IDE libraries

In subfolder examples, we will save examples of libraries' usage. You can write it in Arduino IDE software, and as an example, we will write a countdown on the display.

//add the created library
#include "Segment.h"

//define the Croduino/Arduino pins according to the tutorial
Segment segment(2,3,4,5,6,7,8,9);

void setup() {
}

void loop() {
  // countdown in loop
  for(int i=9; i>=0; i--)
  {
    segment.broj(i); // call numbers from 9 to 0
    delay(1000);     // stop for 1 second
  }

  // in the end, blink couple of times
  for(int j=0; j<3; j++)
  {
    segment.ocisti();
    segment.tocka();
    delay(500);
    segment.broj(0);
    segment.tocka();
    delay(500);
  }
}

Save this code in the examples folder. After that, it is necessary to close and re-open the Arduino IDE so we could use the library.

We hope that we didn't complicate this simple procedure of making your own Arduino library. If you have any difficulties or upgrades for this tutorial, we're looking forward to your comments.

Leave a Reply