W projektach robotycznych i elektronicznych enkodery inkrementalne to kluczowe elementy do precyzyjnego pomiaru pozycji, prędkości obrotowej oraz sterowania silnikami krokowymi i serwo. Mikrokontrolery STM32 oferują sprzętową obsługę enkodera poprzez dedykowane tryby liczników (timery), co eliminuje potrzebę programowego debouncingu i zapewnia wysoką wydajność. Sprzętowy tryb enkodera odciąża CPU, zwiększa niezawodność pomiaru i upraszcza oprogramowanie sterujące.
Zasada działania enkodera inkrementalnego i rola timerów STM32
Enkoder inkrementalny generuje dwa sygnały kwadratowe – A i B – przesunięte o 90°. Kierunek obrotu określa kolejność zboczy: przy ruchu CW sygnał A wyprzedza B, a przy ruchu CCW – odwrotnie. Popularne enkodery (np. KY-040) dostarczają setki–tysiące impulsów na obrót.
Timery STM32 (np. TIM1, TIM2, TIM3, TIM4) w trybie Encoder Mode automatycznie dekodują te sygnały. Licznik (CNT) inkrementuje lub dekrementuje się na podstawie zboczy obu kanałów (CH1 i CH2). Dostępne warianty pracy są następujące:
- TI1 – zliczanie tylko na zboczach kanału 1;
- TI2 – zliczanie tylko na zboczach kanału 2;
- TI1 + TI2 – zliczanie na zboczach obu kanałów, co w praktyce daje do 4× większą rozdzielczość pomiaru względem jednego kanału.
W trybie Encoder Mode 3 (TI1+TI2) timer reaguje na przejścia obu kanałów, co zapewnia wysoką rozdzielczość i stabilny pomiar kierunku. Dodatkowo filtry wejściowe w blokach wejściowych timerów ograniczają drgania styków (bouncing), co jest szczególnie ważne przy enkoderach mechanicznych.
Konfiguracja timera w STM32CubeMX dla obsługi enkodera
Aby szybko rozpocząć pracę, skorzystaj z STM32CubeMX i wygeneruj kod startowy. Przykład dla płytki Nucleo (STM32F4) z enkoderem KY-040 wygląda następująco:
- W zakładce Pinout wybierz timer, np. TIM1.
- Ustaw tryb Combined Channels > Encoder Mode, co automatycznie przydzieli piny CH1 (np. PA8/D7) i CH2 (np. PA9/D8).
- W Configuration > TIM1 ustaw parametry wejść i licznika.
- Wygeneruj projekt z biblioteką HAL.
Kluczowe parametry w konfiguracji timera w trybie enkodera to:
- counter mode – Encoder mode TI1 + TI2 dla maksymalnej rozdzielczości;
- counter period – 65535 dla 16-bitowego timera (przepełnienie i zawijanie upraszcza arytmetykę); dla 32-bitowych (np. TIM2/TIM5) możesz ustawić 0xFFFFFFFF;
- polarity – zwykle rising edge; w razie odwróconego kierunku zamień polaryzację lub przewody A/B;
- input filter – dla enkoderów mechanicznych ustaw wyższą wartość (np. 8–15); przy szybkich enkoderach zmniejsz filtr (1–3), by nie ograniczać maksymalnych obrotów.
Po wygenerowaniu kodu otrzymasz uchwyt timera, np. htim1. W funkcji inicjalizacyjnej uruchom dekoder:
Uruchomienie trybu enkodera:
HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);
Odczyt pozycji z uwzględnieniem kierunku (konwersja do typu ze znakiem):
int32_t pozycja = (int16_t)htim1.Instance->CNT;
Dla mechanicznych enkoderów często uzyskasz ~4 zliczenia na jeden „klik” (detent), co jest prawidłowe i świadczy o poprawnej detekcji zboczy.
Integracja PWM z enkoderem – sterowanie silnikami w robotyce
W aplikacjach mobilnych i napędowych enkoder zasila pętlę sprzężenia zwrotnego (PID), a PWM steruje momentem/prędkością silnika. Połączenie: enkoder → pomiar prędkości/pozycji, PWM → sterowanie napędem to fundament precyzyjnego sterowania.
Przykład – sterownik silnika z PWM i enkoderem
Załóżmy: TIM2 generuje PWM (20 kHz, wypełnienie 0–100), TIM3 pracuje jako enkoder, a TIM4 służy do okresowych zadań (np. programowe PWM lub wywołania PID).
Konfiguracja w CubeMX może wyglądać tak:
- TIM2 CH3 (PB10) – PWM o częstotliwości ~20 kHz (np. Prescaler: 84-1, Period: 839), Clock Source: Internal;
- TIM3 – Encoder Mode na kanałach CH1/CH2, z odpowiednimi filtrami;
- TRGO z TIM2 – ustaw Master Output Trigger: Update, aby wyzwalać ADC synchronicznie z PWM (próbkowanie prądu podczas znanego stanu mostka).
Start i ustawienie wypełnienia PWM w HAL:
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 50); // 50% wypełnienia
Konfiguracja wyzwalania ADC (HAL):
TIM_MasterConfigTypeDef mcfg = {0};
mcfg.MasterOutputTrigger = TIM_TRGO_UPDATE;
mcfg.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim2, &mcfg);
Uproszczona regulacja na podstawie błędu pozycji (P-składnik):
int16_t blad = (int16_t)(zadana_pozycja - (int16_t)htim3.Instance->CNT);
int16_t pwm = previous_pwm + (int16_t)(Kp * blad);
if (pwm < 0) pwm = 0;
if (pwm > 100) pwm = 100;
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, (uint16_t)pwm);
Synchronizacja ADC z PWM pozwala mierzyć prąd/napięcie w przewidywalnym momencie cyklu, ograniczając szum i jitter pomiarów.
Dla przejrzystości zestawmy role użytych timerów w przykładzie:
| Timer | Zastosowanie | Częstotliwość | Uwagi |
|---|---|---|---|
| TIM2 | PWM silnika + TRGO dla ADC | 20 kHz | Synchronizacja próbkowania prądu |
| TIM3 | Enkoder (CH1/CH2) | – | Pomiar pozycji i prędkości |
| TIM4 | Okresowe zadania | 1 kHz | Programowe PWM, wywołania PID |
Obsługa zaawansowana – przepełnienie licznika i kierunek obrotów
Przepełnienie CNT: w 16-bitowym zakresie (0–65535) licznik zawija się, co jest wygodne w obliczeniach różnicowych (modulo). Na F4 timery TIM2/TIM5 są 32-bitowe – minimalizuje to ryzyko przepełnień przy bardzo szybkich obrotach.
Kierunek obrotu możesz odczytać przez status timera lub z różnicy kolejnych próbek CNT. W HAL dostępny jest skrót do sprawdzenia kierunku zliczania:
bool ccw = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim1); // true = CCW, false = CW
Dla enkoderów magnetycznych (np. AS5600) w trybie A/B obowiązuje identyczna konfiguracja wejść jak dla enkoderów mechanicznych.
Praktyczne wskazówki dla projektów robotycznych
- debouncing i filtry – dla enkoderów mechanicznych ustaw wyższy input filter, ale pamiętaj, że zbyt wysoki filtr ogranicza maksymalne RPM;
- wiele enkoderów – rozdziel je na różne timery (np. TIM1–TIM5). W STM32F4 dostępnych jest nawet kilkanaście timerów o różnych możliwościach;
- próbkowanie PID – odczytuj CNT i licz prędkość w przerwaniu stałookresowym (np. TIM4 1 kHz), a nie w pętli głównej;
- RTOS i warstwowanie – połącz STM32 HAL z FreeRTOS, oddzielając zadania: akwizycja, sterowanie, komunikacja;
- diagnozowanie błędów – przy złej polaryzacji kierunek bywa odwrócony; sprawdź CCxP, okablowanie A/B i rzutowanie do typu signed.
Połączenie: licznik enkodera + PWM otwiera drogę do stabilnych line followerów, platform różnicowych czy robotów balansujących – z precyzyjnym pozycjonowaniem i płynną regulacją napędu.