Kako napisati vlastiti Arduino library

Uvod

 
U prijašnjoj lekciji upoznali smo se s 7-segmentnim displayima. Između ostalog, naučili smo zašto je library dobra stvar. Na redu je i da napišemo svoj prvi library. Lekciju ćemo podjeliti prema datotekama, fileovima, koje trebamo izraditi da bi biblioteka, library bio funkcionalan i pregledan.
 
Ono što želimo, i hoćemo napraviti, su funkcije za pisanje brojeva od 0 do 9, funkcija kojom ćemo ugasiti sve segmente na displayu i funkcija koja će paliti/gasiti točku. Krenimo...

Header .h

 
Header file, spremamo ga s ekstenzijom .h, je jedan od dva nužna file za funkcioniranje librarya. S obzirom da Arduino to ne radi sam, ovdje ćemo definirati sve što koristimo u libraryu. Kreiramo klasu, koju kasnije možemo pozvati u Arduino IDEu, sa svim varijablama i funkcijama koje želimo da budu dostupne korisniku librarya (public) i onim internima koje ćemo koristiti kako bi library bio funkcionalan (private.
 
Što je klasa?
 
Ako se do sada niste susreli s pojmom klasa, ona je zapravo skup svih funkcija i varijabli za određeni objekt. Npr. gledajmo na muškarca kao na objekt. Svaki muškarac ima, ili nema, određene karakteristike kao što su IQ, visina, masa ili brkovi. Gledano iz očiju programera IQ je cijelobrojna varijabla int, visina i masa mogu biti float, a brkove imaš ili nemaš pa je logično boolean.
 
No dobro, vratimo se na izradu librarya. Otvorimo najdraži tekst editor i krenimo:

// kreiramo klasu koju ćemo pozivati u Arduino IDE
class Segment  
{
  // funkcije koje koristi korisnik librarya
  public:
  // ovdje cemo postaviti konekciju Croduina i displaya
  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);  // funkcija "broj" imati će jedan parametar, broj "n" koji zelimo prikazati
  void Tocka();  // funkcija "tocka" ce paliti/gasiti tocku 
  void Ocisti();  // funkcija ocisti gasi preostale segmente
  // interne varijable
  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;
};

Bez brige ako nešto nije jasno, glavni dio nalazi se u source fileu kojeg ćemo obraditi za tren. Osim navedenog, Header file mora imati još neke dijelove. Svakako je potrebno implementirati Arduino.h, koji se automatski dodaje pri kompajlanju koda, ali ne i u pisanju librarya.

#include "Arduino.h"

Ovaj dio uvelike ovisi o verziji Arduino IDEa kojeg krisnik ima instaliran. Tako da ovom djelu treba posvetiti puno više pažnje, međutim za sada će ovo biti dovoljno.
 
Običaj je u Header file dodati i mali dio koda koji provjerava da je library samo jednom dodan u sketch. On izgleda ovako:

#ifndef Segment_h
#define Segment_h

 // dio za kod

#endif

Konačno naš Header izgleda ovako:

/*
	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

Sada ga sam trebamo spremiti. Napravimo novi folder u, za Windows OS, Documents - Arduino - Libraries i nazovimo ga Segment ili po želji. Detaljnije o Arduino library-ma ovdje. Važno je da su svi znakovi u imenu prema ASCII standardu. Spremimo napisani kod u kreirani folder i dodajmo mu ekstenziju .h, tako da ime izgleda, npr. Segment.h. Pripazite da naziv nema nikakvu drugu ekstenziju osim .h, kao .txt ili slično.

Source .cpp

 
Source file je dio gdje se nalazi sav naš kod/logika, a pišemo ga u C++ jeziku. Iako smo već objasnili logiku koju želimo napisati, slobodno škicnite na 7 segmentni display tutorial i podsjetimo se kako radi.
 
Za početak moramo includati Arduino.h i Segment.h koji smo kreirali upravo. Ponovno, naravno, pišemo u tekst editoru.

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

Odlično. Vrijeme je da napišemo logiku za konstruktore kreirane u Headeru.

//KLASA  ::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;
  }

Prvi konstruktor "Segment" klase je Segment. Njega koristimo da definiramo na kojim pinovima Croduina su spojene nožice 7 segmentno displaya. Ako display spojimo na isti način kao u 7 segmentni display tutorialu, ovaj konstruktor u Arduino IDE pozvati ćemo ovako:

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

 
_pin definiramo je želimo odvojiti privatne varijable, od onih koje korisnik librarya koristi. Dakle, ako korisnik napravi neke promjene na public varijabli to neće utjecati na funkcioniranje librarya.
 
b = false; koristimo kako bi upalili, odnosno ugasili točku na displayu. Njegov konstruktor izgledati će ovako:

void Segment::tocka()
{
	b = !b; // spremi zamjenjenu vrijednost
	digitalWrite(_pin8, b);  // to ce upaliti tocku ako je ugasena i obratno
} 

Ostao nam je još konstruktor broj. On će za paramater uzeti cijeli broj između 0 i 9 i zapisati ga na displayu. To izgleda ovako:

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;

//... i td. pišemo za svaki pojedinacni broj
   }
}

U Arduino IDE pozivamo ga na sljedeći način:

// palimo broj 0
segment.broj(0);

 
segment je objekt koji smo stvorili pomoci Segment konstruktora par redova izna
broj je konstruktor kojeg smo upravo kreirali
0 je broj koji želimo prikazati na ekranu
 
Kada ispišemo sve, .cpp file nam izgleda ovako:

/*
	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);
}

Preostaje samo spremiti file na isti način kao i Header. Spremammo ga u isti kreirani folder, ovaj puta s .cpp ekstenzijom.

Keywords

 
Keywords je .txt file koji omogućuje Arduino IDE da prepozna ključne riječi iz našeg librarya i promjeni im boju u editoru kao bi kod bio pregledniji. Izgledao bi otprilike ovako:

Segment KEYWORD1
broj 	KEYWORD2
ocisti	KEYWORD2
tocka	KEYWORD2

Spremamo ga u isti folder kao predhodna dva file s ekstenzijom .txt .

Arduino IDE i primjer koda

 
Ako želimo da se primjer korištenja libraya pojavi u Arduino IDE File-Examples trebamo kreirati subfolder s nazivom examples. Ovako to izgleda u Windows OS:
 
Arduino IDE libraries
 
U subfolder examples spremiti ćemo primjer korištenja ovog librarya. Možemo ga pisati u Arduino IDE softwareu, a za primjer ćemo napisati odbrojavanje displaya.

//dodajemo kreiranu biblioteku
#include "Segment.h"

//definiramo pinove Croduina prema tutorialu
Segment segment(2,3,4,5,6,7,8,9);

void setup() {
}

void loop() {
  // odbrojavamo u loop-u
  for(int i=9; i>=0; i--)
  {
    segment.broj(i); // pozivaj brojeve od 9 do 0
    delay(1000);     // zaustavi 1 sekundu
  }

  // za kraj zablicaj par puta
  for(int j=0; j<3; j++)
  {
    segment.ocisti();
    segment.tocka();
    delay(500);
    segment.broj(0);
    segment.tocka();
    delay(500);
  }
}

 
Spremimo ovaj kod u examples folder. Nakon toga nužno je zatvoriti i ponovno otvoriti Arduino IDE kako bi mogli koristiti library.
 
Nadamo se da nismo previše zakomplicirali ovaj relativno jednostavan postupak izrade vlastitog Arduino librarya. Ako imate poteškoća ili nadogradnji na ovaj tutorial, veselimo se vašem komentaru.

One thought on “Kako napisati vlastiti Arduino library”

  • Mladen Dugacki
    Mladen Dugacki 13.11.2016 at 19:11

    Kako mozemo vidjeti nakom kompajliranja kod librarya (.cpp) kao sto se vidi kod osnovnog programa (.ino) U slucaju pogreske vidimo u osnovnom programu(.ino) mjesto pogreske i odmah mozemo ispraviti , dok kod librarya je nedostupan. To je osobito vazno ako radimo slozeniji library.Takodjer u osnovni program mozemo ubaciti zamke "Software serial.print(....)" , dok u library. vjerjatno to nemozemo. Prije kompajliranja kompajler spoji oba programa, dok mi to nemozemo jer .ino ne prihvaca klase.
    Unapred se zahvaljujem

    Reply
Leave a Reply