IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 2 - Přerušení a časovač na modulu ESP-32

V předchozí lekci, Seznámení s ESP-32, jsme se seznámili s čipem ESP-32 a vývojovou deskou ESP-32 DEVKIT DOIT.

V tomto tutoriálu Internetu věcí s ESP32 se zaměříme na možnosti využití přerušení a časování, které nám modul ESP-32 nabízí. Vysvětlíme si princip přerušení a jeho dva typy.

Přerušení

Přerušení jsou klíčovým konceptem v oblasti mikrokontrolerů a systémů vestavěných zařízení, jako je ESP32. Jako přerušení označujeme signály generované buď externími nebo interními událostmi. Tyto signály dočasně přeruší běžící program a spustí specifickou obslužnou rutinu. Uveďme si příklad s jednoduchou LED diodou. Řekněme, že máme program, který rozbliká LED. Mikrokontroler provádí všechny příkazy v programu tak, jak jdou za sebou. Pokud však chceme monitorovat stav diody v reálném čase, narážíme na zpoždění, které je dané délkou běžícího programu – dokud neskončí, nemáme možnost do něj vstoupit. A když program běží ve smyčce loop(), jsme od něj odděleni zcela. Zde do hry přichází přerušení.

Při přerušení mikrokontroler zastaví běh programu a zavolá funkci typu ISR (Interrupt Service Routine). Následně se provedou všechny příkazy v těle funkce a poté se mikrokontroler opět vrátí do hlavního programu. Tento mechanismus umožňuje mikrokontroleru rychle reagovat na důležité události (jako je změna stavu LED diody), aniž by byl nutný průběžný průzkum (polling) stavu diody. To zefektivňuje použití procesorového času a umožňuje mikrokontroleru zvládat více úloh souběžně.

ESP-32 má celkem 32 přerušení na každé jádro a každé z nich má určitou prioritu.

Typy přerušení

Základní rozdělení je odvozeno od zdroje přerušení, dělí se proto na externí/hardwa­rové a softwarové.

Externí/hardwarové přerušení

Toto přerušení je vyvoláno událostí na externí periferii. Jako příklad si uveďme senzor dotyku. Pokud senzor zaregistruje dotyk, změní se i stav na GPIO a vyvolá se přerušení. Následně se provedou příkazy v těle ISR funkce a poté se řízení vrátí do hlavního programu. Největší výhodou přerušení je, že nemusíme neustále monitorovat stav periferie. Periferie si naopak sama řekne, že u ní nastala změna, pro kterou máme připravenou obslužnou rutinu.

Softwarové přerušení

Tento typ přerušení nastane ve chvíli, kdy program sám explicitně vyvolá přerušení a určí rutinu, která se vykoná. Softwarové přerušení se často používá pro manipulaci s hardwarovými zařízeními, signalizaci chyb, nebo pro realizaci komplexních funkcí v rámci operačního systému. Lze jím také emulovat hardwarové události pro testování nebo ladění kódu, nebo vynutit kontrolu některých funkcí.

Při softwarových přerušení je důležité zajistit správnou synchronizaci a řízení přerušení, aby nedocházelo k nekonzistenci dat nebo jiným problémům.

GPIO přerušení

Výhodou modulu ESP-32 je, že všechny jeho GPIO piny lze nakonfigurovat jako zdroje hardwarového přerušení. Docílíme toho velmi jednoduše, stačí pouze příslušný pin připojit k odpovídající ISR. Toto nám umožní následující makro:

attachInterrupt(GPIOpin, ISR, Event);

Makro obsahuje tři argumenty:

  • GPIOpin: číslo pinu, ke kterému má být přiřazeno přerušení,
  • ISR: název funkce, která má být při přerušení zavolána,
  • Event: třetí argument určí, při jaké události má být přerušení vyvoláno. Možné hodnoty jsou následovné:
    • LOW - přerušení se spustí, pokud je na pinu hodnota LOW (0),
    • HIGH - přerušení se spustí, pokud je na pinu hodnota HIGH (1),
    • CHANGE - přerušení se spustí vždy, když se na pinu změní hodnota (LOW na HIGH nebo HIGH na LOW),
    • FALLING - přerušení se spustí, pokud se hodnota na pinu změní z HIGH na LOW (doběžná hrana),
    • RISING - přerušení se spustí, pokud se hodnota na pinu změní z LOW na HIGH (náběžná hrana).

Když už nyní víme, co znamená jaký argument, pojďme dosadit konkrétní hodnoty:

attachInterrupt(5, ISR, CHANGE);

Po provedení tohoto příkazu se nám na pátý pin nastaví hardwarové přerušení, které spustíme např. tlačítkem. Pojďme si ještě popsat ISR funkci, která je předávána do makra jako argument:

void IRAM_ATTR ISR(){
   // příkaz;
   // příkaz;
}

Tato funkce obsahuje všechny příkazy, které se mají spustit, když je hlavní program přerušen. Návratový typ funkce IRAM_ATTR zajistí, že bude funkce uložena do části paměti IRAM a nikoliv do paměti flash, čímž zajistíme její rychlejší načítání.

Jelikož tato funkce blokuje chod hlavního programu, je vhodné používat ji pro co nejkratší úlohy.

Jak odstranit přerušení?

V některých případech je potřeba odstranit přerušení na dobu neurčitou. K tomu nám poslouží funkce detachInterrupt(). Jelikož jsme si v předchozím kroku nastavili přerušení na pin 5, pojďme jej nyní odstranit:

detachInterrupt(5);

Po provedení tohoto příkazu se pin přestane chovat jako zdroj přerušení do doby, kdy bude zavolána funkce attachInterrupt() nebo bude rebootován systém.

Praktický příklad – zhasnutí a rozsvícení LED diody

Nyní již umíme vše, co potřebujeme k vytvoření jednoduchého programu, který bude díky přerušení zhasínat a rozsvěcovat LED. K tomuto příkladu budeme potřebovat kromě modulu také tlačítko a LED diodu, které společně zapojíme podle následujícího schématu:

Internet věcí s ESP32

Vše máme zapojeno a můžeme se vrhnout na kód. Nejdříve si nastavíme makra pro jednotlivé piny a také definujeme ISR funkci:

#define buttonPin 33
#define LEDPin 32

void IRAM_ATTR menLED(){
    digitalWrite(LEDPin, !digitalRead(LEDPin));
}

Při využívání přerušení v programu není potřeba definovat funkci loop(), ta tedy zůstane prázdná. Zbývá už jen doplnit tělo funkce setup(), a to následovně:

void setup(){
    pinMode(LEDPin, OUTPUT);
    pinMode(buttonPin, INPUT_PULLUP);
    attachInterrupt(buttonPin, menLED, CHANGE);
}

Pro úplnost si zrekapitulujme celý program:

#define buttonPin 33
#define LEDPin 32

void IRAM_ATTR menLED(){
    digitalWrite(LEDPin, !digitalRead(LEDPin));
}

void setup(){
    pinMode(LEDPin, OUTPUT);
    pinMode(buttonPin, INPUT_PULLUP);
    attachInterrupt(buttonPin, menLED, CHANGE);
}

void loop(){

}

Nyní nám bude tlačítko fungovat jako přepínač, tzn. že po jeho stisknutí změní hodnotu LED diody na opačnou.

Časování

Když už rozumíme tomu, co je to přerušení a jak funguje, můžeme se pustit do časování. Časování je v podstatě druh přerušení, protože generuje přerušení po určité časové době. Často se využívá třeba jako počítadlo.

Časování na modulu ESP32

Náš mikrokontroler ESP32 obsahuje dvě skupiny časovačů, z nichž každá skupina obsahuje dva hardwarové časovače. Každý časovač má 64 bitů. Ty jsou založeny na 16 bitovém prescaleru (dělička vstupního signálu). Využívání časování je velmi efektivní, protože je při něm jisté, že se načasované události stanou s přesností na milisekundu.

Všechny přerušení vyvolány časovačem se řadí do softwarových přerušení.

Podle frekvence mikrokontroleru se právě díky prescaleru tato frekvence rozdělí na menší celky, tzv. ticky. Nám již známá ISR funkce se tedy vždy spustí po uplynutí určitého počtu ticků.

Pojďme si tedy zrekapitulovat, jak funguje časovač. Časovač používá počítadlo, které se zvýší o jedna vždy, když uplyne určitý časový úsek (tick). Jakmile bude počítadlo na hodnotě, kterou jsme mu v kódu nastavili, časovač spustí přerušení a počítadlo se vynuluje.

Praktický příklad – pravidelné blikání LED diodou

Představte si, že chceme každou sekundu bliknout LED diodou. Nabízí se použít funkci delay(), ale to by zabralo veškerý procesorový čas a nemohli bychom provádět žádné jiné úlohy. Lepší cestou je tedy použití časovače. Zapojení pro tento příklad ponecháme v podstatě stejné, jen z něj vymažeme tlačítko. V kódu si nejdříve zase nastavíme hodnotu makra, vytvoříme proměnnou pro časovač a nadefinujeme si ISR funkci:

#define LEDPin 32;
hw_timer_t *casovac = NULL;

void IRAM_ATTR naCas(){
   digitalWrite(LEDPin, !digitalRead(LEDPin));
}

Do hodnoty makra je důležité vložit číslo pinu, do kterého jsme připojili LED diodu. V případě, že se čísla neshodují, program nebude fungovat!

Když máme všechno nastaveno, doplníme už jen tělo funkce setup() a máme hotovo. Funkce loop() zůstane opět prázdná, protože pro ukázku nepotřebujeme provádět jiné operace (přerušení nastane i tak). Nastavíme pin LED diody na výstup:

pinMode(LEDPin, OUTPUT);

Následně zapneme časovač v našem mikrokontroleru. Prvním parametrem funkce je číslo časovače, který chceme použít (hodnoty 0 až 3). Druhým parametrem je hodnota prescaleru, ze kterého se počítá délka jednoho ticku. My nyní použijeme hodnotu 80. Tím dosáhneme frekvence 1 MHz, což znamená, že každý tick trvá jednu mikrosekundu. Poslední parametr určuje, zda má počítadlo počítat nahoru (true) nebo dolů (false):

casovac = timerBegin(0,80,true);

Musíme také určit, která funkce se má provést, když nastane přerušení. V našem případě využijeme ISR funkci naCas(), kterou jsme si vytvořili:

timerAttachInterrupt(casovac, &naCas, true);

Dále nastavíme interval změny hodnoty na LED diodě. K tomu použijeme funkci timerAlarmWrite(). První parametr určuje, o který časovač se jedná, druhý určuje prodlevu v mikrosekundách a třetí parametr (true) zajišťuje periodické resetování časovače:

timerAlarmWrite(casovac, 1000000, true);

A konečně jen povolíme časovač a náš kód je připraven ke spuštění. Teď bude LED dioda blikat vždy po jedné sekundě:

timerAlarmEnable(casovac);

Na závěr si ještě pro jistotu zrekapitulujeme celý program:

#define LEDPin 32
hw_timer_t *casovac = NULL;

void IRAM_ATTR naCas(){
   digitalWrite(LEDPin, !digitalRead(LEDPin));
}

void setup(){
  pinMode(LEDPin, OUTPUT);
  casovac = timerBegin(0,80,true);
  timerAttachInterrupt(casovac, &naCas, true);
  timerAlarmWrite(casovac, 1000000, true);
  timerAlarmEnable(casovac);
}

void loop(){

}

V příští lekci, Mód hlubokého spánku na modulu ESP-32, si popíšeme mód hlubokého spánku na modulu ESP-32 a předvedeme si jej na praktické ukázce.


 

Předchozí článek
Seznámení s ESP-32
Všechny články v sekci
Internet věcí s ESP32
Přeskočit článek
(nedoporučujeme)
Mód hlubokého spánku na modulu ESP-32
Článek pro vás napsal Adam Hudeczek
Avatar
Uživatelské hodnocení:
12 hlasů
Autor se věnuje zejména programování mikrokontrolerů a tvorbou a provozem webových stránek a webových aplikací.
Aktivity