Programování | Pojďme programovat elektroniku | E-ink

Pojďme programovat elektroniku: Vyzkoušíme elektronický papír, který proslavil čtečku Kindle

  • E-inkové displeje mají jednu ohromnou výhodu
  • Spalují energii jen při překreslení
  • Dnes si to vyzkoušíme s Wi-Fi čipem ESP32

V létě jsme si v našem seriálu Pojďme programovat elektroniku vyzkoušeli základní práci s barevným TFT LCD displejem. Podobná obrazovka poslouží jako skvělý zobrazovač třeba pro údaje z meteostanice i jinou složitější grafiku včetně bitmap ovšem za cenu vysoké spotřeby, protože o pořádný díl energie si řekne především podsvícení displeje.

Jmenuji se elektroforéza a funguje díky mně elektronický papír

Dnes se proto podíváme na displej, který pro zobrazení pixelů nepoužívá technologii LCD, ale elektroforézu – separační techniku, která, jak praví Wikipedie, využívá k dělení látek jejich odlišnou pohyblivost ve stejnosměrném elektrickém poli.

Právě na tom je totiž založený princip fungování elektronického papíru, e-inku, díky kterému se sice před lety mohly masově rozšířit elektronické čtečky knížek, ale více se zatím bohužel příliš neprosadil.

9261e745-6d07-44ae-bc1e-ff33e4d6f098
E-ink tvoří buňky, uvnitř kterých jsou droboučké vodivé částice. Změnou elektrického pole se do popředí dostanu buď tmavé, anebo světlé částice. Grafika: Senarclens, CC BY-SA 3.0

Možná však e-ink zářná budoucnost teprve čeká, všemožné krabičky internetu věcí poháněné malou baterií totiž budou potřebovat velmi úsporný displej. Jistě, máme tu OLED, který ve spotřebě strčí TFT LCD hravě do kapsy, ovšem e-ink je na mnohem drastičtější dietě.

Za vše může ona elektroforéza a konstrukce elektronického papíru, v rámci které tvoří jednotlivé pixely speciální buňky naplněné vodivými světlými a tmavými částicemi. Změnou elektrického náboje se pak do popředí přesunou buď bílé, anebo naopak černé částice a buňka – pixel, se bude jevit jako světlá, anebo tmavá. Pokud buňky ještě zmenšíte a položíte nad ně barevné filtry, mohou fungovat jako subpixely třeba pro model RGB.

Podstatné je to, že displej složený z podobných částic odebírá proud v podstatě jen při kreslení, kdy se musejí přeskupit částice v jednotlivých kapsulích. Jakmile budou mít hotovo, můžete klidně displej odpojit od napájení a obraz nezmizí. Teprve s velkým odstupem času by mohlo dojít k opětovnému promíchání některých černých a bílých „míčků“ a postupnému zhroucení obrazu. Ale to je spíše teorie, když si totiž modul podobného displeje objednáte třeba z eBaye, dorazí vám zpravidla s nějakou kresbou od výroby, kterou na něj kdosi nahrál třeba i před dlouhými měsíci.

2,9" e-ink za čtyři stovky

Moduly podobných displejů, pokud mají mít nějaké použitelné rozlišení a velikost, jsou o něco dražší než ty obvyklé, které jsme si zvykli objednávat z čínských e-shopů za pár dolarů. Aktuálně se těší velké popularitě zejména displeje Waveshare s rozhraním SPI, jejichž cena začíná po přepočtu zhruba na 400 korunách. Já si pro dnešní článek objednal 2,9“ širokoúhlý model s rozlišením 296 × 128 pixelů a rozměry samotné obrazovky 66,89 mm × 29,05 mm.

 
b6ca6391-fc4e-4955-8f2e-a1abe7bd24d297a24af4-14dd-4d4e-b521-16d7bfbb9616ff50ce53-2ba9-4cfe-9840-464d008f594f
E-inkový displej od Wavesharu. Zpravidla dorazí i s podobným zobrazenou grafikou. I bez napájení tedy displej udrží data je to tedy opravdu elektronický papír.

Nezkušený začátečník může mít na začátku docela velký problém. Waveshare sice zaslouží pochvalu, protože k hromadě svých produktů nabízí podrobný wiki web s příklady jak pro Arduino, tak třeba Raspberry Pi, ovšem když nahlédnete do zdrojových kódů právě pro Arduino, zděsíte se neskutečně odfláknuté knihovny, která nic neumí a nejspíše ani nebude pořádně fungovat.

Programuje se snadno díky knihovnám GxEPD a Adafruit GFX

Naštěstí tu ale máme dostatečně altruistickou komunitu a GitHub, na kterém najdete skvělou knihovnu GxEPD jak pro modely e-inkových displejů od Wavesharu, tak i některé další. Nejdůležitější je však to, že autor použil jako základ dnes již univerzální knihovnu Adafruit GFX, takže i na e-inku můžete kreslit všechny základní tvary, bitmapy a rastrová písma převedené do formátu Adafruit.

GxEPD má sice mnohé rutiny trošku upravené, protože pochopitelně nekreslí obrázky na barevný displej, ale pouze na černobílý, nicméně se do toho brzy každý dostane a migrace kreslícího kódu je tak velmi snadná.

E-ink + Wi-Fi čip ESP32 = VSL

Pojďme si to vyzkoušet v praxi: postavíme si e-inkovou internetovou meteostanici. Připojil jsem 2,9“ e-inkový displej k prototypovací desce s Wi-Fi mikrokontrolerem ESP32 od Espressifu. Deska má zároveň nabíjecí obvod a na spodní straně pouzdro na jeden Li-ion článek 18650, čili má vlastní zdroj napájení.

29693008-df8e-40d6-a2a3-7ca180ca2a1d8e0c4213-462b-481d-a1e4-f16b9a6aa79c855f36d0-5f39-4728-a3f5-608d8c2bda01
Prototypovací deska s Wi-Fi čipem ESP32 (nástupce populárních čipů ESP8266), nabíjecím obvodem a pouzdrem po Li-ion článek 18650

Abych byl konkrétní, jedná se o tento model za dvě stovky z Banggoodu, i když nejde o originální Wemos, ale o jeden z jeho mnoha klonů. Podstatné je to, že to funguje a po doinstalování podpory ESP32 do prostředí Arduina a výběru desky WEMOS LOLIN32 můžete čip bez problému programovat. Škoda jen, že nelze na některém dedikovaném pinu přečíst napětí v baterii a sledovat tak její stav.

82a53928-2b56-4c09-bec0-dc5145e18d51
Celý dnešní experimentální obvod

Mě zajímá především odběr proudu, chci vám totiž demonstrovat, jak je obvod s e-inkovým displejem úsporný, a tak jsem do hry zapojil ještě staré Arduino Uno a hlavně modul multimetru INA219. Můžete s ním komunikovat skrze rozhraní I2C a vytáhnete z něj jak napětí v baterii, tak odebíraný proud. V podstatě se tedy jedná o kompletní multimetr. Cena na eBayi? Začíná kdesi na čtyřiceti korunách.

Wi-Fi čip nejprve stáhne z webu data ve formátu JSON

Tak a teď už si konečně pojďme popsat, co bude náš obvod vlastně dělat. ESP32 se nejprve přihlásí k Wi-Fi. Poté se skrze HTTP GET spojí s webovým serverem, od kterého získá data ve formátu JSON. Bude v nich uložená aktuální teplota a vlhkost vzduchu, atmosférický tlak, intenzita slunečního svitu v luxech a nakonec číselný údaj udávající typ počasí (třeba déšť, zataženo, polojasno, jasno atp.).

Z webu stáhnu data ve formátu JSON:

{
  "teplotaDoma": 20.14,
  "teplotaVenku": 9.41,
  "vlhkostDoma": 0.51,
  "vlhkostVenku": 0.99,
  "pocasi": 0,
  "slunce": 1458,
  "tlak": 997.54
}

Zdrojem těchto dat by mohlo být ledacos. Ať už nějaká veřejná webová služba, anebo vlastní meteostanice. Ostatně už jsme si ji v našem seriálu stavěli několikrát: jednou na Wi-Fi čipu ESP8266 a podruhé pomocí radiového vysílače Sigfox.

Nám dnes jde ale opravdu jen o ten displej, a tak samotné měření hodnot nebudeme vůbec řešit. Prostě od webového serveru dostaneme JSON a basta.

JSON rozlouskne knihovna ArduinoJson

Rozměrný textový řetězec JSON by mohl být na drobných arduinech s 2kB RAM smrtící, Wi-Fi čipy od Espressifu však mají k dispozici přinejmenším desítky kB RAM, a tak si to můžeme dovolit. Ostatně i z toho důvodu, jak se bude náš program vlastně chovat.

Arduino samozřejmě nemá žádnou vestavěnou knihovnu pro zpracování JSON, jednu skvělou, jmenuje se přirozeně ArduinoJson, nicméně najdete na GitHubu a autorovi je třeba poděkovat za to, že je maximálně úsporná.

Dekódování textového řetězce JSON pomocí knihovny ArduinoJson:

char* txtJson = "{\"teplotaDoma\": 20.14,\"teplotaVenku\": 9.41,\"vlhkostDoma\": 0.51,\"vlhkostVenku\": 0.99,\"pocasi\": 0,\"slunce\": 1458,\"tlak\": 997.54}";

StaticJsonBuffer<1000> jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(txtJson);

if (!json.success()) {
  Serial.println("Nepodarilo se dekodovat JSON!");
}
else {
  float teplotaDoma = json["teplotaDoma"].as<float>();
  float teplotaVenku = json["teplotaVenku"].as<float>();
  float vlhkostDoma = json["vlhkostDoma"].as<float>();
  float vlhkostVenku = json["vlhkostVenku"].as<float>();
  float tlak = json["tlak"].as<float>();
  uint16_t luxmetr = json["slunce"].as<uint16_t>();
  uint8_t pocasi = json["pocasi"].as<uint8_t>();
}

Příprava rastrových fontů

Jakmile dekódujeme z textových řetězců meteorologické údaje a převedeme je do odpovídajících proměnných, konečně vše zobrazíme na displej. Použijeme k tomu rastrové fonty pro knihovnu Adafruit GFX, přičemž bychom mohli sáhnout po několika hotových, které jsou její součástí.

606600697
Převod písma pro knihovnu Adafruit GFX pomocí webového formuláře Font Converter

Rastrový font není vlastně nic jiného než pole pixelů pro jednotlivá písmena v pevně dané velikosti a na webu najdete hromadu nástrojů, které tuto konverzi provedou, případně již převedené fonty. Já použiji webový formulář Font Converter, který nabízí transformaci několika fontů v různé velikosti a řezu. Ve formuláři stačí zvolit správný výstupní formát Adafruit GFX Font a vygenerovaný kód uložit v editoru Arduina jako nový hlavičkový soubor (*.h).

Nakreslíme na displej text

No, a pak už je to jednoduché. Po nastartování displeje mohu nastavit jeho orientaci (ve výchozím stavu by se vše vykreslovalo ve sloupci na výšku), napsat libovolné ASCII znaky (pochopitelně je musí rastrový font podporovat) a dát displeji pokyn, ať vše vykreslí.

Psaní textu na displej pomocí knihovny GxEPD:

/*
  Displej je pripojeny skrze rozhrani SPI
  Na desce Wemos LOLIN32 takto:
  BUSY -> 4, RST -> 16, DC -> 17, CS -> 5, CLK -> 18, DIN -> 23
*/

GxIO_Class io(SPI, SS, 17, 16);
GxEPD_Class displej(io, 16, 4);

displej.init();
displej.setRotation(1);

displej.setTextColor(GxEPD_BLACK);
displej.setFont(&Lato_Heavy_35);
displej.setCursor(0, 40);
displej.print(„AHOOOOJ“);

displej.update();

Kód výše vypíše text „AHOOOOJ“ rastrovým fontem Lato_Heavy_35 a v černé barvě na pozici 0×40, přičemž displej bude mít orientaci na šířku.

Jen připomenu, že při používání vlastních rastrových písem začíná osa Y při patě znaku. Proto jsem nastavil kurzor na 0×40 a nikoliv 0×0, protože by byl text skrytý mimo displej.

A teď nakreslíme na displej obrázky

Podobným způsobem mohu na displej vykreslit i jednoduchou bitmapu, ačkoliv přítomnost pouze dvou kontrastních barev bílá × černá je dost omezující. Ostatně to platí i o rastrových fontech, kterým chybí více odstínů šedi a tedy adekvátní vyhlazení.

79dd6625-d24f-475b-984c-4710f4d98d25
Náš e-ink zobrazí pouze černou a bílou, takže přijdeme o vyhlazení. Proto na něm lépe vypadají pravoúhlé tvary.

Myslete na to, zdánlivě hezká zmenšená ikonka třeba o velikosti 32×32 totiž na displeji nemusí vypadat tak, jak jste zamýšleli. Knihovna zároveň vyžaduje, aby rozměry bitmap odpovídaly násobku 2. V opačném případě obrázek vykreslí špatně. Já použil rozměr 32×32 pixelů pro malé ikony domečku a stromu pro určení domovní a venkovní teploty a rozměr 128×128 pixelů pro velkou ikonu počasí v pravé části displeje.

Fajn, a jak tedy běžný obrázek v JPG, PNG, GIF nebo třeba BMP dostat do kódu našeho programu? Podobným způsobem jako při tvorbě rastrových fontů. I v tomto případě totiž nejde o nic jiného než o pole pixelů. Ty bílé bude knihovna ignorovat a ty černé vykreslí.

926170741
Webový formulář img2cpp převede bitmapu na pole pixelů přímo pro Arduino

K převodu běžného souboru do pole pixelů nám pomůže skvělý webový nástroj image2cpp, do kterého z počítače nahrajete bitmapu a jako výstup zvolíte Arduino code, single bitmap. Kód pak můžete opět vložit třeba do samostatného hlavičkového souboru obrazky.h. Díky makru PROGMEM bude rozměrné pole uloženo ve flashové paměti mikrokontroleru a nespotřebuje tak celou RAM.

Pro lepší představu, takto vypadá pole obrDomecek, ve kterém je uložená ikona domečku o velikosti 32×32 pixelů:

const uint8_t obrDomecek[] PROGMEM = {
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 
  0xff, 0xfc, 0x3f, 0xff, 0xff, 0xf8, 0x1f, 0xff,
  0xff, 0xf0, 0x0f, 0xff, 0xff, 0xe0, 0x07, 0xff, 
  0xff, 0xc0, 0x03, 0xff, 0xff, 0x80, 0x00, 0x1f,
  0xff, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x1f,
  0xfc, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x1f,
  0xf0, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x07,  
  0xc0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x01,
  0x80, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x1f, 
  0xf8, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x1f,
  0xf8, 0x78, 0x1e, 0x1f, 0xf8, 0x30, 0x1e, 0x1f, 
  0xf8, 0x78, 0x1e, 0x1f, 0xf8, 0x00, 0x1e, 0x1f,
  0xf8, 0x00, 0x1e, 0x1f, 0xf8, 0x00, 0x1e, 0x1f, 
  0xf8, 0x00, 0x0e, 0x1f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

Jen co se odkážeme na hlavičkový soubor s obrázky v našem hlavním zdrojovém kódu, můžeme domeček konečně vykreslit na displej:

displej.drawBitmap(obrDomecek, 10, 70, 30, 30, GxEPD_BLACK, 1);

Kód výše vykreslí bitmapu obrDomecek o rozměrech 30×30 na pozici 10×70 a to černou barvou.

Tímto způsobem a s pixelovou přesností zatím jen v paměti stvoříme podobu celého obrazu a nakonec vše konečně necháme zobrazit příkazem:

displej.update();

Který překreslí celou plochu displeje. E-ink je z principu docela pomalý, musejí se totiž přeskupit všechny mikrokapsule, a tak se rozhodně nehodí třeba pro animace.

Tento problém lze nicméně alespoň částečně vyřešit překreslením pouze určitého výřezu. Displej a jeho ovladač to umožňují a knihovna GxEPD na to myslí ve funkci updateWindow. Kdybychom tedy chtěli překreslit jen určitý obdélníkový výřez, stačí zavolat:

displej.updateWindow(x, y, sirka, vyska, 1);

Jednička na konci říká, že má knihovna vzít v potaz nastavenou orientaci displeje.

Díky parciálnímu překreslení se může na displeji třeba každou sekundu aktualizovat oblast s hodinami, zatímco oblasti, které je třeba překreslit jen jednou za deset minut, zůstanou netknuté. Diváka pak nebude obtěžovat žádné rušivé problikávání celého displeje.

Vše je na displeji, nyní může čip usnout

Ale zpět k našemu experimentu. Právě jsme na displej vykreslili všechny hodnoty a ikonu mráčku, protože je zataženo. Jelikož je náš Wi-Fi čip napájený vlastním lithiovým článkem, musíme co nejvíce šetřit energií, a tak nyní můžeme mikrokontroler přepnout do režimu hlubokého spánku.

PA270029.JPGPA270020.JPGPA270025.JPGPA270028.JPG2ea85da8-8c2a-479f-a77d-cbbb646dc055d5a6f16e-3b00-4881-b8a8-570e26d31eec22bb3b52-8a25-4010-a833-a28cacb25861b857f4e9-bd51-4dac-8d72-268018e18c0b
Elektronicky papír a vše, co jsme získali z webu ve formátu JSON. Když teď displej odpojím od prototypovací desky, vše na něm zůstane.

Zatímco čip se téměř celý vypne, divák si ničeho nevšimne, obraz na elektronickém papíře totiž bude dále svítit. Poté, co uplyne předem stanovená doba, časovač provede reset čipu a náš program začne zase od začátku: přihlásí se k Wi-Fi, stáhne data a obnoví displej.

Vůbec tedy nepoužijeme smyčku loop, kterou dnes nebudeme potřebovat.

Na populárních Wi-Fi čipech ESP8266/ESP32 mohu dát povel ke spánku příkazem:

ESP.deepSleep(60e6);

Který jej uspí na 60 sekund (60 × 106 mikrosekund). Čipy ESP8266 zároveň vyžadují propojení pinů RST a WAKE (GPIO16), protože jakmile během spánku dosáhne čítač nastavené hodnoty, změní napětí na pinu WAKE, což způsobí díky spojení s pinem RST nový start programu (reset).

Jelikož v tomto příkladu používám desku s pokročilejším čipem ESP32, pro pořádek zmíním, že už podobné propojení nevyžaduje a resetuje se sám.

Díky e-inku může vše běžet na baterii

Mikrokontroler tedy periodicky usíná a zase se probouzí. Zatímco v bdělém stavu s aktivní Wi-Fi poskočí odběr proudu na cifry okolo 100 mA, během spánku celý obvod s mikrokontrolerem a displejem klesne na minimum.

A protože nejspíše nepotřebujeme, aby se údaje o počasí aktualizovaly opravdu každou minutu, může se čip probouzet třeba jen jednou za deset-patnáct minut. Během té doby se jistě venkovní teplota a charakter počasí nikterak dramaticky nepromění.

636751064
Spotřeba elektrické energie mikrokontroleru a e-inkového displeje během probuzení, stahování dat skrze Wi-Fi a překreslení displeje. Po přechodu do spánku celková spotřeba klesne na minimum.
685796939
A takto by vypadal časový profil spotřeby elektrické energie při periodickém probouzení mikrokontroleru každých 30 sekund. Divák si všimne pouze probliknutí displeje během jeho inicializace.

Absolutní hodnoty berte s určitou rezervou. INA219 má své limity.

Usínání bude mít dramatický dopad na výdrž. Kdyby Byl čip ESP32 neustále vzhůru a připojený k Wi-Fi, s Li-ion článkem o kapacitě 2 500 mAh by dokázal fungovat zhruba celý jeden den. Pokud však bude po většinu času spát a jen se párkrát za hodinu probudí, aby získal hodnoty z webu a překreslil displej, výdrž dramaticky vzroste.

Vyzkoušejte tuto kalkulačku spotřeby a výdrže, kde můžete stanovit času spánku a bdělosti a spotřebu během těchto stavů

Elektronický papír je tedy opravdu skvělý zobrazovač pro bateriový internet věcí a všemožné sondy. Vytknout bych mu mohl snad pouze nízké rozlišení u levných prototypovacích displejů. Nelze než doufat, že mají to nejlepší ještě opravdu před sebou.

Nakonec nesmí chybět komentovaný zdrojový kód

A to je už opravdu vše. Nakonec samozřejmě nesmí chybět zdrojový kód. Tentokrát se omezím pouze na hlavní program. Rastrové fonty a obrázky jsou už přeci jen rozměrnější.

/*
   Knihovna GxEPD pro praci s e-ink displejem
   Vychazi z knihovny Adafruit GFX
   https://github.com/ZinggJM/GxEPD
*/
#include <GxEPD.h>
// Vyber modelu displeje (GDEH029A1 je 2,9" Waveshare)
#include <GxGDEH029A1/GxGDEH029A1.cpp>
#include <GxIO/GxIO_SPI/GxIO_SPI.cpp>
#include <GxIO/GxIO.cpp>

/*
   Bitmapy ikon prevedene do poli pixelu pomoci
   weboveho nastroje image2cpp: http://javl.github.io/image2cpp
   Delka a sirka obrazku musi byt nasobkem 2
*/
#include "obrazky.h"

/* 
   Rastrovy fonty pro knihovnu Adafruit GFX
   Vytvoril jsem je pomoci weboveho nastroje Font Converter:
   http://oleddisplay.squix.ch/
*/
#include "Lato_Heavy_35.h"
#include "Lato_Medium_21.h"

// Knihovny ESP32 pro pripojeni k Wi-Fi a HTTP GET
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>

// Knihovna pro dekodovani JSON
// https://github.com/bblanchon/ArduinoJson
#include <ArduinoJson.h>

/*
  Displej je pripojeny skrze rozhrani SPI
  Na desce Wemos LOLIN32 takto:
  BUSY -> 4, RST -> 16, DC -> 17, CS -> 5, CLK -> 18, DIN -> 23
*/
GxIO_Class io(SPI, SS, 17, 16);
GxEPD_Class displej(io, 16, 4);

// Knihovna pro pripojeni k vhodnemu AP ze seznamu
WiFiMulti wifiMulti;

// Knuihovna pro HTTP klient
HTTPClient http;

// Funkce setup se zpracuje jen jednou po startu mikrokontroleru
void setup() {
  // Nastaveni automatického probuzení čipu ESP32 po 30 sekundach (30 milionu us)
  esp_sleep_enable_timer_wakeup(30e6);
  // Nastartovani seriove linky
  Serial.begin(115200);
  // Nastartovani displeje
  displej.init();
  // Nastaveni orientace displeje na sirku
  // Po smeru hodinovych rucicek (0 = na vysku, 1 = na sirku atd.)
  displej.setRotation(1);

  Serial.print("Prihlasuji se k Wi-Fi ");
  WiFi.mode(WIFI_STA);
  /*
     Nadefinoval jsem vice Wi-Fi siti a ESP32 se prihlasi k te dostupne.
     To se hodi pri prenaseni krabicky bez potreby nove konfigurace.
  */
  wifiMulti.addAP("Klobouk", "*******");
  wifiMulti.addAP("Kloboukovo", "*******");

  /* Pokus o prihlaseni k Wi-Fi. Pokud se nezadari, cip
     10 sekund pocka a restartuje se.
  */
  if (wifiMulti.run() != WL_CONNECTED) {
    Serial.println("Nepodarilo se prihlasit k Wi-Fi. Restartuji!");
    delay(10000);
    ESP.restart();
  }

  // Jsem pripojeny k Wi-Fi, napisu Ip adresu a silu signalu
  Serial.print("\nPripojeno na IP adrese ");
  Serial.print(WiFi.localIP());
  Serial.print(", ");
  Serial.print(WiFi.RSSI());
  Serial.println(" dBm");

  // Pokusim se skrze HTTP GET stahnout data s pocasim
  Serial.print("Stahuji data z webu... ");
  http.begin("http://kloboukuv.cloud/meteo.json");
  // Ulozim si navratovy HTTP kod
  int httpKod = http.GET();
  if (httpKod > 0) {
    Serial.println(httpKod);
    // Pokud se stazeni dat zdarilo, mohu pokracovat
    if (httpKod == HTTP_CODE_OK) {
      // Vypisu data
      String data = http.getString();
      Serial.println(data);
      /* Pomoci knihovny ArduinoJson prevedu data na JSON.
         Nejprve si vytvorim pamet pro JSON. ESP32 ma dostatek RAM,
         takze treba 1 000 B. Pote prevedu data na objekt JSON
      */
      StaticJsonBuffer<1000> jsonBuffer;
      JsonObject& json = jsonBuffer.parseObject(data.c_str());
      if (!json.success()) {
        Serial.println("Nepodarilo se dekodovat JSON!");
      }
      else {
        // Z JSON objektu ziskam meteorologicke udaje
        Serial.println("Vypisuji hodnoty na e-ink displej");
        float teplotaDoma = json["teplotaDoma"].as<float>();
        float teplotaVenku = json["teplotaVenku"].as<float>();
        float vlhkostDoma = json["vlhkostDoma"].as<float>();
        float vlhkostVenku = json["vlhkostVenku"].as<float>();
        float tlak = json["tlak"].as<float>();
        uint16_t luxmetr = json["slunce"].as<uint16_t>();
        uint8_t pocasi = json["pocasi"].as<uint8_t>();

        // Zavolam funkci pro vykresleni udaju na displej
        nakresli(teplotaDoma, teplotaVenku, vlhkostDoma, vlhkostVenku, luxmetr, tlak, pocasi);
      }
    }
    // Pokud se nepodarilo stahnout data, vypisu do seriove linky chybu
  } else {
    Serial.printf("Nepodarilo se stahnout data: %s\n", http.errorToString(httpKod).c_str());
  }

  // Ukoncim HTTP klient a prepnu mikrokontroler ESP32 do spanku
  http.end();
  esp_deep_sleep_start();
}

/* Funkci loop tentokrat nepouziji, jakmile se totiz
   mikrokontroler po 30 sekundach probudi ze spanku, vse zacne nanovo
   a opet se zpracuje funcke setup
*/
void loop() {
  ;
}

// Funkce pro vykresleni udaju na obrazovku
void nakresli(float teplotaDoma, float teplotaVenku, float vlhkostDoma, float vlhkostVenku, uint16_t luxmetr, float tlak, uint8_t pocasi)
{
  // Podle typu pocasi nakreslim velkou ikonu deste nebo slunicka
  switch (pocasi) {
    case 0:
      /* Nakresleni obrazku obrDest (pole pixelu v samostatnem
         hlavickovem souboru) o velikosti 128x128 px na pozici
         160x0 a to cernou barvou, protoze muj e-inkovy displej
         umi zobrazit jen cerny, nebo bily pixel
      */
      displej.drawBitmap(obrDest, 160, 0, 128, 128, GxEPD_BLACK, 1);
      break;
    case 1:
      displej.drawBitmap(obrSlunce, 160, 0, 128, 128, GxEPD_BLACK, 1);
      break;
  }

  // Nastaveni barvy pisma na cernou
  displej.setTextColor(GxEPD_BLACK);

  // Nakresleni bloku s venkovnimi hodnotami
  // Ikona stromu, teplota, vlhkost a intenzita svetla
  displej.drawBitmap(obrStromy, 10, 10, 30, 30, GxEPD_BLACK, 1);
  displej.setFont(&Lato_Heavy_35);
  displej.setCursor(50, 40);
  displej.print(teplotaVenku, 2);
  displej.setFont(&Lato_Medium_21);
  displej.setCursor(10, 65);
  displej.printf("%.0f%%  %u lx", (vlhkostVenku * 100), luxmetr);

  // Nakresleni bloku s vnitrnimi hodnotami
  // Ikona domecku, teplota, vlhkost a tlak vzduchu
  displej.drawBitmap(obrDomecek, 10, 70, 30, 30, GxEPD_BLACK, 1);
  displej.setFont(&Lato_Heavy_35);
  displej.setCursor(50, 100);
  displej.print(teplotaDoma, 2);
  displej.setFont(&Lato_Medium_21);
  displej.setCursor(10, 120);
  displej.printf("%.0f%%  %.2f hPa", (vlhkostDoma * 100), tlak);
  
  // Zatim vse kreslim jen do pameti
  // Teprve nyni vykreslim pole pixelu na obrazovku
  displej.update();
}
Diskuze (21) Další článek: Co bychom chtěli od nového Microsoft Office?

Témata článku: , , , , , , , , , , , , , , , , , , , , , , , ,