← wszystkie projekty
ubuntowany@panel:~$ whoami nie kupiłem gotowego HAT-a. gołe GPIO, kawałek po kawałku. ubuntowany@panel:~$ cat /etc/motto "jeśli sterownik nie istnieje w jądrze, napisz mu własny overlay."
panelik.

Tani ekran dotykowy SPI (3.5", 480×320, ILI9488+ADS7846) jako fizyczny panel kontrolny do dowolnego headless RPi — od gołych pinów, przez sterownik którego nie ma w jądrze, po własną apkę w Pythonie. Opisane tak, żeby dało się to powtórzyć bez dyplomu z elektroniki.

ILI9488 ADS7846 Raspberry Pi luma.lcd poziom: hobbysta
o projekcie

Co to w ogóle jest ten panelik?

Masz gdzieś headless-a — Raspberry Pi bez monitora i klawiatury, który siedzi cicho w kącie i coś robi. Żeby sprawdzić, czy żyje, zawsze musisz się do niego dołączyć po SSH. panelik to sposób, żeby ten sam RPi miał własny, mały ekran dotykowy: pokazuje status na żywo i pozwala coś przełączyć bez wpisywania jednej komendy.

To nie jest gotowy produkt do kupienia — to metoda i kod do powtórzenia na swoim sprzęcie. Ekran, który tu opisujemy, jest tani i popularny, ale ma dwie pułapki, o które rozbija się większość poradników w internecie: kernelowy sterownik fbtft go nie obsługuje, a dotyk trzeba samemu skalibrować. Ten tekst prowadzi przez obie od razu.

filozofia

Dla kogo to jest

Nie dla profesjonalistów

Nie zakładamy, że kiedykolwiek lutowałeś. Każde połączenie na schemacie niżej jest opisane po ludzku — co to jest i do czego służy, a nie tylko numer nóżki GPIO.

Dla ludzi z headless RPi

Jeśli masz jakikolwiek Raspberry Pi pracujący w tle i choć raz pomyślałeś „szkoda, że nie widzę na oko czy to działa" — to dokładnie ten problem rozwiązuje panelik.

zakupy

Z czego to jest zbudowane

Lista rzeczy, które musisz mieć, zanim zaczniesz cokolwiek podłączać.

elementco robi
Raspberry Pi (testowane: 3 Model B Plus)mózg panelu — starczy dowolny model z pełnym złączem GPIO 40-pin
Ekran SPI 3.5", ILI9488, 480×320goły breakout (nie HAT z automatycznym mapowaniem) — obraz
Kontroler dotyku ADS7846 (rezystancyjny)zwykle wlutowany na tej samej płytce co ekran — dotyk
Karta microSD, min. 8GBRaspberry Pi OS (Debian, testowane na trixie)
Zasilacz 5V (micro-USB lub USB-C, wg modelu RPi)zasilanie całości
Przewody żeńsko-żeńskie (jumper wires)to goły breakout — każdy pin łączysz ręcznie
Obudowa dopasowana do panelu 3.5" (opcjonalnie)uwaga: wąski bezel potrafi przyciąć obraz — patrz „Pułapki"

Zaprojektowałem też pasującą obudowę 3D (snap-fit, bez śrub) — plik do druku jest publiczny: Raspberry Pi 3 snap-fit case 4in display na MakerWorld.

schemat

Co gdzie podłączyć

RPi jest w środku. To goły breakout, nie HAT — nic się nie mapuje samo, każdy pin łączysz ręcznie zgodnie ze schematem niżej. Zasilanie modułu ekranu: VCC → 3.3V, GND → dowolna masa RPi.

Raspberry Pi GPIO 40-pin · serce panelu zasilanie: 5V Ekran ILI9488 480×320, magistrala SPI0 CS → GPIO8 (CE0) RESET → GPIO25 DC → GPIO24 MOSI → GPIO10 SCK → GPIO11 MISO → GPIO9 LED (podświetlenie) — patrz osobny blok niżej Dotyk ADS7846 rezystancyjny, ta sama płytka T_CS → GPIO7 (CE1) T_IRQ → GPIO17 CLK/DIN/DO współdzielone z ekranem (GPIO11/10/9) Podświetlenie (LED) sterowane programowo LED → GPIO18 (fiz. pin 12) domyślny pin luma.lcd — patrz „Pułapki"

Schemat: RPi w środku, a wokół trzy grupy sygnałów. Kolor linii = do czego prowadzi, numery w ramkach = konkretne piny GPIO do wpięcia przewodu.

ekran (SPI) dotyk (ADS7846) podświetlenie

Dotyk dzieli z ekranem trzy linie magistrali (CLK/DIN/DO) — osobny ma tylko wybór chipu (T_CS) i przerwanie (T_IRQ). To normalne dla SPI: wiele urządzeń może siedzieć na jednej magistrali, dopóki każde ma własny CS.

instalacja

Sterownik, którego nie ma w jądrze

To jest ten etap, na którym większość poradników w internecie wysyła cię w złą stronę. Tu jest droga, która faktycznie działa.

Zanim zaczniesz kombinować z konfiguracją — sprawdź jedną rzecz. Kernelowy moduł fbtft (ten, którego używa większość tutoriali do tanich ekranów SPI) obsługuje sporo podobnych chipów — ILI9486, ILI9481, ILI9341 — ale nie ILI9488. Sprawdzisz to sam:

$ ls /lib/modules/$(uname -r)/kernel/drivers/staging/fbtft/ | grep ili # brak fb_ili9488.ko

Jeśli Twój ekran to naprawdę ILI9488 (sprawdź naklejkę/dokumentację modułu), dtoverlay=fbtft,...,ili9488,... nigdy nie zadziała — to nie kwestia złych pinów, sterownik po prostu nie istnieje w tym jądrze. Nie trać na to czasu.

Rozwiązanie: sterowanie z userspace, nie z kernela. Biblioteka luma.lcd ma gotową klasę dokładnie pod ten chip — nie substytut, prawdziwy match.

$ pip install --break-system-packages luma.lcd luma.core pillow gpiozero evdev # Debian trixie: PEP668
from luma.core.interface.serial import spi
from luma.lcd.device import ili9488
serial = spi(port=0, device=0, gpio_DC=24, gpio_RST=25)
device = ili9488(serial, width=480, height=320, rotate=0)

Brakujący /dev/spidev0.0 — i dlaczego, naprawdę. Fora sugerują, że overlay ads7846 globalnie wyłącza SPI0 dla innych urządzeń. To nieprecyzyjne. W drzewie urządzeń magistrala spi0 ma domyślnie już zdefiniowane dzieci spidev@0 i spidev@1, oba wyłączone — ads7846 po prostu włącza własny węzeł na cs=1, nigdy nie dotyka spidev@0. Po prostu nikt go wcześniej nie włączył.

Ślepa uliczka do ominięcia: dtoverlay=spi0-1cs. Wygląda na oczywistą poprawkę — jest w wielu poradnikach. Dopisanie tej linii przed ads7846 w config.txt i restart spowodowały, że RPi całkowicie zniknął z sieci — nawet ping z routera odpowiadał „Destination Host Unreachable". Ratunek wymagał fizycznego wyjęcia karty SD i przywrócenia config.txt z backupu na innym komputerze (partycja bootowa to zwykły FAT32, widoczny bez specjalnych narzędzi). Przyczyna: ten overlay przedefiniowuje piny CS dla całej magistrali, kolidując z tym, co już zajął ads7846. Nie używaj go, gdy ads7846 już jest załadowany na tej samej magistrali.

Działające rozwiązanie: chirurgiczny custom overlay. Zamiast globalnie przedefiniowywać magistralę, minimalny overlay, który tylko włącza już istniejący węzeł spidev@0 i nic więcej nie rusza:

/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2835";
fragment@0 {
target-path = "/soc/spi@7e204000/spidev@0";
__overlay__ { status = "okay"; };
};
};
$ dtc -@ -I dts -O dtb -o /boot/firmware/overlays/spidev0-enable.dtbo spidev0-enable.dts
$ sudo dtoverlay /boot/firmware/overlays/spidev0-enable.dtbo # test na żywo, zero ryzyka
$ echo "dtoverlay=spidev0-enable" | sudo tee -a /boot/firmware/config.txt # dopiero po potwierdzeniu

Złota zasada, wyniesiona z bólu: zawsze testuj nowy overlay komendą sudo dtoverlay <plik.dtbo> na żywym systemie, zanim dopiszesz go do config.txt i zrobisz restart. Live-loading patchuje działające jądro i jest w pełni odwracalne (sudo dtoverlay -r <nazwa>) bez ryzyka utraty dostępu. Merge overlayów przy starcie dzieje się w bootloaderze, przed startem jądra — zły overlay potrafi tam zawiesić maszynę tak, że znika z sieci całkowicie, a jedyny ratunek to fizyczny dostęp do karty SD. I zawsze rób cp config.txt config.txt.bak-<data> przed każdą zmianą.

dotyk

Kalibracja — nie ufaj domyślnym wartościom

Surowe odczyty z ADS7846 nie mają nic wspólnego z orientacją ekranu, dopóki im tego nie każesz.

Zależnie od fizycznego montażu konkretnej płytki (jak driver siedzi względem panelu), surowe osie X/Y bywają zamienione miejscami i odwrócone względem tego, co widzisz na ekranie. Nie zakładaj, że Twoja płytka zachowa się tak samo jak nasza — zawsze kalibruj dotykiem czterech rogów i wylicz transformację samodzielnie, zamiast ufać domyślnym xmin/xmax/ymin/ymax z dtoverlaya.

Metoda: dotknij po kolei każdy z czterech rogów ekranu, zapisz surowe wartości ABS_X/ABS_Y z evtest lub własnego loggera, a potem policz liniową transformację między surowym zakresem a pikselami ekranu. U nas skończyło się to tak (Twoje liczby będą inne — to tylko przykład metody):

Y_AT_X0, Y_AT_X480 = 3826.65, 409.80
X_AT_Y0, X_AT_Y320 = 3718.63, 422.56
def map_touch(raw_x, raw_y):
sx = (Y_AT_X0 - raw_y) / (Y_AT_X0 - Y_AT_X480) * W
sy = (X_AT_Y0 - raw_x) / (X_AT_Y0 - X_AT_Y320) * H
return max(0, min(W, sx)), max(0, min(H, sy))
wiedza wyniesiona z bólu

Pułapki przy budowie apki

Ekran już działa i dotyk jest skalibrowany — teraz zaczynają się pułapki na poziomie samej aplikacji.

przykład

Co można na tym zbudować

U nas panelik pokazuje i przełącza most VPN+WiFi na tym samym RPi — to tylko jeden z możliwych przykładów, ale pokazuje wzorce warte powtórzenia.

przełączniki dotykoweVPN i WiFi/AP włącz/wyłącz jednym dotknięciem
status z wielu sygnałów naraznie tylko systemd — też stan fizycznego łącza i adres tunelu
licznik klientów WiFiz kernela (stacje faktycznie stowarzyszone), nie z leasów DHCP
wygaszacz ekranupierwszy dotyk tylko budzi, nie triggeruje akcji
temperatura + uptimew stopce, na żywo

Ten sam wzorzec — ekran + dotyk + status z systemd/kernela + usługa systemowa — działa równie dobrze do sterowania czymkolwiek innym na headless RPi. Sprzęt i sterownik zostają te same, zmienia się tylko to, co rysujesz i co przełączasz. Kilka pomysłów na start:

Przenośny punkt dostępu VPN

Dokładnie to, co u nas — RPi wystawia własne WiFi i tuneluje ruch do domowej sieci, więc w podróży jednym dotknięciem łączysz się ze swoimi zasobami tak, jakbyś siedział w domu.

Panel dla innej usługi

Serwer plików, drukarka 3D, stacja pogodowa, kolejny host w home labie — ten sam ekran + dotyk, inny systemctl pod spodem.

sposób pracy

Uruchomienie jako usługa

Apka ma przetrwać restart RPi i wracać sama po awarii — nie ma jej sensu odpalać ręcznie w terminalu.

[Service]
User=root # dostęp do /dev/spidev0.0 i /dev/input/eventX bez kombinowania z grupami
ExecStart=/usr/bin/python3 /home/pi/panelik.py
Restart=on-failure
$ sudo systemctl enable --now panelik.service

Jedna pułapka: skoro usługa działa jako root, a nie jako Twój zwykły user, biblioteki trzeba doinstalować osobno dla roota (sudo pip install --break-system-packages ...) — inaczej dostaniesz ModuleNotFoundError mimo że wszystko działało w Twojej sesji.