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:

  1. W zakładce Pinout wybierz timer, np. TIM1.
  2. Ustaw tryb Combined Channels > Encoder Mode, co automatycznie przydzieli piny CH1 (np. PA8/D7) i CH2 (np. PA9/D8).
  3. W Configuration > TIM1 ustaw parametry wejść i licznika.
  4. 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.