Aktuálně: Postihly zákazy tvou profesi? Poptávka po ajťácích prudce roste, využij slevové akce 30% výuky zdarma!
Pouze tento týden sleva až 80 % na e-learning týkající se PHP
PHP týden

Lekce 17 - Tvorba vlastní Arduino knihovny - Třída Nové

V minulé lekci, Arduino a analogový pin, jsme si řekli něco o analogovém pinu a jak jej lze využít pro měření elektrického odporu a napětí.

V dnešním Arduino tutoriálu si vyzkoušíme základy objektově orientovaného programování v praxi. Vytvoříme třídu pro blikání LED diodou. Třídu pak můžeme používat několikrát, vytvořením více instancí. Právě znovupoužívání kódu je jednou z výhod OOP. Začněme ale hezky popořadě.

Co je to OOP?

OOP neboli Objektově Orientované Programování v sobě nese základní myšlenku pohlížet na části programu jako na reálné objekty. S takovými objekty se pak daleko lépe pracuje, protože obvykle odpovídají např. objektům, které přes Arduino ovládáme (LED dioda, robotické rameno, ...).

Třídy

Objekty určitého typu tvoříme tak, že si prvně definujeme tzv. třídu. Ta dovoluje vytvořit objekt, který se vyznačuje svým specifickým chováním a obsahuje své vlastní atributy. Navíc má i svou ojedinělou identitu. Výhodu tohoto přístupu si ukažme na následujícím programu.

Blikačka bez třídy

Vytvoříme si funkci pro blikání se všemi 3 použitelnými LED diodami zapojenými na desce Arduina (RX, TX a L). Nebudeme tedy potřebovat žádné schéma zapojení ani nepájivé pole, postačí jen deska libovolného Arduina.

Kód programu je následující:

bool stav;
long posledniZmena;

void Blikej(int pin, int interval) {
  if ((millis() - posledniZmena) > interval) {
    stav = !stav;
    posledniZmena = millis();
  }
  digitalWrite(pin, stav);
}

void setup() {
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(13, OUTPUT);
}

void loop() {
  Blikej(0, 125);
  Blikej(1, 250);
  Blikej(13, 500);
}

Kód využívá funkci millis(), která se od funkce delay() (známou z předchozích lekcí) liší tím, že se jedná o čítač milisekund od spuštění programu, nikoliv o pauzu.

Program má blikat hned třemi LED diodami a to každou v jiném intervalu. Aby mohly být intervaly úplně různé, každá dioda si podle aktuálního času a posledního času změny stavu zjistí, zda se má nebo nemá změnit její stav.

Jak můžete vidět, diody na desce se chovají dosti nestabilně. Asi tušíte, že problém je v tom, jak je pro všechna volání této funkce vždy stejná proměnná long posledniZmena. Ostatní volaní této funkce jsou tedy zdržována. Takhle by to nešlo.

Problém bychom určitě mohli vyřešit i bez objektů, např. vytvořit samostatnou proměnnou pro každou ledku zvlášť nebo dát LED diody do pole. My si dnes ovšem ukážeme objektové řešení.

Blikačka se třídou

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Použitím třídy vytvoříme 3 samostatné objekty pro každou z LED diod, se svými vlastními proměnnými.

Třída

Nejprve si deklarujeme třídu Blikacka, která definuje co vše budou budoucí blikačky mít.

Třída je vzor, podle kterého pak lze vytvořit libovolné množství objektů, kterým říkáme instance třídy. Ty budou mít všechny ty samé proměnné a funkce jako definuje třída, ale každý objekt v nich pak bude mít své vlastní hodnoty.

Deklarace metod a atributů třídy

Kód třídy bude zatím následující:

class Blikacka {
  public:
    Blikacka(int pin);
    void Blikej(int interval);
    void Neblikej();

  private:
    int pin;
    bool stav = false;
    long posledniZmena ;
};

Za složeným blokem ohraničujícím třídu se skutečně píše středník!

Třídě jsme deklarovali několik funkcí a proměnných. Těm se nyní terminologicky správně již říká metody a atributy, protože patří daným instancím třídy, blikačkám, které podle třídy jako vzoru vytvoříme.

První metoda bez datového typu, Blikacka(), je tzv. konstruktor. Zavolá se automaticky hned po vytvoření konkrétní nové blikačky. Asi netřeba říkat, že pak slouží k inicializaci hodnoty atributů.

Kód metod třídy

Následně po deklaraci třídy doplníme jednotlivé metody a konstruktor prostřednictvím kvalifikátoru "čtyřtečky" :: (neboli operátoru příslušnosti).

Pod deklarací této třídy program pokračuje:

// konstruktor
Blikacka::Blikacka(int pin) {
  if (pin < 0 || pin > 13) pin = 13;
  this->pin = pin;
  pinMode(pin,OUTPUT); // díky tomuto již nepotřebujeme smyčku setup()
}

// metoda pro blikání
void Blikacka::Blikej(int interval) {
  if (interval <= 0) interval = 250;
  if ((millis() - posledniZmena ) > interval) {
    stav = !stav;
    posledniZmena = millis();
  }
  digitalWrite(pin,stav);
}

// metoda pro přerušení blikání
void Blikacka::Neblikej() {
  digitalWrite(pin,LOW);
}

// vytvoření tří instancí
Blikacka X(0);
Blikacka Y(1);
Blikacka Z(13);

void setup() {

}

void loop() {
  X.Blikej(125);
  Y.Blikej(250);
  Z.Blikej(500);
}

Metody jsou doplněny podmínkami pro omezení rozsahu užitých pinů Arduina (0 - 13, uvažujme základní Arduino Nano či Uno), a intervalu - interval 0 ms a menší je nesmysl.

Zde si všimněme několika dalších (pro nás zatím nových) výrazů.

this a operátor ->

Jako první je výraz this->pin = pin. Tímto říkáme programu, že do atributu instance třídy s názvem pin (v privátní části) přiřadíme hodnotu parametru pin z konstruktoru Blikacka(int pin). Právě pomocí this odlišíme která proměnná pin je která. this je ukazatel na instanci samotnou, proto vše označené tímto ukazatelem je vždy součástí instance.

U Arduino programů se běžně užívají pro odlišení duplicitních názvů podtržítka. V tomto případě by tedy tento atribut pak měl tvar _pin. Tato praktika je sice běžná, avšak více se upřednostňuje varianta s ukazatelem this, která je (i podle mého názoru) přehlednější. A vzhledem k tomu, že jde o ukazatel, má i tzv. ukazatelový selektor (->). Se selektorem se setkáváme běžně, avšak jako s operátorem tečka (například při tisku na sériový monitor jsme používali metodu Serial.println()). Případné zájemce o více informací ohledně ukazatele this odkážeme na lekci v programovacím jazyce C++.

Modifikátory přístupu

Dalším výrazům public a private říkáme modifikátory přístupu (někdy též přístupové úrovně) a v podstatě nám říkají, s čím můžeme mimo třídu pracovat, a co je skryto.

Modifikátorem public označujeme vše, s čím chceme, aby nám třída dovolila nějakým způsobem veřejně manipulovat, například volat její metody. K takovýmto částem třídy pak přistupujeme pomocí selektoru tečky. Například pomocí X.Blikej() voláme veřejnou metodu Blikej() instance X. Atributy a metody označené modifikátorem public nazýváme jako veřejné.

Je dobrou praktikou označovat všechny atributy jako soukromé a jejich hodnoty měnit pouze prostřednictvím veřejných metod! Naopak modifikátor přístupu private označuje vše, co je skryté, a my k tomu tedy nemáme přístup. Tímto modifikátorem se nejčastěji označují ty atributy a metody, které třída využívá ke své vlastní činnosti. Například jde o operace, do kterých není vhodné nějakým způsobem zasahovat. O částech třídy označené modifikátorem private vždy mluvíme jako o soukromých částech třídy. K takovýmto atributům nelze veřejně přistupovat prostřednictvím selektoru. Jejich hodnoty lze ale měnit jen ve veřejných metodách. My hodnotu privátního atributu v tomto případě nastavujeme v konstruktoru, jedná se právě o privátní atribut pin.

Schválně si můžeme vyzkoušet vypsat hodnotu atributu posledniZmena (Serial.println(X.posledniZmena)). Kompilátor nám nyní vynadá. Když ale atribut označíme jako veřejný, při každé iteraci smyčky loop() nám bude vypsána hodnota v něm uložená.

Kromě modifikátorů přístupu public a private existuje ještě modifikátor protected, který je podobný privátnímu modifikátoru, avšak jej lze dědit v odvozených třídách. To je ovšem nad rámec této lekce.

Celý program

Tak, dost vysvětlování, jdeme na praktickou ukázku! Nyní nahrajme již ucelený program do Arduina!

class Blikacka {
  public:
    Blikacka(int pin);
    void Blikej(int interval);
    void Neblikej();

  private:
    int pin;
    bool stav = false;
    long posledniZmena ;
};

// konstruktor
Blikacka::Blikacka(int pin) {
  if (pin < 0 || pin > 13) pin = 13;
  this->pin = pin;
  pinMode(pin,OUTPUT);
}

// metoda pro blikání
void Blikacka::Blikej(int interval) {
  if (interval<= 0) interval = 250;
  if ((millis() - posledniZmena ) > interval) {
    stav = !stav;
    posledniZmena = millis();
  }
  digitalWrite(pin,stav);
}

// metoda pro přerušení blikání
void Blikacka::Neblikej() {
  digitalWrite(pin,LOW);
}

// vytvoření tří instancí
Blikacka X(0);
Blikacka Y(1);
Blikacka Z(13);

void setup() {

}

void loop() {
  X.Blikej(125);
  Y.Blikej(250);
  Z.Blikej(500);
}

To už je lepší, nemyslíte? Třída Blikacka je k dispozici ke stažení níže.

V příští lekci, Tvorba vlastní Arduino knihovny - Dokončení, si vytvoříme naši plnohodnotnou Arduino knihovnu.


 

Měla jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 10x (732 B)
Aplikace je včetně zdrojových kódů

 

Předchozí článek
Arduino a analogový pin
Všechny články v sekci
Arduino
Článek pro vás napsal Václav Doškář
Avatar
Jak se ti líbí článek?
1 hlasů
Autor pracuje jako pedagog v oblasti elektroniky a elektrotechniky. Programování má jako koníčka. Věnuje se jazykům C++ a C#.
Aktivity (4)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!