V našem seriálu o programování elektroniky si posledních pár týdnů hrajeme s automatizovaným zavlažovacím systémem na baterii pro náš redakční rýmovník.
Skládá se z kapacitního čidla půdní vlhkosti, maličkého čerpadla, které dle potřeby nažene do květináče vodu z nádržky, a z řídící desky, kterou pohání drobný jednočlánkový lithiový akumulátor a dobíjecí 5V solární panel.
Připomeňte si všechny díly série:
- V první části jsme postavili surový prototyp s lithiovou baterií
- V druhé části jsme si ukázali, jak kreslit grafy rýmovníku na službě TMEP
- V třetí části jsme do nádržky s vodou přimontovali laserový dálkoměr
V dalším pokračování si ukážeme, jak k prototypu připojit extrémně úsporný prototypovací modul displeje s elektronickým inkoustem a jak na něm zobrazit základní údaje o stavu rýmovníku.
Podívejte se na video, jak jsme dnes vylepšili rýmovník:
Buňky plné barevných částic
E-inkové displeje používají ke změně pixelů na obrazovce techniku tzv. elektroforézy, která, jak praví Wikipedie, využívá k dělení látek jejich odlišnou pohyblivost ve stejnosměrném elektrickém poli.
Základní princip přeskupení částeček v buňkách pixelů e-inkového displeje
Jednoduše řečeno, pixelové buňky jsou naplněné drobnými částečkami s různou barvou, které se působením elektrického pole přesunou do popředí, nebo naopak do pozadí. E-inkové displeje proto spalují elektřinu prakticky jen při překreslení.
Jakmile drobné částečky zobrazí to, co potřebujeme, displej klidně můžeme odpojit od napájení, schovat někam do skříně, a když jej po letech vytáhneme, bude ukazovat stále to samé.
E-ink není vhodný pro rychlé animace
Na stranu druhou, jelikož e-ink pracuje na elektromechanickém principu, trpí velmi nízkou rychlostí. Přeskupení částeček po celé ploše chvíli trvá, a proto se drtivá většina laciných modulů nehodí pro zobrazování animací. Však to sami znáte třeba z elektronických čteček knih.
Povrch dvoubarevného e-inkového displeje pod mikroskopem a jeho zadní strana, na kterou se přeskupily částečky opačné barvy, takže vidíme negativ v zajímavé mřížkové konfiguraci
Na stranu druhou, pokud se má displej obnovovat třeba jen jednou za čas, nic lepšího na trhu nenajdete. A to je i případ našeho zavlažovacího systému, který běží na baterii, a proto jeho řídící čip po většinu času spí v hlubokém spánku s minimálním odběrem elektrického proudu.
0,00027 fps
Vzbudí se jen jednou za hodinu, pomocí kapacitního čidla zapíchnutého v květináči změří půdní vlhkost a pomocí laserového dálkoměru v nádržce na vodu také výšku hladiny. Pokud vlhkost klesne pod 60 % a v nádrži bude dostatek vody, řídící mikrokontroler na pět sekund spustí čerpadlo, které vžene do květináče doušek čerstvé vody.
Na závěr se čip připojí k redakční Wi-Fi, odešle změřené údaje na internet, aktualizuje e-inkový displej a přepne se zpět do hlubokého spánku.
Suma sumárum, náš e-inkový displej pracuje s obnovovací frekvencí zhruba 0,00027 fps.
Monochromatický 2,9" e-ink za pár stovek
Na zahraničních i českých e-shopech seženete celý zástup jak surových displejů, které ovšem budou vyžadovat ještě napájecí obvod, tak i hotových a dražších modulů, které rovnou připojíte k Arduinu, Raspberry Pi nebo k čemukoliv jinému.
Monochromatický 2,9" eink a sedmibarevný 4" eink v prototypovacím provedení od asijského výrobce Waveshare
Tyto displeje zpravidla komunikují skrze sběrnici SPI doplněnou hromadou vlastních řídících signálů a k dispozici je hned několik knihoven pro Arduino, které vše usnadní.
K nám do redakce nakonec zamířily dva exempláře od Wavesharu:
Odkazy výše sice vedou na originální asijský e-shop Wavesharu, nicméně oba displeje samozřejmě pořídíte i v tuzemských obchodech pro kutily. Ještě jednou, tím výčet e-inkových prototypovacích modulů rozhodně nekončí a jen Waveshare jich vyrábí desítky ve všech velikostech a cenových hladinách.
E-ink bude kreslit knihovna GxEPD pro Arduino
V naší instalaci jsme nakonec použili cenově dostupnější a menší 2,8“ displej (ten větší si ukážeme příště), který oživíme pomocí knihovny GxEPD pro Arduino od Jeana-Marca Zingga. Umí kreslit všechny základní vektorové tvary, bitmapy a podporuje i práci s rastrovými fonty formátu Adafruit GFX, na které je založená.
O vykreslení základních tvarů, textu a bitmap se nám postará knihovna GxEPD
K dispozici jsou nicméně i ukázkové kódy přímo od Wavesharu, který na GitHub vystavil příklady pro všechny své displeje.
Připojení 2,9" e-inku k desce ESP32-LPKit
Náš systém je založený na české prototypovací desce ESP32-LPKit s Wi-Fi mikrokontrolerem ESP32. Ve srovnání s cetkami z AliExpressu je sice o něco dražší, nabízí ale velmi nízkou spotřebu v hlubokém spánku v řádu jednotek mikroampérů a nabíjecí obvod pro jednočlánkový lithiový akumulátor (4,2 V).
Do konektoru JST připojíme akumulátor a do USB malý solární panel s 5V regulovaným výstupem. O vše ostatní se už postarají obvody na desce.
Schéma připojení e-inkového modulu a desky ESP32-LPKit
Jak už jsme si řekli výše, e-inkové moduly od Wavesharu zpravidla komunikují skrze sériovou sběrnici SPI, přičemž vyžadují ještě několik dalších pomocných signálů. Připojení k desce ESP32-LPKit proto bude vypadat jako na obrázku výše.
Grafické rozhraní
Náš displej bude zobrazovat toto grafické prostředí:
Toto se bude zobrazovat na skutečném displeji
Všimněte si hrubé grafiky bez jakéhokoliv vyhlazení, displej samotný má totiž k dispozici pouze dvě barvy: světlou a tmavou. Displej má zároveň nízké rozlišení/DPI, abychom vyhlazení a odstíny šedi simulovali třeba pomocí dittheringu.
Grafické rozhraní můžeme rozdělit na tři části:
- Základní tvary dělících linek a černého obdélníku patičky
- Texty
- Bitmapy
Adafruit GFX
Všechny tyto operace displej provádí pomocí abstraktní knihovny Adafruit GFX, kterou známe i z práce s jinými displeji. Vše se vlastně liší jen v tom, že v případě dvoubarevného 2,9" displeje od Wavesharu máme k dispozici jen dvě barvy GxEPD_BLACK a GxEPD_WHITE.
Takže primitivní černý obdélník, který jako proužek vyplňuje patičku displeje, jsme vytvořili příkazem:
display.fillRect(0, 98, 296, 30, GxEPD_BLACK);
Přičemž objekt display je instance třídy GxEPD_Class, kterou jsme si vytvořili na začátku našeho programu (viz kód v závěru článku).
Bitmapy
Naše grafické rozhraní vykresluje na plátno také tři bitmapy s ikonami květináče, baterie a vodoměru. Knihovna samozřejmě neumí dekódovat obvyklé formáty jako JPEG, PNG nebo BMP, bitmapou totiž máme na mysli opravdu jen pole bajtů, které představují barvy jednotlivých černých a bílých pixelů s 1bit kódováním (1B = 8 po sobě jdoucích pixelů).
C/C++ pole za nás vygeneruje letitý, ale stále funkční webový generátor Image2cpp na GitHubu. Stačí nahrát černobílý obrázek v některém z obvyklých formátů, ponechat ostatní volby ve výchozím stavu a pouze v závěru v sekci Output vybrat Arduino code, single bitmap.
Vyhledání ikony na flaticon.com, transformace do C/C++ pole v Image2cpp a výsledek v hlavičkovém souboru ikony.h našeho projektu pro Arduino
Po vygenerování získáme pole, které jen podle svého gusta přejmenujeme a zkopírujeme do nového hlavičkového souboru našeho projektu třeba s názvem ikony.h. Na začátek ještě odkážeme na hlavičkový soubor pgmspace.h:
#include <pgmspace.h>
Který dá překladači vědět, že tato rozměrná data označená klíčovým slovem PROGMEM nemá program nahrávat do maličké RAM, ale načítat je přímo z flashové paměti (program memory).
V hlavním souboru našeho programu po odkázaní na hlavičkový soubor s ikonami pak můžeme bitmapu vykreslit pomocí metody drawBitmap:
display.drawBitmap(ico_kvetinac, 0, 16, 64, 64, GxEPD_BLACK, 1);
Příkaz výše projde C/C++ pole pixelů ico_kvetinac, a vykreslí jej na souřadnice 0;16 (X ;Y). Ještě mu musíme sdělit rozměry bitmapy, tedy 64×64 pixelů, a barvu GxEPD_BLACK, kterou má kreslit.
Písma
Velmi podobným způsobem jako s bitmapami můžeme pracovat i s různými rastrovými písmy ve formátu Adafruit GFX. Písmem není ve své podstatě vlastně není nic jiného než pole podobných bitmap vždy pro každý znak abecedy.
Stažení vhodného TTF písma ze služby Google Fonts, vygenerování rastrového řezu pro konkrétní velikost v nástroji fontconvert a hotový hlavičkový soubor v Arduinu
K dispozici je několik předpřipravených řezů v různých velikostech, Adafruit nicméně nabízí i vlastní textový linuxový konvertor fontconvert z obvyklého formátu TrueType, který jsem použil i já. Návod, jak jej přeložit ze zdrojových kódů a jak se používá, najdete v nápovědě knihovny Adafruit GFX.
Příkaz v vykreslení textu „96“ vlastním rastrovým písmem na displej pak může vypadat analogicky takto:
display.setFont(&bebas37pt7b);
display.setTextColor(GxEPD_BLACK);
display.setCursor(62, 75);
display.print("96");
Inicializace displeje
Už umíme vykreslovat primitivní tvary, bitmapy i text, takže nám chybí jen samotné spojení s displejem, následná změna dění na obrazovce a závěrečné přepnutí do úsporného režimu.
Nejprve v hlavním zdrojovém souboru našeho programu odkážeme na konkrétní hlavičkové soubory pro náš 2,9" displej (GxGDEH029A1) a knihovny GxEPD:
#include <GxEPD.h>
#include <GxGDEH029A1/GxGDEH029A1.h>
#include <GxIO/GxIO_SPI/GxIO_SPI.h>
#include <GxIO/GxIO.h>
Poté si vytvoříme instance dvou tříd. Ta první se stará o spojení s displejem skrze sběrnici SPI a pomocných signálů (viz schéma zapojení displeje výše), ta druhá pak o samotné kreslení:
GxIO_Class io(SPI, 5, 17, 16);
GxEPD_Class display(io, 16, 4);
Čísla představují konkrétní vodiče
- BUSY: GPIO4
- SPI CS/SS: GPIO5
- RST: GPIO16
- DC: GPIO17
Knihovna dále předpokládá výchozí zapojení zbývajících vodičů sběrnice SPI, tedy:
- Takt SPI SCK: GPIO18
- Zápis SPI MOSI: GPIO23
SPI MISO (čtení) nepoužíváme, protože do displeje pouze zapisujeme.
Máme vytvořenou instanci displeje, takže jej zkusíme nastartovat:
display.init(115200);
Parametrem je rychlost sériové linky (115 200 b/s), do které může knihovna vypisovat případné chybové hlášky, pokud by se to nepodařilo.
Výchozí orientace displeje je na výšku, takže si ji upravíme po 90° krocích (0-3) do libovolné polohy, jak se nám to hodí. Třeba:
display.setRotation(3);
A vymažeme plátno tím, že jej celé překreslíme pseudobílou barvou:
display.fillScreen(GxEPD_WHITE);
Proč pseudobílou? Skutečná barva odpovídá odstínu částeček v buňkách pixelů, což nemusí být vždy dokonalá bílá, ale spíše našedlá, nažloutlá atp.
V dalším kroku můžeme pomocí metod, které jsme si ukázali výše, displej pokreslit, čím zrovna potřebujeme.
Vše završíme skutečnou aktualizací displeje, protože všechny dosavadní úpravy jsme prováděli jen v mezipaměti:
display.update();
Displej, který nic nežere
Až budeme mít hotovo, můžeme displej vypnout pro co nejnižší odběr elektrické energie v době nečinnosti:
display.powerDown();
I když tedy modul zůstane i nadále pod napětím, jeho elektrické obvody by měly odebírat opravdu naprosto zanedbatelné množství šťávy z baterie. Kdybychom celý modul nyní odpojili od řídící desky, vykreslený obraz na něm zůstane klidně i celé roky.
Jak už jsme si totiž řekli výše, e-ink je vlastně elektromechanický typ displeje a instrukcemi jsme nerozsvěcovali nějaké LCD/OLED subpixely jako na běžných displejích, ale opravdu mechanicky přeskupovali mikroskopické částečky elektroinkoustu. Elektroinkoustu, jehož pozice se pochopitelně nezmění ani po úplném odpojení zdroje elektřiny.