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...
Header
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:
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.