Podłączenie modułu LCD z ST7796 do ESP8266

Od niedawna mamy w ofercie 4-ro calowe moduły LCD TFT ze sterownikiem ST7796 i warstwą dotykową (XPT2046). Oprócz tego moduł ma slot na kartę SD (oddzielne wyprowadzenie). W tym wpisie zajmiemy się kwestią podłączenia i sterowania wyświetlaczem. Obsługę warstwy dotykowej zostawimy sobie na inną okazję.

Podłączać będziemy do ESP8266 (więcej pamięci niż przeciętne Arduino) i mamy załatwioną kwestię poziomów logicznych. Otóż LCD można zasilić 5V ale linie danych nie przyjmą napięcia 5V. ESP8266 pracuje z napięciami 3.3V więc nie ma problemu. Inaczej zostaje stosowanie konwerterów poziomów logicznych (w odpowiedniej ilości). Do testów korzystam z Wemosa D1 mini, ale każda płytka z ESP8266 będzie ok.

No to jak podłączyć?

ESP8266
piny wg nazewnictwa Arduino
ESP8266
GPIO
pin na module LCD
3.3VLED
D514SCK
D713SDI(MOSI)
D30DC/RS
D42RESET
D24CS
GNDGNDGND
5VVCC
Tabela z opisem podłączenia

No dobra, przewody wpięte, ale po podaniu zasilania mamy tylko biały ekran. Trzeba teraz opanować software. Na szybko odnajdziemy dwie biblioteki: Arduino GFX oraz TFT_eSPI. Udało się wyświetlacz uruchomić korzystając z obu, jednak na Arduino GFX nie udało mi się wyświetlić obrazka, mimo różnych prób i kombinacji z formatem danych. Jako że TFT_eSPI nie stwarzało problemów, machnąłem ręką na GFX. Zresztą TFT_eSPI wydaje się być nieco szybszą.

Na końcu wpisu znajdziecie link do archiwum z przykładowym kodem – projektem w Platformio mającym dwa środowiska, każde kompilujące przykład korzystający z jednej z bibliotek. W głównym pliku w zależności od wybranego środowiska załączany jest albo etft.h (obsługa z użyciem TFT_eSPI) albo libGFX.h (Arduino GFX). Macie dobry punkt startowy.

Sterowanie ST7796 z użyciem TFT_eSPI

Jak wspomniałem, ta biblioteka bardziej mi przypadła do gustu, zwłaszcza że obiecuje w przypadku użycia ESP32 możliwość skorzystania z DMA, co powinno dać ciekawe efekty jeśli chodzi o szybkość.

Konfiguracja biblioteki polega na wskazaniu które piny zostały wykorzystane do podłączenia. W przypadku Platformio, do zmiennych środowiska trzeba dodać dyrektywę -DUSER_SETUP_LOADED=1, która spowoduje nieładowanie ustawień. Oznacza to że wszystkie dane trzeba podać w postaci kolejnych dyrektyw. Znający Platformio wiedzą że po prostu dopisuje się je do build_flags w platfomio.ini. I tak całość będzie wyglądać tak:

build_flags =
    -DUSER_SETUP_LOADED=1
    -DST7796_DRIVER=1
    -DTFT_WIDTH=320
    -DTFT_HEIGHT=480
    -DTFT_MISO=12
    -DTFT_MOSI=D2
    -DTFT_SCLK=14
    -DTFT_CS=4
    -DTFT_DC=0
    -DTFT_RST=2
    -DLOAD_GLCD=1
    -DLOAD_FONT2=1
    -DLOAD_FONT4=1
    -DLOAD_FONT6=1
    -DLOAD_FONT7=1
    -DLOAD_FONT8=1
    -DLOAD_GFXFF=1
    -DSMOOTH_FONT=1
    -DSPI_FREQUENCY=40000000

Kolejne -D ustawiają dyrektywy które zawierają informacje – jakiego sterownika użyć, jaka jest rozdzielczość, które pin y zostały użyte i jakie fonty mają być dostępne.

Dla tych, którzy korzystają ze środowiska Arduino IDE – na szybko można poprawić przygotowane szablony konfiguracji, najbliższy docelowej będzie zestaw nr 28 znajdujące się w katalogu UserSetups. Trzeba odnaleźć ten plik i zakomentować linię #define RPI_DISPLAY_TYPE. Następnie zaraz po załączeniu pliku nagłówkowego biblioteki załączyć trzeba plik z konfiguracją. Całość wygląda tak:

#include <TFT_eSPI.h>
#include <User_Setups/Setup28_RPi_ST7796_ESP8266.h>

Jest to rozwiązanie do jakiś szybkich testów. Niestety Arduino IDE nie dorobiło się (nawet w wersji 2.x) sensownego zarządzania wersjami bibliotek (to jest jedna z wielkich przewag Platformio). Dlatego, gdy zrobisz sobie te poprawki do konfiguracji nr 28, po aktualizacji biblioteki którą zrobisz (albo IDE automatycznie) zostaną nadpisane nową wersją. Co radzi autor biblioteki? Przenieść swój plik konfiguracyjnych do oddzielnego katalogu (o unikalnej nazwie), który będzie w folderze z innymi szkicami. Gdzie są szkice można sprawdzić w oknie dialogowym konfiguracji IDE po naciśnięciu Ctrl+,. Wtedy załączenie takiego pliku konfiguracyjnego będzie wyglądać mniej więcej tak:

#include "../TWOJ_FOLDER_Z_KONFIGURACJAMI/tft_espi_config.h" 

Co jeśli, mimo wybranej konfiguracji nie masz obrazu na ekranie? Albo jest on zniekształcony, przesunięty? Dołącz do programu dyrektywę włączającą setupDebug.h oraz przywróć wywołanie testSetup() w funkcji setup. Wtedy podczas startu na Serial zostanie wypisana cała konfiguracja biblioteki – jakie piny, jaki sterownik. Będziesz wiedział czy udało się ustawić właściwe parametry. Oczywiście nie zapomnij sprawdzić drugi i trzeci raz czy przewody ESP<->LCD są prawidłowo połączone. O pomyłkę naprawdę łatwo.

Jak sterować wyświetlanymi treściami? Wszystko odbywa się przez obiekt, który trzeba utworzyć i ustawić parę parametrów:

TFT_eSPI tft = TFT_eSPI();
tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);

Jeśli uważnie patrzyłeś na parametry w konfiguracji może zauważyłeś, że domyślna szerokość to 320px a wysokość to 480px. Ustawienie z wertykalnego na horyzontalne można ustawić przez setRotation. Są po dwa ustawienia dla każdej orientacji. Czyli nie będzie problemu ustawić w dowolny sposób ekranu, nie trzeba będzie przeliczać wszystkich współrzędnych w zależności od ustawienia. Sterownik zrobi to za was.

Do testów wyświetlacza obrazek przechowywałem w pamięci Flash, jako tablicę danych. Dobry człowiek napisał i udostępnił konwerter online obrazków do kodu w C, także możecie sami z niego korzystać. Poniższy zrzut ekranu pokazuje jak został wygenerowany plik ntg_napis.h z którego wyświetla się ładnie nasze logo.

Mając już tablicę z obrazkiem wystarczy użyć pushImage by wysłać obrazek na wybrane miejsce na ekranie.

Sterowanie ST7796 z użyciem Arduino GFX

Drugi przykład jest z wykorzystaniem biblioteki Arduino GFX. Jak już wspomniałem, nie udało mi się wyświetlić obrazka (mimo różnych formatów kończyło się to wyjątkiem i restartem) jednak pozostałe funkcje (wyświetlanie tekstów) działają poprawnie. Dla początkujących, zwłaszcza korzystających z Arduino IDE konfiguracja biblioteki do pracy może być łatwiejsza niż TFT_eSPI.

Arduino GFX używa więcej abstrakcji w budowie swojego interfejsu, dzięki czemu łatwiej jej użyć, ale przez to operacje są minimalnie wolniejsze (ale nie jest to jakoś mocno zauważalne).

Na ESP8266 możemy skorzystać ze sprzętowego SPI, więc wystarczy użyć klasy Arduino_HWSPI (HW – hardware SPI) jako szyny danych. Do jej konfiguracji wystarczy podać dwa piny – DC oraz CS. Następnie mając obiekt reprezentujący szynę danych, przekazujemy go tworząc drugi obiekt, już samego ekranu, korzystając z klasy odpowiadającej ST7796. Tutaj tylko trzeba wskazać pin RESET. Całość konfiguracji wygląda tak:

Arduino_DataBus *bus = new Arduino_HWSPI(D3 /* DC */, D2 /* CS */);
Arduino_GFX *gfx = new Arduino_ST7796(bus, D4 /* RST */);

Teraz mamy obiekt gfx na którym wykonujemy operacje na naszym ekranie. No i tutaj też mamy setRotation powalając na łatwe obracanie ekranem.

Kod do pobrania jest w tym archiwum.