Remote Control Transceiver (RMT) w ESP32 to specjalny moduł sprzętowy, który umożliwia precyzyjne generowanie i odbieranie sygnałów czasowych, takich jak sterowanie IR i RF. Tutaj pokażę jak go uruchomić i wykorzystać do obsługi diod WS2812B, które są znane z tego, że potrzebują dość precyzyjnego przebiegu na wejściu DI w celu uzyskania danych o kolorach. Przy okazji obejrzymy generowane przebiegi na oscyloskopie.
Na początku przypomnę poprzednie tematy z serii. Pierwsze, najważniejsze omówienie WS2812 i podobnych:
PIC18F45K50 jako sterownik paska LED WS2812 (teoria+biblioteka)
Poboczny temat, metoda ze sprzętowym SPI i DMA:
Sterowanie diodami WS2812 przez SPI z DMA - użycie MOSI do generowania timingów
Tym razem program wykonam w oparciu o ESP32:
Prezentację zaczynam od swojego klasycznego kodu integrującego WiFiManager oraz OTA (aktualizację wsadu przez WiFi):
Kod: C / C++
Trzeba też również przywołać dokumentację na której tu bazuję:
https://docs.espressif.com/projects/esp-idf/e...able/esp32/api-reference/peripherals/rmt.html
Przygodę zaczynamy od załączenia nagłówka biblioteki:
Kod: C / C++
Potem trzeba zainicjować RMT. Inicjalizacja obejmuje:
- ustawienie trybu (RMT_MODE_TX dla nadawania lub RMT_MODE_RX dla odbioru)
- wybór kanału (RMT_CHANNEL_0 do RMT_CHANNEL_7)
- ustawienie numeru pinu GPIO, z którym RMT będzie współpracować (enumeracja GPIO_NUM_4, co upraszcza się do numerycznego 4)
- konfiguracja liczby bloków pamięci do przechowywania danych
- konfiguracja trybu nadawania, w tym włączenie/wyłączenie pętli, nośnika, czy ustawienie poziomu bezczynności (niski lub wysoki)
- konfiguracja dzielnika zegara, gdyż czasy wysokie i niskie stanów są wyrażane w cyklach
Domyślnym wejściem zegara jest APB_CLK, czyli 80MHz. Jak ustawimy dzielnik zegara na 2, to zegar RMT to 40MHz. Wtedy jeden cykl ma 25 ns.
Kod: C / C++
Teraz można coś nadać, pamiętając o tym, że jeden cykl to 25 ns. Skoro jeden cykl to 25 ns, to wybierzmy sobie na próbę wartość 50, co da nam 50*25ns = 1.25 μs. A więc teraz ustawiamy tablicę obiektów rmt_item32_t , gdzie każdy z nich opisuje osobno jeden stan wysoki i niski. Mamy kontrolę nad tym, kiedy i jak długo trwają te stany. Zarówno dla niskiego, jak i dla wysokiego wpisałem 50. Potem ustawiamy te dane i wysyłamy.
Kod: C / C++
Obie funkcje odpowiednio podłączyłem do setup i loop.
Teraz można podłączyć oscyloskop. Potrzebny będzie tryb Single, wyzwalanie impulsem, musimy złapać ten moment w którym ESP wyśle dane:
Użyłem funkcji Cursor, by zmierzyć przebieg. Jest dobrze, błąd jest pomijalny (ręcznie ustawiałem). Wszystko działa, teraz można poeksperymentować.
Krótszy stan niski pierwszego cyklu:
Kod: C / C++
Pora przerobić to na obsługę WS2812B. Zaczynamy od lektury noty katalogowej:
Najpierw mamy T0H - 0.4us. Ile cykli to będzie 0.4us? 0.4us/25ns = 16.
Podobnie liczymy pozostałe czasy. Wyszło mi:
Kod: C / C++
WS2812B korzysta z 8-bitowego RGB. W sumie mamy 24 bity - po 8 bitów na kanał. Potrzebne zatem będą nam 24 obiekty struktury rmt_item32_t.
Kod: C / C++
Do głównej pętli dodałem:
Kod: C / C++
Miga zielony... no tak, ale to nie błąd. Format oczekiwany to GRB.
To teraz dwa kolory:
Kod: C / C++
Kolejnym krokiem jest uogólnienie przypadku dla N pikseli, a może nawet lepiej - dla N bajtów, bo niektóre paski mają format RGBW.
Kod: C / C++
W ten sposób można zrobić efekty gdzie każdy piksel ma inny kolor:
Kod: C / C++
Step to licznik który określa bieżącą klatkę animacji.
Można też użyć HSV i zrobić lepszą animację tak jak w WLED, ale to już nieco poza zakresem tego tematu:
Kod: C / C++
Rezultat:
Tyle na dzisiaj starczy... sterowanie WS2812B niewątpliwie działa, a i w razie potrzeby zawsze można zmienić czasy tak, by dopasować je do innego rodzaju LEDów. Obsługa dodatkowego kanału, bieli, też nie będzie problemem, bo kod zamieniający bajty na dane RMT i tak "nie musi wiedzieć" jakie jest znaczenie poszczególnych bitów.
W temacie poczyniłem pewne uproszczenia, ale myślę, że to nie jest problem i na bazie pokazanego tu rozwiązania można budować własny sterownik WS2812. Załączam pełen projekt w PlatformIO:
Fajne? Ranking DIY Pomogłem? Kup mi kawę.