Na początku wyjaśnienie do tytułu – nie jest to typowy termometr, gdyż niczego nie mierzy lecz po prostu wyświetla temperaturę pobraną przez inne czujniki. Stwierdziłem jednak, że „wyświetlacz temperatury” brzmi dziwnie. Za to „do sypialni” ma swoje uzasadnienie, o czym napiszę dalej.
Trochę historii
Wskazania temperatury zewnętrznej w sypialni mają swój sens – wszak to tam podejmujemy decyzję jak się ubrać. Początkowo temperaturę wyświetlał stary tablet Lenovo – dzięki przeglądarce Chrome i możliwości wyświetlania na całym ekranie wyglądało to całkiem przyzwoicie. Problemem była jasność świecenia – w nocy w sypialni ma być ciemno. Przeglądarka nie ma możliwości sterowania podświetleniem. Częściowo rozwiązałem problem nakładając półprzeźroczysty „div” na podstawie danych zegara astronomicznego. Działało to nawet całkiem dobrze, ale ikonki Wi-Fi czy zasilania i tak mocno świeciły. Wystarczyło jednak odwrócić ekran, tak aby z pozycji poduszki nie było go widać i było OK. Pewnego razu jednak zauważyłem, że wyświetlacz się wybrzuszył, a po pewnym czasie, gdy wybrzuszenie wzrosło, wyświetlanie zaczęło szwankować. Czytałem o puchnących bateriach przy stałym zasilaniu, lecz myślałem, że nie dotknie to Lenovo. Powstał problem – pozyskać nowy tablet, czy zrobić to „po swojemu”. Kiedyś z myślą o własnym wyświetlaczu temperatury kupiłem moduł TFT 480x320px. W zasadzie zależało mi na dużym wyświetlaczu, a nie na wysokiej rozdzielczości, ale wówczas nic ciekawszego niż ten 4” wyświetlacz nie znalazłem. Postanowiłem zatem wybudować własną konstrukcję opartą o ESP8266.
Budowa ramki
Podstawowy problem przy budowie urządzenia „na widoku” jest oczywiście obudowa. Postanowiłem, że całość zrobię w formie ramki na zdjęcia. Na komodzie, gdzie stoi „termometr” są też inne ramki z prawdziwymi zdjęciami – stwierdziłem, że wszystko będzie się ładnie komponować:
Był to mój pierwszy projekt z wyświetlaczem TFT – dlatego najpierw przeprowadziłem testy:
Zwykle układy buduję na płytce uniwersalnej, ale miałem gotową płytkę pod ESP-12 dla całkiem innego projektu (znany problem – trzeba zamówić kilka sztuk) – postanowiłem zrobić „recykling”. Nie będę kreślił schematu, gdyż po prostu odpowiednie piny ESP (interfejs SPI) są podłączone do wyświetlacza. Dodatkowe piny to:
Kod: C / C++
oraz GPIO15 do sterowania podświetlaniem TFT. Wybór GPIO15 nie był przypadkowy. Podczas startu ten pin ma wymuszony stan niski (wymaga tego ESP8266). Powoduje to, że przez cały czas startu ESP ekran nie jest podświetlany i dopiero gdy wszystko jest gotowe to podświetlenie jest załączane.
Jak już wspominałem istotne było ściemnianie, dlatego ramka została wyposażona w fotorezystor:
Przydało się jedyne wejście ADC procesora ESP8266. Może dziwić wysoka rezystancja R4. Wynika ona z tego, że układ miał mieć dobrą rozdzielczość przy bardzo małym oświetleniu.
Konstrukcja
Po zakupie ramki i oderwaniu tylnej stopki wyciąłem otwór na wyświetlacz:
Precyzja cięcia nie jest specjalnie istotna – z przodu i tak będzie passe partout, który zamaskuje wszystko. Ważne jest jednak umieszczenie otworu w pionie – część aktywna wyświetlacza nie jest w jego środku, co należy uwzględnić przy wycinaniu otworu.
Po zamontowaniu wyświetlacza z przodu wygląda to tak:
Śruby są stożkowe i mają swoje gniazda, tak aby z przodu powstała jedna równa płaszczyzna. Ponieważ płyta jest cienka, dodałem trochę kleju „kropelka” pod łebki śrub dla wzmocnienia całości. Widok z boku:
Grubość płyty i nakrętki zgadzała się idealnie z grubością wyświetlacza.
A tak wygląda całość po zmontowaniu:
Górne śruby z płytki nie są przymocowane do wyświetlacza – pełnią wyłącznie rolę dystansów.
Widok gotowej ramki z tyłu:
Ponieważ nie wykorzystuję panelu dotykowego, w ramce pozostawiłem oryginalne plexi.
Oprogramowanie
Programowanie ESP wykonałem jak zwykle w Arduino. Do obsługi wyświetlacza postanowiłem użyć biblioteki TFT_eSPI, która bardzo dobrze współpracuje z moim wyświetlaczem. Autorzy biblioteki w ciekawy sposób rozwiązali problem konfiguracji pinów sterujących oraz typu wyświetlacza – wszystko jest w pliku „User_Setup.h”. To rozwiązanie ma tę zaletę, że po jednorazowej konfiguracji można kompilować przykładowe projekty, które od razu działają! Na „pierwszy ogień” poszedł przykład z wyświetlaniem obrazka JPG – działało bardzo dobrze, a ja przekonałem się, że mam dobrze podłączony i sprawny wyświetlacz. Kolejny krok to wyświetlanie napisów – tu też są dostępne przykłady. Postanowiłem je trochę zmodyfikować i sprawdzić, co z polskimi znakami. Niestety ich nie było. Później czytałem, że można to zrobić, ale proste to nie jest. Trochę to ostudziło mój zapał, tym bardziej, że chciałem używać ładnych, dużych znaków.
Postanowiłem rozwiązać problem inaczej – zdecydowałem, że ramka będzie wyświetlać tylko cały obraz, który powstanie po stronie serwera przy użyciu PHP i biblioteki GD. Biblioteka GD daje mi dostęp do pisania z użyciem TrueType, a ponieważ PHP to język interpretowany, bardzo łatwo o modyfikację – nie muszę nic kompilować, wgrywać itd.
Pozostał problem jak przesłać obraz z PHP do ESP. Kompresję JPEG odrzuciłem – jest to kompresja stratna, a ja nie chciałem mieć rozmazanego obrazu na krawędziach. Moduł do kompresji PNG nie działał (prawdopodobnie wymaga większej ilości pamięci RAM). Myślałem jeszcze o GIF, ale ostatecznie zdecydowałem się na własne rozwiązanie z własną kompresją.
Postanowiłem, że PHP przygotuje od razu obraz do wyświetlenia, czyli zakoduje go do 65k kolorów (RGB 565) czego wymaga wyświetlacz TFT. Początkowo dane były wysyłane bez kompresji – każdy wiersz składał się z 320 pikseli czyli 640 bajtów. Całość obrazu miała więc rozmiar 307200 bajtów. Działało to bardzo ładnie i ciekawie, ale wolno. Przekonałem się, że Wi-Fi w ESP8266 jest bardzo wolne. Przerysowanie zajmowało ponad 2 sekundy. Ponieważ można je wykonać bez wymazywania poprzedniej treści powstawał ciekawy efekt przejścia typu „żaluzja”, co może być przydatne, gdy ktoś chce zrobić elektroniczną ramkę na zdjęcia.
Mnie jednak zależało na prędkości, dlatego dodałem kompresję opartą o RLE. Poniżej opis zastosowanej metody.
Kompresja
Ponieważ jeden piksel to 2 bajty postanowiłem wszystko kodować na dwóch bajtach – w dalszym opisie będę to nazywał „słowem”, które może zawierać liczby lub kolor RGB (w układzie 565). Podstawowym założeniem był łatwy odczyt po stronie ESP. Dlatego pierwsze słowo zawiera liczbę słów w wierszu. Kolejne słowo jest słowem sterującym (nazwijmy go n) – jeśli jest mniejsze od 10000 to oznacza, że należy następnych n słów przepisać jako piksele. Jeśli n jest większe od 10000, to następne słowo (piksel) należy powielić (n-10000) razy. Takie kodowanie stosujemy do końca wiersza – czyli kolejne słowo sterujące i dane itd. Po zakodowaniu wiersza kod PHP sprawdza, czy aby zakodowany ciąg (wiersz pikseli) nie jest dłuższy niż bez kompresji. W takim przypadku kompresja jest anulowana dla tego wiersza, a ESP gdy odczyta, że wiersz ma 320 słów, wie iż nie jest on skompresowany. Dla poniższego obrazu:
Kompresja daje rozmiar wynikowy 43160 bajtów, co stanowi 14% oryginału. Uznałem to za bardzo przyzwoity wynik.
Kod Arduino
Kod: C / C++
Cały kod to mniej niż 200 wierszy. Oprócz wspomnianej biblioteki TFT_eSPI używam jeszcze Wi-FiManager do konfiguracji sieci WiFi oraz ESP8266httpUpdate do aktualizacji OTA. Aktualizację OTA stosuję od pewnego czasu i muszę przyznać, że to bardzo dobre rozwiązanie. W Arduino zaktualizowałem bibliotekę ESP8266 do 3.x. Niestety kod do obsługi OTA przestał działać (problem z kompilacją). Nie chciało mi się szukać rozwiązania problemu, więc wróciłem do starszej wersji biblioteki (2.7.4). Po pozbyciu się OTA (lub naprawie mojego kodu) prawdopodobnie będzie wszystko działać z biblioteką 3.x.
Działanie programu jest proste – główna pętla wykonuje się co 2s i w tym interwale wykonywany jest pomiar oświetlenia. Co 30 cykli (czyli co 1 minutę) kierowane jest zapytanie do serwera o nowy obraz do wyświetlenia. W nagłówku odpowiedzi są wpisy typu „X-”, które definiują komendę oraz ustawienie PWM podświetlania. Zdecydowałem, że ramka tylko wysyła wynik pomiaru oświetlenia, a skrypt PHP będzie określał jasność. Cykl odpytywania co jedną minutę może być skrócony, jeśli w ciągu 2s nastąpi zmiana jasności o 100. Ramka reaguje więc szybko na zapalenie/zgaszenie światła w sypialni.
Kod PHP
Kod: PHP
Przedstawiony kod nie jest kodem, który u mnie działa, gdyż skrypt PHP pobiera dane z różnych miejsc i składa je w jeden obraz. Pokazuje jednak jak coś napisać z użyciem TrueType, włożyć obrazek i skompresować całość opisanym wcześniej algorytmem. Kod PHP przyjmuje dodatkowy atrybut w postaci „output=png” do zastosowania w przeglądarce WWW np.:
http://192.168.0.24/term/term.php?output=png
który powoduje, że obraz będzie zwracany jako plik PNG – jest to idealne do testów, gdyż nie trzeba patrzeć na naszą ramkę, a wynik widać w przeglądarce.
Podsumowanie
Myślę, że zaproponowane rozwiązanie może być przydatne w wielu przypadkach np. do tworzenia skomplikowanych grafik, ciekawych tekstów o nietypowym foncie. Jeśli ktoś będzie chciał zrobić w oparciu o to rozwiązanie zegar, ale bez wyświetlania sekund, to warto w odpowiedzi w nagłówku dodać kolejny wpis „X-”, który poda liczbę sekund do kolejnej zmiany minuty. Można wówczas zsynchronizować czas zapytania o obraz ze zmianą minuty. Można też zbudować elektroniczną ramkę na zdjęcia, w której obrazy będą pobierane z sieci – ciekawy prezent np. dla rodziców. Mankamentem w tym przypadku jest niestety mały rozmiar wyświetlacza.
Poniżej do pobrania przykładowy kod PHP wraz z czcionką oraz obrazkiem:
Fajne? Ranking DIY