Home Assistant: programování s ESP pomocí ESPHome

18. 1. 2024
Doba čtení: 23 minut

Sdílet

 Autor: Home Assistant
Dnešní pokračování bude určené spíše pro bastlíře. Podíváme se co vše potřebujeme k tomu, abychom dokázali naprogramovat své vlastní ESP zařízení a následně jej propojit s domácí automatizací.

Co je ESP?

Co se dozvíte v článku
  1. Co je ESP?
  2. ESPHome
  3. Praktické příklady
  4. Nebojte se toho

ESP je označení pro integrovaný čip od společnosti Espressif Systems, který obsahuje Wi-Fi, 32bitový microkontroler, implementuje TCP/IP stack a pomocí sběrnice dokáže komunikovat s připojenými periferiemi. Vyznačuje se svou jednoduchostí, malou spotřebou a je k dispozici jako samostatný modul nebo, což je častější případ, jako součást vývojových desek. Proto je tak oblíbený v IoT světě, kdy je alespoň s částečnou znalostí programování a zručností možná za relativně malé částky postavit zajímavá jednoúčelová zařízení.

Těmi mohou být různé senzory a měřiče, relé pro spínání různých zařízení nebo prosté zobrazování dat na displejích. Možností je opravdu nepřeberné množství a některé z nich si konkrétně ukážeme v tomto článku. Velkou výhodou je podpora OTA aktualizací, tedy že software je možné aktualizovat bezdrátově. Podrobněji o ESP pojednává několik starších článků, proto bych se opakoval a tak raději odkážu na předchozí články tady na Rootu.

Nejčastěji se tedy setkáme s čipem ESP8266 nebo výkonnějším ESP32, které jsou osazeny na vývojových deskách různých výrobců a provedení. Desky typicky obsahují pevně danou velikost flash paměti, různé množství a typy vstupně/výstupních pinů, integrovanou Wi-Fi anténu nebo konektor pro externí připojení. Nechybí konektor microUSB nebo USB-C pro napájení resp. programování.

Jakou desku vybrat? Pro začátek bych doporučil desku ESP8266 NodeMCU v3, obsahující USB převodník CH340, paměť RAM o velikosti 128 KB, flash paměť o velikost 4 MB a mikroprocesor pracující na frekvenci 80 MHz. Tuto desku je možné sehnat za cenu do 100 Kč a ve většině příkladů v tomto článku ji budeme používat.

Zajímavou alternativou je např. vývojová deska Wemos D1 mini Pro, která je minimalistických rozměrů a má tedy menší počet pinů. Za to ale obsahuje konektor pro externí Wi-Fi anténu. Je to tedy ideální pro případ, že je signál díky integrované Wi-Fi anténě nedostačující. Oproti NodeMCU obsahuje USB převodník CP2104 a flash paměť je k dispozici o velikosti 16 MB. Jak obě desky vypadají ve skutečnosti se můžeme podívat na následujících fotografiích:

Pokud čip ESP8266 nedostačuje, musíme zvolit výkonnější čipe ESP32. V tomto případě doporučím vývojovou desku ESP-WROOM-32 NodeMCU. K dispozici je navíc podpora Bluetooth, obsahuje převodník CP2102, dvě mikroprocesorová jádra s frekvencí 80 až 240 Mhz a deska je osazena 36 nebo 38 piny. Variantu s 38 piny následně používám s poslední ukázce tohoto článku.

Ačkoliv jsou jednotlivé piny na deskách označeny, určitě minimálně začátečníkům pomůže detailní popis, včetně obrázků. Velice zdařile je to uvedeno na webu RandomNerdTutorials.com, konkrétně na stránkách ESP8266 a ESP32.

ESPHome

Pro programování vývojových desek (nejen s čipy ESP) je možné využít různé možnosti a produkty. Často se používá Arduino IDE prostředí, pro které je nejdříve doplnit potřebné ovladače v závislosti na použité vývojové desce. Kód se pak píše přímo v jazyce  C++.

Jelikož už známe a používáme Home Assistant, můžeme si celé programování zásadně zjednodušit. Tím řešením je použití ESPHome, za kterým aktuálně stojí společnost Nabu Casa, kterou založili zakladatelé Home Assistanta. ESPHome tedy podporuje primárně čipy ESP8266 a ESP32, dokáže pracovat i s Raspberry Pico W, zařízeními Sonoff a dalšími. Hlavní výhoda je velice úzká integrace s Home Assistantem. Seznam zatím podporovaných zařízení a čipů nalezneme na stránkách projektu.

Jako hlavní způsob programování se používá jazyk YAML, jde tedy vlastně o definici různých proměnných, metod, vstupů, výstupů. Z YAML kódu se pak zkompiluje výsledný program a nahraje do zařízení. Složitější konstrukce je však samozřejmě možné realizovat v jazyce C++ nebo Python. Jak si ukážeme na konkrétních příkladech níže, některé syntaxe nám budou velice povědomé díky přípravě šablon senzorů pro Home Assistanta v minulých dílech našeho seriálu.

Instalace ESPHome

Instalaci si opět ukážeme pro obě nejčastěji používané varianty Home Assistanta. Pokud používáme OS/Supervised, pak jednoduše přejdeme do obchodu s doplňky, vyhledáme „EPSHome“ a nainstalujeme. Poté stačí jen nechat doplněk zobrazit v postranním panelu a spustit.

V případě varianty Container, budeme instalovat opět přímo z Docker hubu. Připravíme si na souborový persistentní úložiště, ve kterém budou uložena data a spustíme:

docker run --rm --name esphome --privileged -v /mnt/docker/esphome/config:/config -v /etc/localtime:/etc/localtime:ro --network host ghcr.io/esphome/esphome:stable

Příprava zařízení

Nové ESP máme před sebou, začneme s modelem ESP8266 NodeMCU v3. Stačí jen rozbalit a propojit s PC/serverem vhodným USB kabelem. Nejčastěji se setkáme s osazeným konektorem microUSB, případně také s USB-C. Ještě si musíme dát pozor na to, jaký USB kabel použijeme. Pokud nějaký obyčejný, typicky ze staré nabíječky mobilních telefonů, může se stát, že kabel nebude datový, ale jen nabíjecí. To zjistíme záhy, když budeme chtít navázat komunikaci se zařízením před uploadem připraveného firmware.

Přejdeme tedy do webového rozhraní ESPHome, pokud používáme variantu Supervised/OS, pak jen klikem z postranního panelu. Pokud máme ESPHome běžící z Dockeru, přistoupíme na URL http://IP_adresa:6052. Klikneme na tlačítko „+ NEW DEVICE“. V následující obrazovce se dozvíme, jaké možnosti inicializace nového zařízení jsou k dispozici. Potvrdíme pokračovat a zvolíme si název našeho nového zařízení, např. „esp1“. Pokud se jedná o opravdu první přidávané zařízení, zadáme ještě i údaje pro Wi-Fi síť.

Vzhledem k bezpečnosti doporučuji použít oddělené ESSID ve vlastní VLAN. ESP máme sice pod kontrolou, protože software nahráváme my, ale nemusí mít ostatní zařízení v síti k těmto IoT deskám přímý přístup. Název ESSID a heslo bude tedy uloženo do „Secrets“, které je možné kdykoliv editovat. ESPHome následně pro každé zařízení definuje odkaz na tyto hodnoty do jejich konfigurace, takže můžeme bez obav sdílet výsledný soubor YAML, pomocí kterého se připravuje firmware pro upload do zařízení.

V další obrazovce zvolíme typ zařízení. V našem případě budeme tedy pracovat s ESP8266. Po zvolení této platformy doporučuji odškrtnout položku „Use recommended settings“, abychom mohli vybrat konkrétní desku, kterou používáme. V opačném případě by se vybrala generická „esp01_1m“. Samozřejmě, že to je možné změnit, nicméně je to další krok navíc. Vybíráme tedy „NodeMCU 1.0 (ESP-12E Module)“. Po potvrzení je základní konfigurace připravena a v některých případech je i rovnou zobrazen klíč pro Home Assistanta, ke kterému se vrátíme později. ESPHome instalovaný z doplňku tento klíč nezobrazí, naopak instalace z Dockeru ano.

Nyní můžeme přistoupit k nahrání konfigurace pomocí tlačítka „Install“. Na výběr je několik možností, jak pokračovat. Volbu „Wireless“ budeme používat myslím nejčastěji, ale nelze jí nyní použít, protože v zařízení nemáme nahraný žádný firmware, který by alespoň navázal spojení s Wi-Fi.

Volba „Plug into the computer running ESPHome Dashboard“ je nejsnazší cesta, jak nahrát do zařízení firmware, ale znamená to, že musíme mít ESP přímo připojené s PC/serverem. Při první inicializaci to asi není problém, ale i tak to může být nepříjemné. Osobně dávám přednost volbě „Plug into this computer“, tedy vývojová deska je zapojena přímo např. do notebooku.

Má to však jeden háček. Aby bylo možné v takovém případě komunikovat se zařízením, je jediná cesta využít veřejný web ESPHome Web ovšem s webovými prohlížeči, které podporují WebSerial. Těmi jsou aktuálně pouze Google Chrome a Microsoft Edge. Zvolíme tedy tuto možnost, na pozadí se začne podle vytvořené konfigurace sestavovat firmware, který si pak lokálně stáhneme. Následně můžeme přejít na ESPHome Web pomocí jednoho z podporovaných webových prohlížečů.

Na úvodní obrazovce klikneme na „CONNECT“ a vybereme USB serial zařízení. Na různých operačních systémech a v závislosti na daném ESP se může detekovat různě, např. „cu.usbserial-10“, „ttyUS0“, „USBtoUART“ apod. Pokud žádnou podobnou položku nevidíme, tak zřejmě nepoužíváme datový USB kabel, ale jen nabíjecí. Nebo nemáme potřebné ovladače, které je potřeba stáhnout podle použitého čipu.

Pro zařízení s čipem CP210× (typicky ESP32, čip ve tvaru čtverce, na kterém je typ i přímo uveden), pak jsou ovladače k dispozici na Silabs.com. Pro zařízení s čipem CH340/1 (typicky ESP8266) můžeme ovladače najít na GitHubu, případě ještě pro čipy CH342/3 nebo CH9102 pak na Wch.cn. V případě, že na Linuxu objeví chyba s připojením, je potřeba zkontrolovat oprávnění přihlášeného uživatele, zda-li je ve skupině „dialout“. V opačném případě je potřeba uživatelský účet přidat do skupiny:

usermod -aG dialout USER_NAME

a následovaně provést odhlášení/restart. Pokud by to přeci jen nepomohlo, pak je možné nastavit oprávnění přímo na dané zařízení.

setfacl -m u:USER_NAME:rw /dev/ttyUSB0

Po úspěšném spojení se zařízením již stačí kliknout na „Install“ a vybrat uložený soubor .bin  s firmwarem. Pokud máme funkční protokol mDNS (na Linuxu k tomu potřebujeme běžící službu avahi-daemon ) a domácí Wi-Fi AP tento protokol podporují, mělo by být zařízení dostupné v našem případě jako  esp1.local.

Pro základní otestování, že je zařízení v síti viditelné, můžeme vyzkoušet ping esp1.local , jinak je nutné zkontrolovat logy DHCP serveru a vyzkoušet dostupnost přímo přes IP adresu. Od této chvíle můžeme ESP odpojit od počítače a napájet standardním adaptérem a současně již všechny další aktualizace firmware můžeme realizovat bezdrátově.

Než přistoupíme k lehkému programování, mám ještě dvě poznámky. V rozhraní ESPHome se u každého zařízení ukazuje, jestli je dostupné či nikoliv. Tato kontrola se provádí pomocí protokolu mDNS a nemá na žádnou funkcionalitu vliv. Je to jen informativní položka. Pokud vás znepokojuje, že se zařízení stále hlásí jako „OFFLINE“ a tedy máme problém s mDNS, můžeme to opravit dvěma způsoby. Tím prvním je definice IP adresy a doménového jména v souboru /etc/avahi/hosts pro všechna zařízení. Zápis je stejný, jako v u souboru  /etc/hosts.

Druhou možností je změnit metodu ověřování dostupnosti cíle přímo v ESPHome, pokud je provozován jako Docker kontejner. V takovém případě postačí přidat parametr -e ESPHOME_DASHBOARD_USE_PING=true a namísto ověřování mDNS se bude používat standardní ping.

Druhá poznámka souvisí s bezdrátovým připojením k zařízení pro aktualizaci firmware. Pokud se nám nedaří se spojit se zařízením, ať už se jedná o problém s překladem mDNS či jakýkoliv jiný, je možné každému zařízení do konfigurace přímo nastavit jeho IP adresu. Ta se právě z konfiguračního souboru načte před pokusem o připojení. Stačí tedy kliknout na „Edit“ do sekce wifi doplnit  use_address.

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  use_address: 192.168.50.44

Praktické příklady

Prvotní inicializaci máme za sebou a můžeme se podívat na několik praktických příkladů. Přemýšlel jsem, jak vás nejlépe s touto problematikou seznámit a tak jsem vymyslel tři, z mého pohledu, nejčastější případy použití. Pro tyto případy jsem opatřil potřebné komponenty, se kterými vás seznámím a dále jsem připravil, vyzkoušel a odladil každý program.

V jednotlivých krocích se budu snažit vysvětlit, co daný kus kód provádí, proč je důležitý a jak dále postupovat. Cílem je, aby bylo možné na konci každého příkladu jednoduše sestavit kompletní a funkční kód.

Teploměr, vlhkoměr, tlakoměr

V prvním praktické příkladu si ukážeme, jak sestavit jednoduchý senzor teploty, vlhkosti a atmosférického tlaku. Budeme potřebovat senzor BME280 (nabízí se jak v 3,3V tak i v 5V variantě) a samozřejmě desku ESP8266 NodeMCU. Senzor používá známou sběrnici I2C (podrobněji např. v jiném článku na Rootu), kterou ESP běžně podporuje a je samozřejmě možné na jednu desku připojit více zařízení na stejné sběrnici. Komunikace mezi nimi se pak rozlišuje dle adresy, na rozdíl od sběrnice SPI.

5V varianta tohoto senzoru komunikuje pouze na sběrnici I2C a obsahuje tak čtyři piny – napájení VCC+GND, SDA (přenos dat) a SCL (hodinový signál). 3,3V varianta tohoto senzoru podporuje i sběrnici SPI a tak kromě již zmíněných čtyř pinů obsahuje ještě i piny CSB (chip select) a SD0 (MISO – Master-Input, Slave-Output). Pro ukázku jsem využil 3,3V variantu senzoru, ale komunikace probíhala po I2C.

Než začneme programovat, zapojíme všechny potřebné piny senzoru. Na pin D1 (GPIO5) připojíme SCL, na pin D2 (GPIO4) SDA, na pin 3V napájení VCC a na pin GND zem GND. Samozřejmě nezapomene na napájení ESP desky USB kabelem, např. pomocí jakékoliv vhodné nabíječky na mobilní telefon. Datový kabel už není potřeba, protože ESP máme zinicializované a komunikující po Wi-Fi.

Nyní můžeme přistoupit k psaní kódu. Otevřeme webové rozhraní ESPHome, klikneme na „Edit“ našeho aktivního zařízení a vlastní YAML kód budeme psát klidně na konec. Začneme definicí použitých pinů pro sběrnici I2C:

i2c:
  sda: D1
  scl: D2

Následně zadáme senzor pro jednotlivé měřící veličiny, který se vždy definuje vzhledem ke své platformě. V tomto případě tedy k platformě bme280. Každou veličinu je možné pojmenovat a nepovinně vložit také své ID, které využijeme později. Dále ještě uvedeme adresu (tyto senzory nejčastěji používají adresu 0×76 nebo 0×77) a interval, po kterém se mají poslat nové hodnoty měření. Kompletní definice pak vypadá následovně:

sensor:
  - platform: bme280
    temperature:
      name: "Templota"
      id: temperature
    pressure:
      name: "Tlak"
      id: pressure
    humidity:
      name: "Vlhkost"
      id: humidity
    address: 0x76
    update_interval: 5min

V tuto chvíli již budeme mít k dispozici data všech tří veličin, ale ještě je potřebujeme posílat přímo do Home Assistanta. Využijeme na to tentokrát platformu homeassistant a určíme, jak budou nové entity pojmenované a na jaké ID bme280 senzoru budou namapované. Do již existující sekce sensor: tedy přidáme:

  - platform: homeassistant
    id: bme280_temperature
    entity_id: sensor.mujsensor_temperature
    internal: true

  - platform: homeassistant
    id: bme280_humidity
    entity_id: sensor.mujsensor_humidity
    internal: true

  - platform: homeassistant
    id: bme280_pressure
    entity_id: sensor.mujsensor_pressure
    internal: true

Ještě doporučím přidat ke každému ESP senzor Wi-Fi signálu, pro lepší kontrolu stavu připojení. Ten se bude také exportovat přímo do Home Assistanta a bude se aktualizovat každých pět minut:

  - platform: wifi_signal
    name: "WiFi_Signal"
    id: wifi_sensor
    update_interval: 5min

Nyní už zbývá jen kód uložit tlačítkem „Save“ vpravo nahoře. Pokud by se objevila nějaká syntaktická chyba, rozhraní na to včas upozorní. Po uložení již můžeme svůj první program nahrát do ESP tlačítkem „Install“, kde v dalším kroku již můžeme zvolit metodu „Wirelessly“. Aby se zařízení objevilo v Home Assistantu, je potřeba jej přidat pomocí IP adresy a šifrovacího klíče, o kterém jsme se zmiňoval výše.

Ten si můžeme vypsat a zkopírovat do schránky kliknutím v ESPHome rozhraní na tři svislé tečky u daného zařízení zvolením „Show API Key“. V Home Assistantu tedy pak v menu Nastavení → Integrace přidáme novou integraci ESPHome a přidáme nové zařízení. Vložíme IP adresu a již zjištěný šifrovací klíč. Pokud vše proběhne v pořádku, mělo by se objevit nové zařízení se čtyřmi entitami. Zapojení v praxi ukazuje následující obrázek.

OLED displej

Senzor tedy měří tři veličiny, které od něj očekáváme a posílá je do Home Assistantu. Co kdybychom je ale chtěli zobrazovat třeba na displeji? Přesně na to jsem myslel, když jsem si zprovoznil svou první desku ESP, že to je další věc, kterou musím vyzkoušet. Začal jsem tedy jednoduchým OLED displejem, alfanumerické LCD displeje jsem rovnou zavrhl pro jejich přílišnou jednoduchost. V druhém praktickém příkladu tedy rozšíříme již funkční senzor bme280 o jednoduchý displej.

ESPHome má podporu pro OLED displeje v rámci platformy SSD1306 a podporuje je jak ve variantě I2C, tak i SPI. Vybral jsem si model SH1106 s uhlopříčkou 1,3" a rozlišením 128×64 pro sběrnici I2C. K dispozici jsou ještě další druhy s jinými rozlišeními. Tento konkrétní model jsem vybral jako takovou zlatou střední cestu v tomto segmentu.

Displej má tedy také čtyři piny, napájení VCC+GND, SDA a SCK (jiné označení pro SCL). Stejně jako v předchozím případě má definovanou svojí adresu, po které na sběrnici komunikuje. Zapojení pinů je tedy totožné, jako v předchozím případě a teď už vše musíme propojit pomocí nepájivého pole.

Pokud máme zapojeno, můžeme přidat do stávajícího programu základní definici displeje, dle použitého modelu a se správnou adresou:

display:
  - platform: ssd1306_i2c
    model: "SH1106 128x64"
    address: 0x3C

Abychom mohli pracovat s displejem, musíme využít konstrukci lambda (doplňuje YAML o C++ kód), kterou je ale možné použít pouze u displejů, které vykreslují pixely. Kromě renderování znaků můžeme definovat různé fonty, vykreslovat čáry či různé obrazce, v případě barevných displejů obarvit text nebo pozadí, jednoduché grafy a samozřejmě i obrázky. Možností je velké množství, pro kompletní specifikaci odkáži na dokumentaci displejů.

Vraťme se ale zpět k programování. Každý správný program přeci začíná konstukcí „Hello world!“ a to si také ukážeme. Je to jednoduché, do sekce display přidáme konstrukci it.print s parametry, které určí, že začátek textu bude vykreslen od pozice x=20, y=10 a zadaným fontem:

  lambda: |-
    it.print(20, 10, id(mujfont), "Hello World!");

Font ale musí mít také svojí definici, jinak rozhraní nahlásí chybu, že jej nezná. Nejdříve si musíme sadu fontů stáhnout. Buď přímo konkrétní soubory .ttf  na internetu a nebo na Linuxu (konkrétně Debianu) instalací balíku ttf-mscorefonts-installer. Fonty pak budou k nalezení v umístění /usr/share/fonts/truetype/msttcorefonts. Konkrétní soubor, v mém případě Arial.ttf je nutné nakopírovat přímo do kořenového adresáře ESPHome.

Pokud jej používáme jako dockerový kontejner, stačí jej nakopírovat přímo do vlastního persistentního úložiště. V případě doplňku ESPHome v rámci Home Assistant OS/Supervised můžeme využít doplněk „File Editor“. Do kódu svého zařízení tak ještě přidáme sekci font:, zadáme ID fontu a velikost, uložíme a můžeme vyzkoušet nahráním upraveného programu do zařízení:

font:
  - file: 'Arial.ttf'
    id: mujfont
    size: 12

Pozdrav máme tedy za sebou, ale nás zajímá zobrazení přímo měřených veličin senzorem bm280. Zápis v lambda je v podstatě stejný, jen namísto vypisovaného řetězce použijeme ID s metodou state dané veličiny, např. teploty:

  lambda: |-
    it.printf(0, 20, id(mujfont), "%7.1f°C", id(bme280_temperature).state);

Tímto způsobem můžeme vykreslit displej s informacemi přesně podle našich přestav. Pro vaší inspiraci jsem si připravil kompletní zobrazení dat na displeji z použitého senzoru, včetně aktuálního času a síly Wi-Fi signálu. Oba údaje se získávají z běžící instance Home Assistantu. Posuďte sami na obrázku, jak to reálně může vypadat. Samozřejmě přikládám kompletní kód.

time:
  - platform: homeassistant
    id: esptime
    timezone: Europe/Prague

sensor:
  - platform: homeassistant
    id: bme280_temperature
    entity_id: sensor.teplomer_temperature
    internal: true

  - platform: homeassistant
    id: bme280_humidity
    entity_id: sensor.teplomer_humidity
    internal: true

  - platform: homeassistant
    id: bme280_pressure
    entity_id: sensor.teplomer_pressure
    internal: true

  - platform: bme280
    temperature:
      name: "Temperature"
      id: temperature
    pressure:
      name: "Pressure"
      id: pressure
    humidity:
      name: "Humidity"
      id: humidity
    address: 0x76
    update_interval: 5min

  - platform: wifi_signal
    name: "WiFi_Signal"
    id: wifi_sensor
    update_interval: 5min

font:
  - file: 'Arial.ttf'
    id: arial
    size: 12
  - file: 'Arial.ttf'
    id: arial_clock
    size: 22
  - file: 'materialdesignicons-webfont.ttf'
    id: icons
    size: 12
    glyphs:
      - "\U000F050F" #thermometer
      - "\U000F058E" #humidity
      - "\U000F029A" #gauge

i2c:
  sda: D1
  scl: D2

display:
  - platform: ssd1306_i2c
    model: "SH1106 128x64"
    address: 0x3C
    update_interval: 5s
    lambda: |-
      it.printf(it.get_width(),0, id(arial), TextAlign::RIGHT, "%.0f dBm", id(wifi_sensor).state);
      it.line(75, 15, it.get_width(), 15);
      it.strftime(it.get_width(), 25, id(arial_clock), TextAlign::RIGHT, "%H:%M", id(esptime).now());

      if (id(temperature).has_state()) {
       it.printf(0, 20, id(icons), "\U000F050F");
       it.printf(7, 20, id(arial), "%7.1f°C", id(bme280_temperature).state);
      }
      if (id(humidity).has_state()) {
        it.printf(0, 35, id(icons),"\U000F058E");
        it.printf(7, 35, id(arial), "%7.1f%%", id(bme280_humidity).state);
      }
      if (id(pressure).has_state()) {
        it.printf(0, 50, id(icons),"\U000F029A");
        it.printf(10, 50, id(arial), "%7.1fhPa", id(bme280_pressure).state);
      }

Pravděpodobně se pozastavíte nad tím, jakým způsobem jsou vykresleny ty ikonky. Využívám k tomu speciální font MaterialDesign, který je ke stažení na GitHubu. Pracuji s tím tak, že na webu Pictogrammers.com vyhledám ikonu, kterou chci použít a po kliknutí se v horní pravé části ukáže její kód, např. F02D1, který následně definuji jak u daného fontu, tak při vykreslování v lambda pomocí  it.printf.

Volitelná proměnná glyphs určuje, které znaky se budou v programu používat a tedy se zkompilují spolu s programem. Je tím možné zmenšit velikost výsledného binárního souboru s programem a současně se to používá pro netypické znaky, typicky naše háčky a čárky, aby se zobrazily správně. Zbytek práce je už jen správné pozicování textu a použitých senzorů.

TFT dotykový displej

Pokud vás neodradila trochu složitější práce s relativně obyčejným OLED displejem, poslední praktický příklad bude náročnější. Ukážeme si totiž použití barevného displeje, konkrétně jak pomocí dotyku rozsvítit a zhasnout žárovku integrovanou v Home Asisstantu.

Pro tento příklad jsem použil 2,4" TFT dotykový displej ILI9341 s rozlišením 240×320, komunikující na sběrnici SPI. Pokud by uhlopříčka nebo rozlišení nestačilo, můžeme si vybrat ze stejné série (níže uvedené postupy budou tedy stejné) např. 3.5" displej ILI9486 s rozlišením 320×480 nebo 4.0" displej ST7796 se stejným rozlišením.

Drobnou komplikací však je, že už nelze využít ESP8266, byť deska NodeMCU obsahuje všechny potřebné piny a zapojit displej (alespoň bez dotykové části) je možné. Bohužel výkon tohoto ESP nestačí k tomu, aby bylo možné displej používat. Musíme využít již na začátku zmiňovaný ESP32, tj. desku ESP-WROOM-32 NodeMCU.

Nejdříve zapojíme displej s vývojovou deskou. Budeme potřebovat celkem čtrnáct vodičů – prvních devět pro samotný displej a zbylých pět, označených T_, pro dotykovou vrstvu. Zapojení jednotlivých pinů displeje k desce ESP je uvedeno pro větší přehlednost v tabulce a opět se neobejdeme alespoň bez nepájivého pole:

Displej ESP32
VCC 3V3
GND GND
CS P13
RESET P33
DC P27
SDI(MOSI) P23
SCK P18
LED P32
SDO(MISO) P19
T_CLK na SCK – P18
T_CS P17
T_DIN na SDI(MOSI) – P23
T_DO na SDO(MISO) – P19
T_IRQ P16

K desce připojíme USB kabel a provedeme stejným způsobem inicializaci v ESPHome, jako v případě desky ESP8266 NodeMCU. Jen s tím rozdílem, že vybereme zařízení typu ESP32 a desku NodeMCU-32S. Před samotnou inicializací může být potřeba stisknout tlačítko BOOT, aby se zahájil přenos. Jakmile je zařízení dostupné na Wi-Fi síti, můžeme začít programovat. Na rozdíl od předchozích příkladů, nepoužijeme sběrnici I2C, ale SPI. Piny CLK, MOSI a MISO odpovídají zapojení dle tabulky.

spi:
  clk_pin: 18
  mosi_pin: 23
  miso_pin: 19

Dále nadefinujeme výstup s LCD pinem a informace o samotném displeji. Zde definujeme platformu, konkrétní model, piny CS, DC a RESET a případně otočení. V dalších ukázkách budu předpokládat, že je displej otočený na šířku o 270 stupňů.

output:
  - platform: ledc
    pin: 32
    id: led_output

display:
  - platform: ili9xxx
    model: TFT_2.4
    cs_pin: 13
    dc_pin: 27
    reset_pin: 33
    rotation: 270
    id: my_display
    lambda: |-

Pro prvotní vyzkoušení můžeme opět vypsat uvítací hlášení, tentokrát i barevně, díky definici  color:

font:
  - file: 'Arial.ttf'
    id: arial
    size: 20

color:
  - id: color_yellow
    red: 100%
    green: 100%
    blue: 0%

display:
  ...
    lambda: |-
      it.print(20, 20, id(arial), id(color_yellow), "Hello World!");

Funguje? Skvěle, v dalším kroku připravíme finální podobu displeje. Tedy dvě tlačítka pro zapnutí a vypnutí světla, na které na závěr nastavíme dotykovou oblast. Dále umístíme obrázek, který bude informovat o tom, zda-li žárovka svítí a pár dalších textových informací – nadpis, sílu signálu Wi-Fi a aktuální čas.

Vložíme tedy definici font s vyjmenovanými znaky, včetně háčků a čárek. Dále blok image pro definici dvou obrázků, které se budou vykreslovat dle stavu žárovky. Žárovku zadáme jako binary_sensor dle entity z Home Assistantu. Tlačítka vykreslíme pomocí barevného obdélníku. Obrázky je potřeba stejným způsobem nahrát, podobně jako fonty, přímo do úložiště ESPHome. Po vložení můžeme opět nahrát nový program do ESP a vše vyzkoušet.

time:
  - platform: homeassistant
    id: esptime

binary_sensor:
  - platform: homeassistant
    id: moje_svetlo
    entity_id: light.svetlo_obyvak
    internal: true

sensor:
  - platform: wifi_signal
    name: "WiFi_Signal"
    id: wifi_sensor
    update_interval: 5min

font:
  - file: 'Arial.ttf'
    id: arial
    size: 20
    glyphs: "!%()+,-/_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyzěščřžýáíéů"
  - file: 'Impact.ttf'
    id: impact
    size: 34
    glyphs: "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz"
  - file: 'Impact.ttf'
    id: impact_clock
    glyphs: ":0123456789"
    size: 60

image:
  - file: "home-assistant.png"
    id: domecek
    resize: 80x80
    type: RGB24
  - file: "home-assistant_2.png"
    id: domecek_white
    resize: 80x80
    type: RGB24

display:
  ...
  lambda: |-
      auto red = Color(255, 0, 0);
      auto green = Color(0, 255, 0);
      it.fill(Color::BLACK);

      it.printf(0,0, id(arial), id(Color::WHITE), "Ovládání světla");
      it.printf(it.get_width(),0, id(arial), id(color_yellow), TextAlign::RIGHT, "%.0f dBm", id(wifi_sensor).state);
      it.line(240, 25, it.get_width(), 25);
      it.strftime(it.get_width(), 60, id(impact_clock), TextAlign::RIGHT, "%H:%M", id(esptime).now());

      it.filled_rectangle(0, 160, 160, 80, green);
      it.filled_rectangle(160, 160, 160, 80, red);
      it.print(25, 180, id(impact), id(Color::WHITE), "Zapnout");
      it.print(188, 180, id(impact), id(Color::WHITE), "Vypnout");

      if (id(moje_svetlo).state) {
        it.image( 50,  60, id(domecek_white));
      } else {
        it.image( 50,  60, id(domecek));
      }

V tuto chvíli už zbývá jen oživit dotykovou vrstvou displeje. Nejdříve vložíme definici touchscreen s platformou xpt2046 vzhledem k použitému displeji. Dále uvedeme, kam jsou zapojené piny T_CS a T_IRQ a doplníme volitelné parametry. Abychom mohli dále s dotykovou vrstvou pracovat, musíme mít zkalibrované oblasti os x a y. Proto přidáme událost on_touch, program přeložíme a nahrajeme do zařízení.

touchscreen:
  platform: xpt2046
  id: my_touchscreen
  cs_pin: 17
  interrupt_pin: 16
  update_interval: 50ms
  threshold: 400
  on_touch:
    - lambda: |-
          ESP_LOGI("cal", "x=%d, y=%d, x_raw=%d, y_raw=%0d",
              touch.x,
              touch.y,
              touch.x_raw,
              touch.y_raw
              );

Necháme si otevřenou konzoli s logy, použijeme přiložený stylus a dotykem zjistíme minimální a maximální hodnoty os x a y. V logu se objeví řádky v tomto formátu a nás budou zajímat hodnoty x_raw a y_raw.

[14:13:57][I][cal:073]: x=3, y=172, x_raw=3800, y_raw=2741

Vzhledem k tomu, že je displej otočen o 270 stupňů, jsou pouze mezi sebou vyměněné hodnoty max a min. Tím zajistíme, že pozice x=0,y=0 bude skutečně v levém horním rohu, aby se nám dobře počítaly hranice obou tlačítek. V sekci touchscreen tedy můžeme odstranit událost on_touch a vložíme zkalibrované hodnoty. V mém případě se jednalo o:

touchscreen:
  ...
  calibration_x_min: 3835
  calibration_x_max: 333
  calibration_y_min: 300
  calibration_y_max: 3685

Po úspěšné kalibraci vytvoříme dva binary_sensor pro obě tlačítka s platformou touchscreen, pro která musíme uvést hodnoty x_min, x_max, y_min, y_max. Tedy konkrétní hranice daných obdélníků. Ty můžeme buď odhadnout podle hodnot uvedených v it.filled_rectangle  a nebo opět použít logování pozic v kroku kalibrace. Nakonec přidáme událost on_press s logováním, abychom nejdříve vyzkoušeli, že máme hranice dotyku nastavené správně. Program opět přeložíme a nahrajeme do zařízení.

binary_sensor:
  ...
  - platform: touchscreen
    id: touch_tlacitko_zapnout
    x_min: 0
    x_max: 160
    y_min: 160
    y_max: 240
    on_press:
    - logger.log: "stisknuto tlacitko zapnout"

  - platform: touchscreen
    id: touch_tlacitko_vypnout
    x_min: 161
    x_max: 320
    y_min: 160
    y_max: 240
    on_press:
    - logger.log: "stisknuto tlacitko vypnout"

Pokud displej reaguje na dotyk v požadovaných mezích, zbývá už jen doplnit ovládání žárovky. Přidáme událost on_state s podmínkou, zda-li je aktivní daný binární senzor a na základě toho se zavolá služba Home Assistantu  light.turn_on, resp. light.turn_off. Zápis pro tlačítko zapnutí bude vypadat následovně:

  - platform: trouchscreen
  id: touch_tlacitko_zapnout
  ...
  on_state:
  if:
    condition:
      binary_sensor.is_on: touch_tlacitko_zapnout
    then:
    - homeassistant.service:
        service: light.turn_on
        data:
         entity_id: light.svetlo_obyvak

V posledním kroku musíme ještě provést jednu podstatnou akci. ESP nemá standardně kvůli bezpečnosti povoleno externě volat jakoukoliv službu Home Assistanta. Proto musíme jít v Home Assistantu do Nastavení → Integrace → ESPHome a u svého zařízení kliknout na „NASTAVIT“. V dialogovém okně zaškrtneme „Povolí zařízení volat službu Home Assistanta“. Nyní by už nemělo nic bránit nahrání kompletního programu do ESP a můžete vyzkoušet ovládání světla pomocí dotykového displeje, který bude vypadat takto:

Nebojte se toho

Tento díl byl trochu náročnější a snad mi odpustíte, že jsem se příliš nevěnoval teorii. Chtěl jsem vás co nejjednodušší formou seznámit s tím, jak začít s ESP programováním ve spojení s Home Assistantem a že to vlastně není nic tak složitého, jak se možná na první pohled zdá.

Třeba jsem tím někoho nadchl k vlastnímu bastlení. Pokud již rozmýšlíte, jaký další projekt s ESP budete realizovat, doporučuji nejdříve prostudovat na webu projektu, zda jednotlivé vybrané komponenty jsou v ESPHome podporované.

bitcoin_skoleni

Do minulého dílu, který byl věnován uživatelskému rozhraní, se vzhledem k rozsahu nevešla zajímavá rozšíření a integrace, které používám pro sledování a řízení fotovoltaické elektrárny. Proto toto téma zpracuji do příštího pokračování.

Autorem fotografií je Václav Steiner.

Autor článku

V minulosti vedl týmy systémových administrátorů ve společnosti IGNUM nebo sdružení CZ.NIC, nyní působí ve společnosti VSHosting.