logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Jak podłączyć klawiaturę USB do wyświetlacza dotykowego z ESP32? Waveshare LVGL i tryb hosta USB

p.kaczmarek2 25 Lut 2026 10:37 1083 2

TL;DR

  • Na płytce Waveshare ESP32-S3-Touch-LCD-5 uruchomiono obsługę klawiatury USB HID z wyświetlaczem dotykowym i LVGL, tworząc prosty interfejs tekstowy na ESP32-S3.
  • Kluczowe elementy to tryb USB Host z ESP-IDF, rejestracja klienta USB, callbacki zdarzeń oraz własny bufor kołowy do podawania klawiszy do LVGL jako LV_INDEV_TYPE_KEYPAD.
  • Korzystano z PlatformIO, LVGL 8.4.0 i ArduinoOTA; konfiguracja obejmowała upload_protocol=espota oraz upload_port ustawiony na adres IP płytki.
  • Klawiatura działała poprawnie: litery, cyfry, znaki specjalne, strzałki, delete i backspace; dodatkowo pokazano dekodowanie myszy HID z osiami X, Y i Z.
  • Zwykły ESP32 nie obsługuje sprzętowego USB, a na tej płytce jedno złącze USB wymusiło użycie OTA zamiast wygodnego programowania przewodowego.
Wygenerowane przez model językowy.
REKLAMA
📢 Słuchaj (AI):
  • Płytka z ekranem dotykowym na klawiaturze; na ekranie tekst „Type on USB keyboard...” i podłączony kabel USB
    Czy da się podłączyć zwykłą klawiaturę USB do urządzenia z ESP32 i połączyć ją z wyświetlaczem dotykowym? Tak - to wcale nie jest takie trudne. W tym temacie krok po kroku pokażę, jak uruchomić tryb Hosta USB, zintegrować klawiaturę z LVGL i poprawnie obsłużyć zdarzenia wejścia.

    Prezentację oparłem na płytce z ESP-S3, a dokładniej Waveshare ESP32-S3-Touch-LCD-5, którą już wcześniej osobno omawiałem. Całość podzieliłem na etapy tak, aby sposób wdrażania klawiatury był bardziej przystępny i zrozumiały. Temat zakłada podstawową znajomość C++, ale w razie czego na końcu zamieszczę kod mojego przykładu.

    Warto również wiedzieć, czym jest HID, gdyż ten temat będzie dotyczyć urządzeń HID. HID (Human Interface Device) to standard klasy urządzeń USB przeznaczonych do komunikacji z użytkownikiem. Do tej grupy należą m.in. klawiatury, myszy, joysticki, gamepady oraz inne peryferia. Ich ogromną zaletą jest to, że system (lub mikrokontroler) nie musi znać konkretnego modelu urządzenia – wystarczy obsługa klasy HID, aby poprawnie odebrać dane wejściowe.

    HID komunikuje się poprzez proste pakiety danych zwane raportami. Ich struktura jest opisana w tzw. Report Descriptor, który urządzenie wysyła do hosta podczas enumeracji. To właśnie ten deskryptor mówi, ile bajtów ma raport, co oznacza każdy bit oraz jakie typy zdarzeń mogą się pojawić (np. klawisz wciśnięty, zwolniony, modyfikatory typu Shift czy Ctrl). Dla nas sprowadza się to jednak tylko do znajomości formatu raportu urządzenia który chcemy obsłużyć, i do odczytania z tego raportu klawiszy. Większość pracy zrealizuje za nas gotowa biblioteka od ESP IDF.

    Które układy z serii ESP obsługują USB? Podział umieściłem w tabelce, zrealizowane na bazie dokumentacji od espressif.
    UkładUSB OTG High-SpeedUSB OTG Full-SpeedUSB-Serial-JTAGFull-Speed PHYHigh-Speed PHY
    ESP32-P4
    ESP32-S3XX
    ESP32-S2XXX
    ESP32-C6XXX
    ESP32-C3XXX
    ESP32-C2XXXXX
    ESP32XXXXX
    ESP8266XXXXX

    Jak widać sprzętowe USB może być jednym z argumentów za wyborem nowszej wersji ESP, zwykły ESP32 go nie obsługuje. Stąd w temacie wybór S3, na nim można wygodnie uruchomić HID. Najpierw jednak środowisko pracy. Zaczynamy.

    Krok 1: LVGL
    Pierwszym etapem jest uruchomienie LVGL, czyli wyświetlania i sterownika ekranu dotykowego. Użyłem do tego zewnętrznej biblioteki:
    https://github.com/esp-arduino-libs/ESP32_Display_Panel
    Omawiałem to już w osobnym temacie:
    Waveshare ESP32-S3-Touch-LCD-5 - Wi-Fi, BLE, CAN, RS485 i ekran dotykowy 800x480
    5-calowy ekran dotykowy Waveshare ESP32-S3-Touch-LCD-5 z wyświetlonym komunikatem powitalnym „Hello Elektroda.com!” i parametrami testowymi.

    Krok 2: ArduinoOTA
    Drugim etapem jest uruchomienie aktualizacji wsadu przez Wi-Fi. Jest to niezbędne dla komfortowej pracy, bo na płytce mamy tylko jedno złącze USB, więc nie dałoby się jednocześnie programować i obsługiwać klawiatury, a odłączanie z każdą próbą sprzętu nie jest wygodne. ArduinoOTA już omawiałem w temacie:
    Jak programować płytkę Wemos D1 (ESP8266) w kształcie Arduino? ArduinoOTA w PlatformIO
    Tu przygotowałem połączenie ArduinoOTA z LVGL. Poniższy fragment inicjuje wyświetlanie, łączy ESP ze zdefiniowanym w kodzie punktem Wi-Fi i pokazuje nadany IP na ekranie. Dodatkowo cały czas nasłuchuje, czy nie jest wgrywana aktualizacja.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Najważniejsze jest połączenie z Wi-Fi, tego nie możemy zepsuć, bo będziemy znów wgrywali wsad przewodowo, oraz regularne sprawdzanie pakietów OTA - ArduinoOTA.handle w głównej pętli.

    Powiązane platformio.ini:
    
    [platformio]
    default_envs = Board_WaveShare5
    
    [env:Board_WaveShare5]
    framework = arduino
    platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.11/platform-espressif32.zip
    
    board = BOARD_CUSTOM_8MB
    monitor_speed = 115200
    upload_protocol = espota
    upload_port = 192.168.0.162
    monitor_port = com38
    lib_ldf_mode=deep
    lib_deps =
        https://github.com/esp-arduino-libs/ESP32_Display_Panel.git#v1.0.2
        https://github.com/esp-arduino-libs/ESP32_IO_Expander.git#v1.1.0
        https://github.com/esp-arduino-libs/esp-lib-utils.git#v0.2.0
        https://github.com/lvgl/lvgl.git#v8.4.0
    build_flags =
        -DLV_CONF_INCLUDE_SIMPLE
        -DLV_LVGL_H_INCLUDE_SIMPLE
        -DBOARD_WAVESHARE5=1
        -I src
    monitor_filters = esp32_exception_decoder
    
    

    Ustawienie upload_port na adres IP to nie błąd - w ten sposób mówimy ArduinoOTA, gdzie jest płytka.


    Krok 3: Wykrycie urządzenia USB
    Teraz uruchamiamy tryb USB Host w ESP32-S3 i sprawdzamy, czy do portu USB faktycznie zostało podłączone jakiekolwiek urządzenie. Jest to absolutna podstawa – zanim zaczniemy myśleć o klawiaturze HID, raportach i mapowaniu klawiszy do LVGL, musimy mieć pewność, że:
    - stos USB Host działa poprawnie
    - urządzenie przechodzi enumerację
    - potrafimy odczytać jego deskryptory
    Nasza płytka ma już złącze USB, ale tu uwaga - nie można pomylić tego z płytkami gdzie na USB jest wyprowadzony konwerter USB na UART. Tu nam zależy na sprzętowym USB, żaden CH340 tu nie przejdzie.
    Dodatkowo, jako że płytka ma złącze żeńskie USB C, to przyda się przejściówka męskie USB C na USB A żeńskie:
    Płytka ESP32-S3 z gniazdem USB-C obok przejściówki USB-A na USB-C i wtyku USB-A
    ESP32-S3 ma sprzętowy kontroler USB OTG, więc nie potrzebujemy żadnych zewnętrznych układów – wystarczy poprawnie skonfigurować bibliotekę USB Host z ESP-IDF, która jest dostępna również w środowisku Arduino.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Dodajemy nagłówek, a potem:
    - uruchamiamy bibliotekę USB Host (usb_host_install())
    - rejestrujemy klienta USB (usb_host_client_register())
    -ustawiamy callback usb_host_client_event_cb, który będzie informował nas o podłączeniu i utracie urządzenia klienta
    Funkcją usb_read_device_info tworzymy opis urządzenia pokazywany na ekranie.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Dodatkowo wywołujemy wszystko w init:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    oraz przetwarzamy zdarzenia USB w głównej pętli (usb_host_poll):
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod





    Ekran dotykowy z komunikatem o wykryciu urządzenia USB i podłączoną wtyczką USB-A

    Płytka z ekranem dotykowym pokazuje komunikat „USB device removed” i adres IP; obok wtyk USB



    Krok 4: Podstawowe zdarzenia klawiatury
    Teraz potrzebne są dwa dodatkowe mechanizmy:
    - przechwycenie klawiszy z klawiatury USB
    - obsługa pola tekstowego LVGL
    Tak się składa, że LVGL ma gotowy mechanizm pola tekstowego wraz z pełnoprawną edycją. Działa tam nawet kursor. Wystarczy zarejestrować sterownik przez strukturę lv_indev_drv_t i ustawić mu typ LV_INDEV_TYPE_KEYPAD. Dodatkowo ustawiamy funkcje, która będzie odczytywać zdarzenia klawiszy z bufora kołowego, tutaj kb_indev_read_cb.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    No tak, ale nie mamy żadnej kolejki - trzeba będzie ją samodzielnie zaimplementować. Poniżej na razie callback, który korzysta z mojej funkcji kb_ring_pop oraz z mojego bufora kołowego (warunek kb_ring_head != kb_ring_tail) do odczytywania klawiszy.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Oto właściwa implementacja bufora kołowego - zdarzenia są wstawiane za "głową" bufora, a jego "ogon" wskazuje na ostatnie nieprzetworzone zdarzenie. Bufor ma skończony rozmiar, w razie przepełnienia nie dodaje kolejnych zdarzeń.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Zostało jeszcze odebrać zdarzenia od klawiatury. Tylko skąd mamy wiedzieć, jak parsować pakiety HID? Można to wyczytać w dokumentacji:
    https://usb.org/sites/default/files/hid1_11.pdf
    Tabela z dokumentacji HID pokazująca raport wejściowy klawiatury (8 bajtów) i raport wyjściowy LED (1 bajt)
    Klawiatura raportuje zbiór wciśniętych w danym momencie klawiszy. Samodzielnie możemy potem określić, stan których klawiszy się zmienił, tj. które zostały zwolnione a które wciśnięte.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Rezultat:
    Ekran dotykowy z czarną ramką pokazuje wpisywany tekst z klawiatury USB i adres IP 192.168.0.162.
    Klawiatura jest poprawnie widziana. Działają litery, cyfry i znaki specjalne. Można robić duże litery, choć caps lock natywnie nie działa. Działają strzałki, można poruszać kursorem, można usuwać znaki klawiszami delete i backspace,

    Dodatek: eksperyment z myszką
    Analogicznie można obsłużyć myszkę zgodną z HID. Znowu musimy odnieść się do dokumentacji HID i dodać własny parsing pakietu w hid_transfer_cb.
    https://learn.microsoft.com/en-us/windows-har...ers/hid/keyboard-and-mouse-hid-client-drivers
    Cytat:

    ByteD7D6D5D4D3D2D1D0Comment
    100YsignXsign1MRLX/Y signs and R/L/M buttons
    2X7X6X5X4X3X2X1X0X data byte
    3Y7Y6Y5Y4Y3Y2Y1Y0Y data bytes
    4Z7Z6Z5Z4Z3Z2Z1Z0Z/wheel data byte


    Tak użyte dane można potem wyświetlić na ekranie, w ramach przykładu dodałem wyświetlanie poszczególnych odebranych raportów. Warto zwrócić uwagę, że nie mamy od myszki informacji o "absolutnym" położeniu kursora, jedynie mamy jego przesunięcie.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Powyższy kod poprawnie dekoduje raporty od myszki i odczytuje z nich przesunięcie w osiach X, Y oraz Z (kółko). Odczytywany jest również stan przycisków (wciśnięty lub nie).
    Ekran dotykowy z logami na niebieskim tle, podłączony przewodami; obok niebieska mysz USB


    Podsumowanie
    Sprzętowe USB w układach z serii ESP (ESP32-S2/S3/C3/P4) otwiera nowe możliwości, a jedną z nich jest pełnoprawna obsługa urządzeń HID takich jak właśnie pokazana klawiatura i myszka. Protokół HID jest bardzo prosty w użyciu, bo wszystko jest schowane za gotowymi bibliotekami, a my tylko odczytujemy bajty z raportów. W połączeniu z wyświetlaczem pozwala to zrobić namiastkę prostego mikrokomputerka działającego tak jak przykładowo ogólnoznane edytory tekstowe. W podobny sposób można też ożywić joystick lub gamepad.

    Następnym krokiem tutaj może być próba uruchomienia ESP z zewnętrznym hubem USB tak, aby móc podłączyć jednocześnie i myszkę, i klawiaturę, ale tego spróbuję w osobnym temacie.

    Załączam kod moich demek. Po więcej informacji odsyłam do dokumentacji od Espressif.
    https://docs.espressif.com/projects/esp-iot-s.../en/latest/usb/usb_overview/usb_overview.html
    https://github.com/espressif/esp-idf/blob/master/examples/peripherals/usb/host/hid/README.md

    Jakie widzicie praktyczne zastosowania do roli hosta USB na ESP?
    Załączniki:
    • usb_keyboard_basic.rar (33.83 KB) Musisz być zalogowany, aby pobrać ten załącznik.
    • usb_host_scan_demo.rar (33.81 KB) Musisz być zalogowany, aby pobrać ten załącznik.
    • usb_host_mouse_demo.rar (33.69 KB) Musisz być zalogowany, aby pobrać ten załącznik.

    Fajne? Ranking DIY
    Pomogłem? Kup mi kawę.
    O autorze
    p.kaczmarek2
    Moderator Smart Home
    Offline 
    Inżynier programista z wieloletnim doświadczeniem embedded i full stack developer.
    Specjalizuje się w: embedded, Full-Stack Developer
    p.kaczmarek2 napisał 14548 postów o ocenie 12551, pomógł 654 razy. Jest z nami od 2014 roku.
  • REKLAMA
  • #2 21848220
    chemik_16
    Poziom 27  
    Posty: 1000
    Pomógł: 74
    Ocena: 127
    to teraz pora na klawiaturę BT :D
    malo używany protokół w przypadku tych wszystkich ESP :)

    ciekawe też na ile można złapać sygnał 2.4Ghz który jest używany w bezprzewodowych klawiaturach z odbiornikiem usb, nie wiem jakim to standardem leci.
  • #3 21848225
    p.kaczmarek2
    Moderator Smart Home
    Posty: 14548
    Pomógł: 654
    Ocena: 12551
    Ciekawa sugestia, na Bluetooth to coś kolega @DeDaMrAz z OBK (OpenESP32) próbuje, ja na razie nie myślałem o tym, ale wezmę to pod uwagę.
    ESP32-C3 WiFi rozłącza się i uruchamia ponownie podczas testowania stosu BT - analiza dziennika debu

    Ja myślałem, by w następnej kolejności z tym hubem spróbować, myszka i klawiatura jednocześnie to by już było coś.
    Pomogłem? Kup mi kawę.
📢 Słuchaj (AI):
REKLAMA