Ten niepozorny moduł opiera się o ESP32 C3 i oferuje 1.44-calowy, kolorowy wyświetlacz o rozdzielczości 128x128, sterowany przez protokół SPI. Tutaj pokażę, jak łatwo można zacząć z nim przygodę, jak można wgrywać mu wsad zdalnie (przez WiFi), jak wyświetlić prostą animację oraz porównam szybkość wyświetlania pomiędzy programowym i sprzętowym SPI. Dodatkowo sprawdzę, czy starszy esptool poradzi sobie z ESP32-C3...
Produkt występuje często pod hasłem "ESP32 C3 Desktop Trinket Mini TV Portable Pendant LVGL 1.44inch LCD ST7735" i można go kupić za około 40 zł. Całość po zakupie dostałem w takim pudełeczku, odpowiednio zabezpieczone:
W zestawie jest też prosta obudowa oparta o dystanse oraz breloczek:
Załączona naklejka (czemu naklejka?) z kodem QR odsyła nas informacji od sprzedawcy.
I oto sam moduł:
Oprócz klasycznych przycisków BOOT (tryb bootloadera) i RESET mamy tutaj też dwa dodatkowe przyciski na IO8 i IO10, jak również mamy pady od kilku wyprowadzonych pinów.
Widać tu pamięć 25Q128JVSG (całe 16MB) oraz oczywiście ESP32-C3. Jest też złącze 1.27mm do podłączania ogniwa Li-Ion i złącze micro USB.
Informacje od sprzedawcy prowadzą do krótkiego samouczka/dokumentacji na stronie:
https://spotpear.com/wiki/ESP32-C3-desktop-tr...ortable-Pendant-LVGL-1.44inch-LCD-ST7735.html
Schemat:
Obsługą baterii Li-Ion zajmuje się tutaj PL4054. 3.3V (z 5V z USB) zapewnia CAT6219. Pamięć Flash to, jak wspomniałem, W25Q128, a wyświetlacz... wiadomo
Program demonstracyjny
Program demonstracyjny jest fabrycznie wgrany na płytkę i wyświetla obraz od razu po podaniu zasilania:
Nie znalazłem w sieci angielskojęzycznej instrukcji do jego obsługi, ale zasadniczo wymaga on tylko utworzenia na naszym telefonie punktu dostępu WiFi o danych:
spotpear
12345678
Następnie podłącza się do niego, a potem przez połączenie internetowe naszego telefonu pobiera informacje pogodowe dla naszej lokalizacji:
Na górnym pasku kolejno wyświetlane są pobrane dane.
Źródło programu można pobrać na Githubie:
https://github.com/Spotpear/ESP32C3_1.44inch
Kopia flashu i błąd Unexpected CHIP magic value 0x1b31506f
Na początek zacząłem od wykonania kopii oryginalnego fabrycznego programu i już wtedy natrafiłem na problem. Użyłem mojego sprawdzonego esptool.py, co się zainstalowało kiedyś razem z wsparciem ESP dla Arduino:
esptool.py read_flash 0 0x1000000 ESP32-C3-Desktop-Trinket-Mini-TV-Portable-Pendant-LVGL-1.44inch-LCD-ST7735.bin
pause
Ten esptool jednak nie rozpoznaje tej płytki:
To dlatego, że jest on w wersji 3.0.2, o czym świadczy sama ścieżka:
esp8266\hardware\esp8266\3.0.2\tools\esptool
Dlatego lepiej jest pobrać najnowszy esptool z Githuba - można już w postaci exe:
https://github.com/espressif/esptool/releases
Nowszy esptool-v4.8.1-win64.zip bez problemu dał radę zgrać wsad
esptool.exe read_flash 0 0x1000000 ESP32-C3-Desktop-Trinket-Mini-TV-Portable-Pendant-LVGL-1.44inch-LCD-ST7735.bin
pause
Kopię umieściłem tutaj:
https://github.com/openshwprojects/FlashDumps/tree/main/IoT/ESP32
Najprostszy program w PlatformIO
Niektórzy programują jeszcze w Arduino IDE, ale mi łatwiej jest w PlatformIO. Środowisko te stanowi dodatek do darmowego Visual Code, co szerzej opisywałem już wcześniej w tematach:
Jak programować płytkę Wemos D1 (ESP8266) w kształcie Arduino? ArduinoOTA w PlatformIO
Zegar na ESP12 i wyświetlaczu MAX7219 - tutorial - część 1, ArduinoOTA, podstawy
Utworzyłem nowy projekt. Nie znalazłem w płytkach tej konkretnej z tematu, więc użyłem innej z ESP32-C3.
Na początek uruchomiłem sam UART, bez wyświetlacza.
Kod: C / C++
Mój platformio.ini
[env:adafruit_qtpy_esp32c3]
platform = espressif32
board = adafruit_qtpy_esp32c3
framework = arduino
Jedno wywołanie "Upload and Monitor" później wszystko zaczęło działać zgodnie z oczekiwaniami:
Uruchamiamy wyświetlacz w PlatformIO
Ok, ale nie kupiliśmy tej płytki by nie korzystać z jej wyświetlacza. Trzeba go uruchomić.
Potrzebne będą do tego dwie biblioteki:
- adafruit/Adafruit ST7735 and ST7789 Library
- adafruit/Adafruit GFX Library
Można je dodać przez GUI PlatformIO:
... albo po prostu dopisać do naszego platformio.ini i PIO samo je pobierze:
[env:adafruit_qtpy_esp32c3]
platform = espressif32
board = adafruit_qtpy_esp32c3
framework = arduino
lib_deps =
adafruit/Adafruit ST7735 and ST7789 Library
adafruit/Adafruit GFX Library
Potem możemy uruchomić Hello World ST7735. Tu ważne jest odpowiednie ustawienie indeksów pinów, gdyż mogą się one różnić między modułami:
Kod: C / C++
Mamy tu kolejno:
- Adafruit_ST7735(int8_t cs, int8_t dc, int8_t mosi, int8_t sclk, int8_t rst) - uruchamia wyświetlacz w trybie programowego SPI (bit-bang)
- tft.initR(INITR_BLACKTAB) - inicjalizuje wyświetlacz z odpowiednią konfiguracją dla ST7735
- tft.fillScreen(color) - wypełnia cały ekran określonym kolorem
- tft.setCursor(x, y) - ustawia pozycję kursora
- tft.setTextColor(color) - ustawia kolor tekstu
- tft.setTextSize(size) - ustawia rozmiar tekstu
- tft.print(text) - wyświetla tekst w obecnym miejscu kursora
Rezultat:
Animacja i technika częściowego czyszczenia ekranu
Statyczny tekst to nie wszystko - tu można robić dość płynne animacje. Oczywiście wymaga to odpowiednich zabiegów optymalizacyjnych, a jednym z nich jest rysowanie na ekranie tylko tego, co uległo zmianie.
Przykładowo, gdy chcemy narysować prosty zegar, to zamiast z każdym ruchem wskazówki odświeżać cały ekran, możemy po prostu "zamazywać" wcześniejszą wskazówkę kolorem tła a potem rysować ją na nowo:
Kod: C / C++
Dużo się w kodzie nie zmieniło, zasadniczo na początku liczę tylko centrum ekranu a potem w funkcji od rysowania wskazówki też liczę jej końcówkę dla danego kąta (z trygonometrii). Punkt centrum łączę linią z obliczoną końcówką. To samo wywołuję w pętli dwa razy, raz dla "starej" wskazówki, zamalowuję ją kolorem tła, a potem dla "nowej" wskazówki - na biało.
Rezultat:
Aktualizacja wsadu przez sieć
Nie zapominajmy o Arduino OTA - prezentowałem to już m. in. tutaj:
Jak programować płytkę Wemos D1 (ESP8266) w kształcie Arduino? ArduinoOTA w PlatformIO
Zmodyfikujmy mój projekt tak, aby dodać zdalną aktualizację. Nowe PlatformIO.ini:
[env:adafruit_qtpy_esp32c3]
platform = espressif32
board = adafruit_qtpy_esp32c3
framework = arduino
lib_deps =
adafruit/Adafruit ST7735 and ST7789 Library
adafruit/Adafruit GFX Library
ArduinoOTA
[env:adafruit_qtpy_esp32c3_ota]
extends = env:adafruit_qtpy_esp32c3
upload_protocol = espota
upload_port = 192.168.0.192
Nowy kod:
Kod: C / C++
Dodane ArduinoOTA.begin(); inicjuje system OTA, a z kolei równie ważne jest regularne wywołanie ArduinoOTA.handle();, które obsługuje samą aktualizacje.
Po pierwszym wgraniu sprawdzamy IP płytki na routerze i wpisujemy je do wspomnianego już platformio.ini:
Teraz na pasku bocznym mamy dwie grupy zadań, uruchamiamy wgrywanie z grupy OTA:
Program zostaje zaktualizowany zdalnie:
Kolory
Na tej płytce jest nieco większy wybór kolorów niż do tej pory pokazałem. Oto zmodyfikowany kod "zegara", tak aby wskazówka zmieniała kolor w zależności od tego w której ćwiartce ekranu się znajduje:
Kod: C / C++
Rezultat:
Przyśpieszamy rysowanie
Do tej pory pokazywałem przykłady w wersji opartej o programowe, wolne SPI. Takie SPI jest realizowane poprzez programowe "machanie" pinami, co zresztą widać w kodzie biblioteki (patrz sekcja TFT_SOFT_SPI):
Kod: C / C++
ale dostępna jest też opcja hwspi, czyli SPI sprzętowe.
To, jakie SPI zostanie użyte zależy od użytego konstruktora.
W celu uruchomienia sprzętowego SPI należy wprowadzić drobną zmianę:
Kod: C / C++
Reszta kodu analogicznie. Teraz pytanie, jak dużo nam to daje?
Zróbmy w tym celu mały benchmark, test wydajności:
Kod: C / C++
Powyższy kod zapisuje bieżący czas a potem wypełnia wielokrotnie ekran różnymi kolorami za pomocą funkcji fillScreen. Potem bieżący czas jest pobierany ponownie i obliczane jest ile trwał cały proces.
Uruchomiłem go dla obu wersji i porównałem wyniki:
Programowe SPI: 16 014ms
Sprzętowe: 470ms
Sprzętowe SPI jest w tym przypadku ponad 30 razy szybsze. Zdecydowanie zrobi to odczuwalną różnicę, zwłaszcza przy częstym odświeżaniu ekranu.
Demonstracja różnych funkcji
Ten wyświetlacz potrafi jeszcze nieco więcej, w związku z tym zdecydowałem się przerzucić na niego program "graphicstest" od Adafruit:
https://raw.githubusercontent.com/adafruit/Ad...master/examples/graphicstest/graphicstest.ino
Program wymagał tylko zmiany pinów i portu z konstruktora klasy Adafruit_ST7735:
Kod: C / C++
Rezultat:
Przyciski i ich obsługa
Na koniec warto pokazać użycie przycisków na pinach IO8 i IO10. W najprostszej wersji można do ich obsługi wykorzystać pinMode i zwykłe digitalRead. Nie będę tutaj przejmować się drganiem styków, problem rozwiążę dodając blokujący delay w kodzie. W oparciu o te przyciski można zrealizować np. nawigację w menu:
Kod: C / C++
Powyższy kod można by znacznie usprawnić, przede wszystkim usuwając blokujące delay, jak również też optymalizując wyświetlanie menu - zamiast rysować je całe za każdym razem od nowa, można by po prostu tylko zamalowywać strzałkę i rysować ją w nowym miejscu. Rezultat:
Uproszczona znacznie biblioteka obsługi ST7735 w jednym pliku/projekcie
Tutaj bez większego komentarza, ale może komuś się przyda.
Chciałem zapoznać się bliżej z obsługą ST7735 i przerobiłem sobie bibliotekę od Adafruit tak, aby miała raptem 600 linijek kodu i to w stylu C (bez klasy). Całość obsługuje tylko programowe SPI (bit-bang) oraz potrafi tylko rysować proste kształty, nie ma tu czcionki. Wszystko jest w jednym projekcie PlatformIO:
Moje uproszczone demko:
Kod: C / C++
Rezultat:
Do pobrania:
Podsumowanie
Bardzo ciekawy moduł. Można nieco projektów zrobić, a do wszystkiego są gotowe biblioteki. Wyświetlacz można wysterować zarówno sprzętowo (wydajnie), jak i programowo, choć ta druga opcja raczej tu się nie przyda. Pamięci Flash jest dużo, bo całe 16MB. Oprócz przycisków boot i reset są jeszcze wyprowadzone dwa GPIO, więc można czymś posterować już bez lutowania, a i jeśli chcemy dodatkowe peryferia, to taka opcja też jest.
Nie testowałem natomiast zasilania z baterii i tu mam pewną wątpliwość, ile to podziała z tym wyświetlaczem na ogniwie? Nie jest on za jasny? Pobór prądu mojego przykładu z wyświetlaczem to około 70-100mA...
Czy korzystaliście z tego modułu, jakie widzicie dla niego zastosowania?
Fajne? Ranking DIY Pomogłem? Kup mi kawę.