klasa Timer – sterowanie wewnętrznymi licznikami czasu (timerami)

Liczniki czasu (timery) mogą być używane do bardzo różnorodnych zadań. Obecnie zaimplementowano jedynie najprostszy przypadek: okresowe wywoływanie funkcji.

Każdy licznik czasu (timer) składa się z licznika, który zlicza w górę z określoną szybkością. Szybkość zliczania to częstotliwość zegara urządzenia peryferyjnego (w Hz) podzielona przez preskaler timera. Gdy licznik osiągnie wartość okresu timera, wyzwala zdarzenie, a licznik zostaje wyzerowany. Korzystając z metody callback, zdarzenie timera może wywołać funkcję w Pythonie.

Przykładowe użycie do przełączania diody LED ze stałą częstotliwością:

tim = pyb.Timer(4)              # create a timer object using timer 4
tim.init(freq=2)                # trigger at 2Hz
tim.callback(lambda t:pyb.LED(1).toggle())

Przykład z użyciem nazwanej funkcji jako wywołania zwrotnego:

def tick(timer):                # we will receive the timer object when being called
    print(timer.counter())      # show current timer's counter value
tim = pyb.Timer(4, freq=1)      # create a timer object using timer 4 - trigger at 1Hz
tim.callback(tick)              # set the callback to our tick function

Dalsze przykłady:

tim = pyb.Timer(4, freq=100)    # freq in Hz
tim = pyb.Timer(4, prescaler=0, period=99)
tim.counter()                   # get counter (can also set)
tim.prescaler(2)                # set prescaler (can also get)
tim.period(199)                 # set period (can also get)
tim.callback(lambda t: ...)     # set callback for update interrupt (t=tim instance)
tim.callback(None)              # clear callback

Uwaga: Timer(1) jest używany przez kamerę. Podobnie Timer(5) steruje sterownikiem serwa, a Timer(6) służy do odczytu/zapisu ADC/DAC z synchronizacją czasową. Zaleca się używanie pozostałych timerów we własnych programach.

Uwaga: Podczas wywołania zwrotnego (przerwania) nie można alokować pamięci, dlatego wyjątki zgłaszane wewnątrz wywołania zwrotnego nie dostarczają wielu informacji. Zobacz micropython.alloc_emergency_exception_buf(), aby dowiedzieć się, jak obejść to ograniczenie.

Konstruktory

class pyb.Timer(id: int, *args, **kwargs)

Tworzy nowy obiekt timera o podanym identyfikatorze. Jeśli podano dodatkowe argumenty, timer jest inicjalizowany przez init(...). Zbiór prawidłowych wartości id zależy od mikrokontrolera STM32 zastosowanego w używanej kamerze OpenMV Cam; sprawdź dostępne timery ogólnego przeznaczenia i zaawansowanego sterowania w dokumentacji referencyjnej STM32.

Metody

init(*, freq: int | float | None = None, prescaler: int | None = None, period: int | None = None, mode: int = Timer.UP, div: int = 1, callback: Callable[[Timer], None] | None = None, deadtime: int = 0, brk: int = Timer.BRK_OFF, hard: bool = True) None

Inicjalizuje timer. Inicjalizacja musi odbywać się albo przez częstotliwość (w Hz), albo przez preskaler i okres:

tim.init(freq=100)                  # set the timer to trigger at 100Hz
tim.init(prescaler=83, period=999)  # set the prescaler and period directly

Argumenty nazwane:

  • freq — określa okresową częstotliwość timera. Można to też rozumieć jako częstotliwość, z jaką timer przechodzi przez jeden pełny cykl.

  • prescaler [0-0xffff] - określa wartość, która ma zostać załadowana do rejestru preskalera timera (PSC). Źródło zegara timera jest dzielone przez (prescaler + 1), aby uzyskać zegar timera. Źródło zegara pochodzi z macierzystej magistrali APB timera i jest zależne od mikrokontrolera. W STM32 timery na APB1 zwykle taktowane są z 2 * pclk1, a timery na APB2 z 2 * pclk2; bieżące częstotliwości magistral odczytasz za pomocą pyb.freq(), a szczegóły sprawdzisz w dokumentacji referencyjnej STM32 dla mikrokontrolera Twojej kamery OpenMV Cam.

  • period [0-0xffff] dla timerów 1, 3, 4 oraz 6-15. [0-0x3fffffff] dla timerów 2 i 5. Określa wartość, która ma zostać załadowana do rejestru automatycznego przeładowania timera (ARR). Wyznacza ona okres timera (tzn. moment, w którym licznik wykonuje cykl). Licznik timera przepełni się po period + 1 cyklach zegara timera.

  • mode może przyjmować jedną z wartości:

    • Timer.UP - konfiguruje timer do zliczania od 0 do ARR (wartość domyślna)

    • Timer.DOWN - konfiguruje timer do zliczania od ARR w dół do 0.

    • Timer.CENTER - konfiguruje timer do zliczania od 0 do ARR, a następnie z powrotem w dół do 0.

  • div może wynosić 1, 2 lub 4. Dzieli zegar timera, aby wyznaczyć zegar próbkowania używany przez filtry cyfrowe.

  • callback - zgodnie z Timer.callback()

  • deadtime - określa wielkość „martwego” lub nieaktywnego czasu między przełączeniami na kanałach komplementarnych (oba kanały będą nieaktywne przez ten czas). deadtime może być liczbą całkowitą od 0 do 1008, z następującymi ograniczeniami: 0-128 w krokach co 1, 128-256 w krokach co 2, 256-512 w krokach co 8 oraz 512-1008 w krokach co 16. deadtime mierzy takty source_freq podzielone przez div taktów zegara. deadtime jest dostępny tylko na timerach 1 i 8.

  • brk - określa, czy tryb przerwania (break) jest używany do wyłączenia wyjścia PWM, gdy wejście BRK_IN zostanie aktywowane. Wartość tego argumentu określa, czy tryb break jest włączony i jaka jest jego polaryzacja, i może przyjmować jedną z wartości Timer.BRK_OFF, Timer.BRK_LOW lub Timer.BRK_HIGH. Aby wybrać pin BRK_IN, utwórz obiekt Pin z mode=Pin.ALT, alt=Pin.AFn_TIMx. Funkcje wejścia GPIO pinu są dostępne w trybie alt - pull=, value() oraz irq().

  • hard może przyjmować jedną z wartości:

    • True - wywołanie zwrotne zostanie wykonane w kontekście twardego przerwania, co minimalizuje opóźnienie i jitter, ale podlega ograniczeniom opisanym w Pisanie procedur obsługi przerwań, w tym braku możliwości alokacji na stercie.

    • False - wywołanie zwrotne zostanie zaplanowane jako miękkie przerwanie, co pozwala na alokację, ale może również wprowadzać opóźnienia i jitter związane z odśmiecaniem pamięci.

    Domyślną wartością tej opcji jest True.

Musisz określić albo freq, albo zarówno period, jak i prescaler.

deinit() None

Deinicjalizuje timer.

Wyłącza wywołanie zwrotne (oraz powiązane irq).

Wyłącza wszystkie wywołania zwrotne kanałów (oraz powiązane irq). Zatrzymuje timer i wyłącza urządzenie peryferyjne timera.

callback(fun: Callable[[Timer], None] | None) None

Ustawia funkcję wywoływaną w momencie wyzwolenia timera. Do fun przekazywany jest 1 argument - obiekt timera. Jeśli fun ma wartość None, wywołanie zwrotne zostanie wyłączone.

channel(channel: int, mode: int | None = None, *args, **kwargs) TimerChannel | None

Jeśli podano tylko numer kanału, zwracany jest wcześniej zainicjalizowany obiekt kanału (lub None, jeśli nie ma poprzedniego kanału).

W przeciwnym razie inicjalizowany i zwracany jest obiekt TimerChannel.

Każdy kanał można skonfigurować do wykonywania pwm, porównania na wyjściu (output compare) lub przechwytywania na wejściu (input capture). Wszystkie kanały współdzielą ten sam bazowy timer, co oznacza, że współdzielą ten sam zegar timera.

Argumenty nazwane:

  • mode może przyjmować jedną z wartości:

    • Timer.PWM — konfiguruje timer w trybie PWM (aktywny stan wysoki).

    • Timer.PWM_INVERTED — konfiguruje timer w trybie PWM (aktywny stan niski).

    • Timer.OC_TIMING — wskazuje, że żaden pin nie jest sterowany.

    • Timer.OC_ACTIVE — pin zostanie ustawiony jako aktywny po wystąpieniu zgodności porównania (stan aktywny jest określany przez polaryzację)

    • Timer.OC_INACTIVE — pin zostanie ustawiony jako nieaktywny po wystąpieniu zgodności porównania.

    • Timer.OC_TOGGLE — pin zostanie przełączony po wystąpieniu zgodności porównania.

    • Timer.OC_FORCED_ACTIVE — pin jest wymuszony jako aktywny (zgodność porównania jest ignorowana).

    • Timer.OC_FORCED_INACTIVE — pin jest wymuszony jako nieaktywny (zgodność porównania jest ignorowana).

    • Timer.IC — konfiguruje timer w trybie przechwytywania na wejściu (Input Capture).

    • Timer.ENC_A — konfiguruje timer w trybie enkodera. Licznik zmienia się tylko wtedy, gdy zmienia się CH1.

    • Timer.ENC_B — konfiguruje timer w trybie enkodera. Licznik zmienia się tylko wtedy, gdy zmienia się CH2.

    • Timer.ENC_AB — konfiguruje timer w trybie enkodera. Licznik zmienia się, gdy zmienia się CH1 lub CH2.

  • callback - zgodnie z TimerChannel.callback()

  • pin None (wartość domyślna) lub obiekt Pin. Jeśli zostanie określony (i nie jest None), spowoduje to skonfigurowanie funkcji alternatywnej wskazanego pinu dla tego kanału timera. Zostanie zgłoszony błąd, jeśli pin nie obsługuje żadnych funkcji alternatywnych dla tego kanału timera.

Argumenty nazwane dla trybów Timer.PWM:

  • pulse_width - określa początkową wartość szerokości impulsu.

  • pulse_width_percent - określa początkową procentową szerokość impulsu.

Argumenty nazwane dla trybów Timer.OC:

  • compare - określa początkową wartość rejestru porównania.

  • polarity może przyjmować jedną z wartości:

    • Timer.HIGH - wyjście jest aktywne w stanie wysokim

    • Timer.LOW - wyjście jest aktywne w stanie niskim

Opcjonalne argumenty nazwane dla trybów Timer.IC:

  • polarity może przyjmować jedną z wartości:

    • Timer.RISING - przechwytuje na zboczu narastającym.

    • Timer.FALLING - przechwytuje na zboczu opadającym.

    • Timer.BOTH - przechwytuje na obu zboczach.

Należy pamiętać, że przechwytywanie działa tylko na kanale głównym, a nie na kanałach komplementarnych.

Uwagi dotyczące trybów Timer.ENC:

  • Wymaga 2 pinów, więc jeden lub oba piny będą musiały zostać skonfigurowane do używania odpowiedniej funkcji alternatywnej (AF) timera za pomocą API Pin.

  • Odczytaj wartość enkodera za pomocą metody timer.counter().

  • Działa tylko na CH1 i CH2 (a nie na CH1N lub CH2N)

  • Numer kanału jest ignorowany podczas ustawiania trybu enkodera.

Przykład PWM – na każdej kamerze STM32 OpenMV Cam kanały 1 i 2 timera TIM4 są skierowane odpowiednio na piny złącza P7 i P8

timer = pyb.Timer(4, freq=1000)
ch1 = timer.channel(1, pyb.Timer.PWM, pin=pyb.Pin.board.P7,
                    pulse_width=8000)
ch2 = timer.channel(2, pyb.Timer.PWM, pin=pyb.Pin.board.P8,
                    pulse_width=16000)
counter(value: int | None = None) int | None

Pobiera lub ustawia licznik timera.

freq(value: int | float | None = None) int | float | None

Pobiera lub ustawia częstotliwość timera (zmienia preskaler i okres, jeśli jest ustawiana).

period(value: int | None = None) int | None

Pobiera lub ustawia okres timera.

prescaler(value: int | None = None) int | None

Pobiera lub ustawia preskaler timera.

source_freq() int

Pobiera częstotliwość źródła timera.

Stałe

Stałe trybu zliczania (argument mode metody init()):

UP: int

Zliczanie od 0 w górę do ARR (tryb domyślny).

DOWN: int

Zliczanie od ARR w dół do 0.

CENTER: int

Zliczanie od 0 w górę do ARR, a następnie z powrotem w dół do 0.

Stałe trybu przerwania (break) (argument brk metody init()):

BRK_OFF: int

Wejście przerwania (break) jest wyłączone.

BRK_LOW: int

Wejście przerwania (break) jest aktywne w stanie niskim.

BRK_HIGH: int

Wejście przerwania (break) jest aktywne w stanie wysokim.

Stałe trybu kanału (argument mode metody channel()):

PWM: int

Konfiguruje kanał do wyjścia PWM (aktywny stan wysoki).

PWM_INVERTED: int

Konfiguruje kanał do wyjścia PWM (aktywny stan niski).

OC_TIMING: int

Tryb synchronizacji porównania na wyjściu (output-compare); żaden pin nie jest sterowany.

OC_ACTIVE: int

Tryb aktywny porównania na wyjściu (output-compare); pin jest ustawiany jako aktywny przy zgodności porównania.

OC_INACTIVE: int

Tryb nieaktywny porównania na wyjściu (output-compare); pin jest ustawiany jako nieaktywny przy zgodności porównania.

OC_TOGGLE: int

Tryb przełączania porównania na wyjściu (output-compare); pin przełącza się przy zgodności porównania.

OC_FORCED_ACTIVE: int

Tryb wymuszonej aktywności porównania na wyjściu (output-compare); pin jest wymuszony jako aktywny, a zgodność porównania jest ignorowana.

OC_FORCED_INACTIVE: int

Tryb wymuszonej nieaktywności porównania na wyjściu (output-compare); pin jest wymuszony jako nieaktywny, a zgodność porównania jest ignorowana.

IC: int

Konfiguruje kanał w trybie przechwytywania na wejściu (input-capture).

ENC_A: int

Tryb enkodera: licznik zmienia się tylko wtedy, gdy zmienia się CH1.

ENC_B: int

Tryb enkodera: licznik zmienia się tylko wtedy, gdy zmienia się CH2.

ENC_AB: int

Tryb enkodera: licznik zmienia się za każdym razem, gdy zmienia się CH1 lub CH2.

Polaryzacja porównania na wyjściu (output-compare) (argument polarity metody channel() w trybach OC):

HIGH: int

Wyjście jest aktywne w stanie wysokim.

LOW: int

Wyjście jest aktywne w stanie niskim.

Polaryzacja przechwytywania na wejściu (input-capture) (argument polarity metody channel() w trybie IC):

RISING: int

Przechwytywanie na zboczu narastającym.

FALLING: int

Przechwytywanie na zboczu opadającym.

BOTH: int

Przechwytywanie na dowolnym zboczu.