První kroky s M5Stackem: Meteostanice

M5Stack je další z řady programovatelných desek s mikropočítačem. Pro tento projekt byl použit kit M5GO, který se oproti jiným rozhraním může chlubit zabudovaným dvoupalcovým barevným LCD diplejem, devítiosým gyroskopem, WiFi konektivitou, reproduktorem i mikrofonem a baterií. Zkrátka – plně připraven pro IoT projekty. Zaujme i kompabilita s LEGEM, takže je možné mikropočítač připevnit na vlastní Lego projekty.

První spuštění

Pro první spuštění je navolen program, který ukazuje, jak je možné M5GO použít a seznámí Vás se všemi přednostmi – od reproduktoru, přes vestavěné LED Bary (na levé i pravé straně se nachází 5 RGB diod), až po vlastní moduly, které jsou součástí kitu – těmi jsou senzor na měření teploty, vlhkosti a tlaku, senzor pohybu, 3 RGB LED, infračervené ovládání a potenciometr. Ke každému ze senzorů je i ukázková miniaplikace. Součástí kitu je pak i Grove HUB, na který lze přes Grove propojky napojit až další 3 moduly. Grove konektivita je tak hlavní předností M5GO.

Update firmwaru

M5GO, stejně jako další modely od M5Stack, lze programovat v Arduino IDE nebo v WebIDE UIFlow (M5Flow), který funguje na bázi Blockly a Micropythonu – mezi oběma typy lze přepínat. Pro ukázku jsem použil M5Flow v režimu Blockly, neboť nevyžaduje žádné předchozí znalosti. Před začátkem je nutné ujistit se, že M5GO je ve stejné verzi jako M5Flow. Nejčastěji je nutné M5GO updatovat.

K updatu je potřeba M5GO připojit přes dodávaný USB-C kabel, nainstalovat potřebný CP2104 Driver a M5Burner. Obojí je dostupné na stránkách M5Stack. V programu M5Burner je nutné vybrat, na kterém COMu je M5GO připojen. Tato informace je k nalezení ve Správci zařízení, v záložce porty.

Prostředí M5Burner

V době psaní článku byla aktuální verze UIFlow 1.4.5. Po stažení zbývá novou verzi nahrát do M5GO pomocí tlačítka Burn. Jakmile se M5GO aktualizuje, přihlásí se sám znovu o slovo a opět se spustí uvítací program.

Pro další použití je potřeba M5GO restartovat stiskem napájecího tlačítka (dvojitý stisk M5GO vypne, pokud je napájen baterií) a stisknout pravé tlačítko označené jako SETUP. Zobrazí se stručné menu, ze kterého se pomocí tří tlačítek vybere požadovaný způsob připojení podle toho, kde se bude M5GO programovat.

Webové UIFlow

V menu SETUP v M5GO se zvolí Switch to Internet mode. M5GO vytvoří vlastní WiFi síť, na kterou se po připojení přes IP adresu (např. 192.168.4.1) zadají údaje k domácí WiFi síti. Po úspěšném zadání se M5GO sám připojí, restartuje a zobrazí QR kód i s API klíčem. Přes něj je možné se k mikropočítači připojit skrz prohlížeč a programovat M5GO přes webovou stránku. Na té se ihned po otevření zadá API klíč, pomocí kterého se prohlížeč spojí s M5GO. K nahrání kódu do M5GO nejsou potřebné žádné kabely, vše probíhá bezdrátově přes WiFi. Pokud však není dostupné připojení k internetu, musí se využít druhé varianty.

Desktopový program UIFlow

Prvně je nutné stáhnout desktopový program ze stránek M5Stack. Program je portable, což znamená, že není nutná žádná instalace a program lze přenášet třeba i na USB disku. V menu SETUP v M5GO se zvolí Switch to USB mode. V programu UIFlow se zvolí, na kterém portu je M5GO připojen. Výhodou této metody je nevázanost na připojení k internetu, je ale potřebné s sebou mít USB-C kabel.

Rozhraní programu UIFlow

Zapojení projektu

K projektu Meteostanice je zapotřebí mimo M5GO pouze jeden z modulů, který je navíc součástí balení – ENV senzor. Ten se připojí k M5GO pomocí Grove propojky, důležité je jeho připojení k portu A. Senzor lze k M5GO přichytit lego stavebnicí.

Kód pro M5GO

Před zahájením programování se musí přidat do UIFlow ENV senzor a vložit do displeje prvky, které budou použity. Ikonky počasí byly vytvořeny z kruhů a obdélníků. Mimo grafiky budou na obrazovce i tři štítky popisující přesný hydrometeorologický stav.

Vložení senzoru a základní schéma displeje

Ihned po startu, než se program dostane do smyčky, se skryjí ikonky počasí. V případě slunce, které se skládá z jednoho kruhu na to stačí jeden příkaz, déšť a mrak je řešen přes funkci, která v sobě obsahuje příkazy pro skrytí jednotlivých elementů.

Smyčka začíná aktualizováním štítků label_xxx, které nesou informace o aktuální situaci a které byly přidány do displeje ještě před začátkem programování. Přečtou se data ze senzoru a spojí se s textem. Hodnoty teploty a tlaku jsou zaokrouhlovány pouze na jedno desetinné místo.

Počátení nastavení, aktualizace štítků s hodnotami a volání funkcí diplay_temp / hum

Funkce display_temp a display_hum řídí vestavěné diody na bocích M5GO. Podle hodnot rozsvěcí daný počet diod a upravuje jejich barvu. Nastavení poslední diody na černou barvu zajišťuje její zhasnutí.

Část bloků pro rozsvěcení diod dle velikosti teploty

Posledním prvkem smyčky je podmínka, která na základě tlaku mění zobrazenou ikonku počasí. Některé předpřipravené prvky (které byly po přidání na displej pojmenovány jako cloud_x, sun_x, …) skryje, zbytek zavolá funkce, které jednotlivé ikonky rozpohybují pro dosažení lepšího efektu.

Rozeznání srážek a spuštění funkcí pro zobrazení odpovídající ikonky

Srážky jsou definované tlakem nižším než 950 Pa. Druhá podmínka kontroluje teplotu, podle jejíž hodnoty spustí animaci deště či sněžení.

Animace sněžení

Konkrétně animace sněžení se skládá z trojice pohybujících se obrázků vloček, které každou půl sekundu změní svou vertikální polohu na náhodnou souřadnici.

Animace deště funguje obdobným způsobem, kdy je měněna výška obdélníku představující kapky. U polojasna definovaného tlakem mezi 950 a 1050 Pa se náhodně mění velikost dvou kruhů uprostřed.

Pro slunce byla zvolena animace vzdalujících se paprsků v podobě kružnice. M5GO pokaždé vykreslí kružnici o daném poloměru, o chvíli později vykreslí další kružnici o větším poloměru a starou kružnici překryje novou kružnicí o barvě pozadí. Proměnná i je definována ihned na začátku smyčky a při každém opakování se navýší. Právě hodnota i definuje velikost poloměru kružnice, čímž je dosaženo vzdalující se kružnice od slunce.

Vzdalující se kružnice paprsků

Tímto jsou naprogamovány všechny prvky a zbývá nahrát kód do M5GO.

Nahrání kódu do M5GO

Testovací kód se do M5GO nahrává tlačítkem RUN v pravém horním rohu. Nahrávání kódu netrvá dlouho, takže je možné v průběhu programování jednotlivé funkce pohodlně testovat.

Program je možné do M5GO uložit a při každém zapnutí si například vybrat, který z nahraných programů má být spuštěn. Program se do M5GO ukládá z UIFlow tlačítkem Download v rozbalovací liště v pravém horním rohu vpravo od tlačítka RUN. Nalevo od tlačítka RUN se nachází správce zařízení. Jedině přes něj je možné nahrát do M5GO potřebné obrázky, případně smazat staré projekty.

Kód z Blockly na Python

from m5stack import *
from m5ui import *
from uiflow import *
import time
import unit

setScreenColor(0x000000)
env0 = unit.get(unit.ENV, unit.PORTA)




rain_3 = M5Rect(130, 140, 2, 40, 0x5578ff, 0x5578ff)
rain_4 = M5Rect(155, 140, 2, 40, 0x5578ff, 0x5578ff)
sun_1 = M5Circle(57, 44, 28, 0xffff00, 0x222222)
rain_2 = M5Rect(105, 140, 2, 40, 0x5578ff, 0x5578ff)
rain_1 = M5Rect(80, 140, 2, 40, 0x5578ff, 0x5578ff)
label_temp = M5TextBox(190, 180, "Teplota: -- *C", lcd.FONT_Default,0xFFFFFF, rotate=0)
cloud_4 = M5Circle(140, 88, 40, 0xFFFFFF, 0xFFFFFF)
label_hum = M5TextBox(190, 200, "Vlhkost: --%", lcd.FONT_Default,0xFFFFFF, rotate=0)
cloud_5 = M5Circle(170, 100, 30, 0xFFFFFF, 0xFFFFFF)
label_press = M5TextBox(190, 220, "Tlak: -- Pa", lcd.FONT_Default,0xFFFFFF, rotate=0)
cloud_1 = M5Rect(75, 90, 100, 41, 0xFFFFFF, 0xFFFFFF)
cloud_3 = M5Circle(97, 85, 15, 0xFFFFFF, 0xFFFFFF)
cloud_2 = M5Circle(69, 105, 25, 0xFFFFFF, 0xFFFFFF)
snow_3 = M5Img(133, 140, "res/m5_ms_02.jpg", True)
snow_2 = M5Img(108, 140, "res/m5_ms_02.jpg", True)
snow_1 = M5Img(83, 140, "res/m5_ms_02.jpg", True)

import random

i = None
j = None

def cloud_start():
  global i, j
  cloud_3.setSize(random.randint(15, 20))
  cloud_4.setSize(random.randint(30, 40))
  cloud_1.show()
  cloud_2.show()
  cloud_3.show()
  cloud_4.show()
  cloud_5.show()
  wait(0.5)

def rain_stop():
  global i, j
  rain_3.hide()
  rain_4.hide()
  rain_2.hide()
  rain_1.hide()

def cloud_stop():
  global i, j
  cloud_1.hide()
  cloud_2.hide()
  cloud_3.hide()
  cloud_4.hide()
  cloud_5.hide()

def display_temp():
  global i, j
  if (env0.temperature) < 0:
    rgb.setColor(5, 0x33ccff)
    rgb.setColor(4, 0x000000)
  elif (env0.temperature) < 10:
    rgb.setColor(5, 0x33ff33)
    rgb.setColor(4, 0x33ff33)
    rgb.setColor(3, 0x000000)
  elif (env0.temperature) < 20:
    rgb.setColor(5, 0xffff00)
    rgb.setColor(4, 0xffff00)
    rgb.setColor(3, 0xffff00)
    rgb.setColor(2, 0x000000)
  elif (env0.temperature) < 30:
    rgb.setColor(5, 0xff9900)
    rgb.setColor(4, 0xff9900)
    rgb.setColor(3, 0xff9900)
    rgb.setColor(2, 0xff9900)
    rgb.setColor(1, 0x000000)
  else:
    rgb.setColor(5, 0xff0000)
    rgb.setColor(4, 0xff0000)
    rgb.setColor(3, 0xff0000)
    rgb.setColor(2, 0xff0000)
    rgb.setColor(1, 0xff0000)

def display_hum():
  global i, j
  if (env0.humidity) < 20:
    rgb.setColor(6, 0x66ffff)
    rgb.setColor(7, 0x000000)
  elif (env0.humidity) < 40:
    rgb.setColor(6, 0x33ccff)
    rgb.setColor(7, 0x33ccff)
    rgb.setColor(8, 0x000000)
  elif (env0.humidity) < 60:
    rgb.setColor(6, 0x3366ff)
    rgb.setColor(7, 0x3366ff)
    rgb.setColor(8, 0x3366ff)
    rgb.setColor(9, 0x000000)
  elif (env0.humidity) < 80:
    rgb.setColor(6, 0x3333ff)
    rgb.setColor(7, 0x3333ff)
    rgb.setColor(8, 0x3333ff)
    rgb.setColor(9, 0x3333ff)
    rgb.setColor(10, 0x000000)
  else:
    rgb.setColor(6, 0x000099)
    rgb.setColor(7, 0x000099)
    rgb.setColor(8, 0x000099)
    rgb.setColor(9, 0x000099)
    rgb.setColor(10, 0x000099)

def rain_start():
  global i, j
  rain_3.show()
  rain_4.show()
  rain_2.show()
  rain_1.show()
  j = random.randint(0, 40)
  rain_1.setSize(height=j)
  rain_1.setPosition(y=random.randint(140, 180 - j))
  j = random.randint(0, 40)
  rain_2.setSize(height=j)
  rain_2.setPosition(y=random.randint(140, 180 - j))
  j = random.randint(0, 40)
  rain_3.setSize(height=j)
  rain_3.setPosition(y=random.randint(140, 180 - j))
  j = random.randint(0, 40)
  rain_4.setSize(height=j)
  rain_4.setPosition(y=random.randint(140, 180 - j))
  wait(0.5)

def sun_start():
  global i, j
  lcd.circle(57, 44, i, color=0xffff00)
  lcd.circle(57, 44, (i - 1), color=0x000000)
  lcd.circle(57, 44, 35, color=0x000000)
  wait(0.1)

def snow_start():
  global i, j
  snow_1.setPosition(y=random.randint(140, 160))
  snow_2.setPosition(y=random.randint(140, 160))
  snow_3.setPosition(y=random.randint(140, 160))
  wait(0.5)

def snow_stop():
  global i, j
  snow_1.hide()
  snow_2.hide()
  snow_3.hide()



sun_1.hide()
cloud_stop()
rain_stop()
snow_stop()
while True:
  for i in range(28, 36):
    label_temp.setText(str((str('Teplota: ') + str(((str(("%.1f"%((env0.temperature)))) + str(' *C')))))))
    label_hum.setText(str((str('Vlhkost: ') + str(((str((env0.humidity)) + str('%')))))))
    label_press.setText(str((str('Tlak: ') + str(((str(("%.1f"%((env0.pressure)))) + str(' Pa')))))))
    display_temp()
    display_hum()
    if (env0.pressure) < 950:
      sun_1.hide()
      cloud_1.show()
      cloud_2.show()
      cloud_3.show()
      cloud_4.show()
      cloud_5.show()
      if (env0.temperature) <= 0:
        snow_start()
      else:
        rain_start()
    elif (env0.pressure) > 1050:
      sun_1.show()
      sun_start()
      cloud_stop()
      rain_stop()
      snow_stop()
    else:
      sun_1.show()
      cloud_start()
      rain_stop()
      snow_stop()
  wait_ms(2)
zavři kód

Závěr

Do M5GO byl nahrán program, který využívat dat z připojeného ENV senzoru. Tato data zpracovává a zobrazuje je na LCD displeji. Teplotu a vlhkost navíc graficky zobrazují i diody na bocích M5GO.

Eshop

M5Stack M5GO IoT Starter Kit

Sada vývojové desky s 6 M5 jednotkami (ENV, IR, RGB, PIR, ANGLE, HUB) založená na ESP32.

Leave a Reply