Skip to main content

2.10 Prerušenie z časovača

Okrem prerušenia zo vstupného portu môžeme tiež využiť prerušenie z časovača. V tomto prípade nevznikne prerušenie pri zmene vstupu, ale vyvolá ho časovač po uplynutí zadaného času. Vďaka tomu môžeme načasovať spustenie nejakej funkcie alebo zariadiť, aby sa spúšťala opakovane v určitých intervaloch.

2.10 časovač.webp

Rôzne MCU majú rôzny počet hardvérových časovačov - označujú sa general-purpose timers, niektoré majú virtuálny časovač:

  • klasický ESP32 a ESP32-S3 majú 4 časovače (ID 0 až 3);
  • ESP32-C3, ESP32-C6ESP32-H2 majú 2 časovače (ID 0 a 1);
  • starý ESP8266 má virtuálny časovač (ID -1).

V školskej inštalácii M5Stick sa časovač ID 2 používa pre vypnutie zariadenia po poklese napájania, preto ho nepoužívajme. Dostupný je pod menom boot_ext.casovac.

Pozor, opakovaná inicializácia časovača s rovnakým ID zruší predošlé nastavenie časovača!

Keďže časovačov máme obmedzený počet, v prípade potreby viacerých načasovaní treba strategicky zvážiť, ako ich šetriť. Ak by sme napríklad potrebovali niečo skontrolovať každú sekundu a niečo odoslať každú minútu, nie je potrebné používať dva časovače - stačiť bude jeden a ten zistí, či okrem sekundy uplynula aj minúta.

Časovač v MicroPython - objekt Timer

V MicroPythone je časovač dostupný cez objekt Timer z modulu machine. Jeho konštruktor len vytvorí samotný objekt časovača, no nastaviť ho musíme objektovou funkciou init(), v ktorej musíme uviesť:

  1. údaj o tom, ako často sa má časovač spúšťať:
    • buď požadovaný čas parametrom period (v milisekundách)
    • alebo frekvenciu spúšťania parametrom freq (v Hz);
  2. odkaz na funkciu obsluhy udalosti parametrom callback.
from machine import Timer
časovač = Timer(0)
časovač.init(callback = Časovač, freq = 1)

Keď nastane správny čas, obslužnej funkcii bude odovzdaný vstupný parameter typu Timer - inštancia toho časovača, ktorý vyvolal udalosť. Teda podobne ako pri prerušení vstupného portu, jedna funkcia môže obslúžiť aj viaceré časovače.

Režim časovača

Nastaviť môžeme tiež režim časovača parametrom mode:

  • Timer.PERIODIC - časovač vyvolá udalosť opakovane s periódou podľa nastaveného času (toto je predvolený režim);
  • Timer.ONE_SHOT - časovač vyvolá udalosť jednorazovo po uplynutí nastaveného času.

Časovač je po skončení programu potrebné vypnúť (deaktivovať) objektovou funkciou deinit(), inak bude bežať naďalej.

Demonštračný program

Tento program bude simulovať „časové znamenie“, ktoré si vaši rodičia ešte pamätajú z vysielania rádia - každú hodinu oznamovalo presný čas. Okrem pípania však aj bliká LEDkou, to rádio nedokázalo. 🙂

Všimnite si presnosť odpočtu času vo výpise ticks_ms(). Prípadne skúste časovač zrušiť a spoľahnite sa len na príkaz sleep() - zostane odpočet taký presný?

from time import sleep, ticks_ms
from machine import Timer, Pin, PWM, Signal

def Časovač(časovač):
    global sekunda, buzzer, led
    sekunda += 1
    print(f"\nUplynula {sekunda}. sekunda! ({ticks_ms() % 1000})")
    buzzer.duty_u16(2**15)
    led.on()
    sleep(0.1)
    buzzer.duty_u16(0)
    led.off()

led = Signal(10, Pin.OUT, value = 0, invert = True)
buzzer = PWM(Pin(2))
buzzer.deinit()
buzzer.init(freq = 3000, duty_u16 = 0)

sekunda = i = 0
časovač = Timer(0)
časovač.init(callback = Časovač, freq = 1)
while sekunda < 5:
    i += 1
    print(f"Odpočívam ({i})...", end = "\r")
    sleep(0.1)
časovač.deinit()

Pozor na funkciu sleep() v prerušení!
V tomto programe sme porušili zásadu, že spracovanie udalosti má byť čo najkratšie. Naša obslužná funkcia sa zdržiava vydaním tónu a čakaním, aby sme demonštrovali, že časovač beží nezávisle. V praxi však buďte opatrní - obslužná funkcia by mala trvať čo najkratšie, pretože kým beží, hlavný program je pozastavený. Ak by trvala dlhšie než perióda časovača, program by dokonca mohol zhavarovať.