Programování | Pojďme programovat elektroniku | Arduino

Pojďme programovat elektroniku: Meteostanice, která bude díky Sigfoxu posílat stav počasí třeba z vrcholu Sněžky

  • Příští roky budou ve znamení internetu věcí
  • Podívali jsme se podrobně na síť Sigfox
  • Takhle s ní komunikují krabičky z celé Evropy

S rostoucím počtem všemožných automatických krabiček, které měří vše okolo nás, roste i hlad po konektivitě. Zatímco u vás doma postačí Wi-Fi, kdesi na volném prostranství, na chalupě, nebo prostě uprostřed lesa už to tak jednoduché není. V takových případech zpravidla zbývá jen klasická mobilní síť a zasílání dat pomocí SMS nebo mobilního internetu, nebo využití nějaké proprietární rádiové technologie.

Sigfox

Na podzim jsme si v našem seriálu Pojďme programovat elektroniku vyzkoušeli jednu z nich – Sigfox, který je dnes jednou z největších mobilních sítí pro IoT. To v praxi znamená, že k mikropočítači, který bude třeba na chalupě sledovat, jak vám čerstvě zasazený trávník rozrývají krtci, připojíte maličký 868MHz modem, který pak bude moci až 140× za den odeslat malou 12B zprávu.

44445206 267649527
Aktuální stav pokrytí Sigfoxem (všichni operátoři) v Evropě a v Česko-Slovensku (SimpleCell). Bledě-modře jsou označené země, kde probíhá výstavba sítě.

Aby se tak stalo, vedle sítě samotné má Sigfox i své operátory, kteří postupně (a zpravidla ve spolupráci s tradičními mobilními operátory) pokrývají svět. V České republice se o to stará operátor SimpleCell, který využívá infrastruktury T-Mobile. Díky této spolupráci je dnes Sigfoxem pokrytá drtivá většina Česka a operátor si tak vedle dat nově troufá i na geolokační služby.

Pětidolarový Wisol

Sigfox a další sítě jsou stále na svém počátku, a tak se teprve rodí dostatečně pestrá nabídka vysílačů všech cenových kategorií. Jedním takovým jsou i maličké modemy Wisol, jejichž cena začíná už na atraktivních pěti dolarech za kus.

428762724 760966393 639214873 846036259
Maličký modem Wisol na prototypovací destičce BRKWS01 odešle data na server prakticky z libovolného místa v ČR

Něco takového jsem si musel samozřejmě vyzkoušet, a tak jsem si od SimpleCellu půjčil o něco dražší prototypovací destičku Sigfox BRKWS01 od francouzské společnosti SNOC, která tento modul používá. V balení dorazila i anténa a hlavně kupón na roční předplatné samotné služby.

143262409 661322690 15186917
Registrace modemu v síti Sigfox

Každý modem Sigfoxu je třeba před prvním použitím aktivovat. To znamená, že si na webu založíte účet a v registračním formuláři zadáte nejprve zemi a operátora, kde budete modem používat, a pak jeho sériové číslo a identifikátor PAC. Jedná se o jakousi analogii IMEI a telefonního čísla z klasické mobilní sítě. A to je celé. Jakmile bude modem zaregistrovaný, můžete okamžitě začít posílat zprávy.

Kolik to vlastně stojí?

No, a to se vlastně dostáváme ke klíčové otázce. Sigfox asi není zdarma, že? Ne, není. Někdo musí síť rozšiřovat a udržovat a stejně tak musí být stále k dispozici servery, na které každým okamžikem přichází hromada zpráv z jednotlivých krabiček.

464086682 254835235
Přehled registrovaných modemů pod mým účtem a pohled na petiminutové statistiky komuniakce jednoho z nich

Jenže když budete chtít znát výši předplatného jako amatérský bastlíř, který by si nejraději koupil třeba jen jeden modem za pár dolarů, spíše narazíte. Na webech jednotlivých operátorů nenajdete koncové ceníky, zatím se totiž pochopitelně orientují především na B2B scénu a předpokládají instalaci poněkud většího množství senzorů než jednoho plašiče krtků.

Na stranu druhou, každá technologie je tak živá, podporovaná a sexy, jak živá a široká je její komunita. Pokud se tedy zájemci z řad amatérů ozvou, operátoři Sigfoxu je neodmítnou. A kolik to tedy bude stát? Pavel Sodomka z českého SimpleCellu nabídl lakonickou odpověď: „Cena se podle počtu zpráv od zařízení a počtu zařízení v projektu pohybuje od jednotek po nízké desetikoruny měsíčně.

Proč jen 140 zpráv denně?

Jak už jsem zmínil výše, zpráva v síti Sigfox může mít nejvýše 12 bajtů a jejich denní počet je limitovaný na cirka 140 kusů. Relativně malé množství je dáno i kontinentální regulací ETSI, v daném kmitočtu a na stanoveném výkonu totiž může zařízení strávit vysíláním nejvýše 1 % času z jedné hodiny, což dělá nějakých 36 sekund. A jelikož odeslání zprávy zabere okolo šesti sekund, znamená to, že byste neměli zasílat více než šest zpráv za hodinu.

593780997
Hrubá poloha modemu podle příslušnosti k vysílači

Celou dobu tu píšu o zprávách ze zařízení, ale co když chci naopak já něco poslat modemu? Jde to, ale principiálně se s tím příliš nepočítá. Takovým zprávám se říká downlink, jsou kratší (8 B) a během dne jich můžete poslat jen pár.

Proč? Protože modem v síti Sigfox neudržuje stále spojení. To je ostatně poměrně typický jev i u ostatních IoT sítí, u kterých se klade maximální důraz na nízkou spotřebu. Maličký modem Wisol, který už si brzy vyzkoušíme ve spojení s Arduinem, tak v klidovém stavu nespotřebuje prakticky nic (ve spánku až 2μA). O pořádný kus energie si řekne až během odesílání zprávy (50-60 mA). Stále se však jedná o zlomek energie ve srovnání s GSM nebo třeba Wi-Fi.

Aby tedy mohl modem sám stáhnout nějaká data ze Sigfoxu, musí tento downlink iniciovat sám. V podstatě odešle klasickou zprávu, přičemž dá tentokrát síti vědět, že očekává i připravenou odpověď. Downlink se tedy hodí pro periodické (třeba každodenní) stahování nové konfigurace pro modem a mikropočítač, stažení přesného času pro seřízení RTC hodin aj.

Co se dá sakra vtěsnat do 12 bajtů?

Pro webového vývojáře, který je zvyklý na JSON, XML, CSV a další formáty textových dat bude znít 12bajtová zpráva jako hodně špatný vtip, ale 96 bitů není vůbec málo. V lednovém pokračování našeho seriálu jsem nastínil, jak lze i do mnohem menšího paketu vtěsnat třeba hromadu meteorologických údajů, pokud bychom Sigfox chtěli použít třeba pro meteosondu umístěnou kdesi na vrcholu Sněžky.

Teplotu v proměnné 32bitového reálného čísla (float) lze snadno převést na 16bitovou hodnotu při zachování přesnosti na dvě desetinná místa. Podobně můžeme pro transport zkrátit atmosférický tlak, pro vlhkost stačí jeden bajt a tak dále a tak dále. Stačí jen trošku optimalizovat.

Jak jednoduše šetřit bajty, když je to potřeba

Teplotu 20,2432°C lze uložit jako 32bitové reálné číslo (datový typ float). Pokud mi však bude stačit přesnost na dvě/tři desetinná místa, mohu hodnotu vynásobit 100 a převést na celé číslo. Nyní tedy bude mít proměnná s teplotou hodnotu 2 024 a mohu ji uložit jako 16bitové celé číslo, které má rozsah -32 768 až 32 767. Jednoduchým přepočtem jsem tedy zkrátil velikost proměnné na polovinu a získal k dobru celé dva bajty. Analogicky mohu pokračovat i v dalších případech.

Převádíme napětí na 3,3 V

Pojďme si to tedy konečně celé vyzkoušet v akci se zmíněným maličkým a levným modemem Wisol, který připojíme k Arduinu. Většina Arduin běží v 5V pracovním napětí, nicméně Wisol očekává napájení v rozsahu 1,8V-3,6V a to se týká i jeho RX a TX pinů pro komunikaci přes sériovou linku (Přinejmenším krátkodobě unese i 5V, rozhodně byste jej neměli hned zničit).

993813666 674525340
Převodník napětí na logice: Upraví datovou komunikaci RX/TX z 5V Arduina na 3V modem, takže se nemusím obávat, že jej poškodím.

Jelikož jsem žádné 3,3V Arduino zrovna neměl po ruce, sáhl jsem po klasickém základním modelu Arduino Uno (5V) a použil napěťový převodník (logic level converter). Drobný modul za pár korun, nabízí zpravidla čtyř kanály, přičemž z jedné strany připojíte vyšší referenční napětí (5V), z druhé to požadované nižší (3,3V) a adekvátně se pak promění i napětí na jednotlivých kanálech.

676690005 362289470 727551605
Sigfoxový modem bude na server odesílat data z luxmetru BH1750 a tlakoměru/vlhkoměru/teploměru BME280 (oba na sběrnici I2C). O běh se postará 5V Arduino Uno, k převodu sériové komunikace na 3V modem proto používám logic level converter na obrázku uprostřed.

Hromada AT příkazů odhalí třeba schovaný teploměr v čipu

Jak už jsem napsal výše, sigfoxové modemy se ovládají pomocí sériové linky a AT příkazů, kterým jsme se už v našem seriálu také věnovali, když jsme si hráli s GSM modemem.

Piny RX (příjem) a TX (vysílání) na modemu tedy stačí křížově propojit s TX a RX piny na Arduinu (anebo na jiné GPIO piny s využitím knihovny SoftwareSerial), a pak v programu otevřít sériové spojení při rychlosti 9600 bps.

Pokud bude vše v pořádku, modem na dotaz AT odpoví OK.

Abychom tedy mohli poslat zprávu do Sigfoxu, musíme nejprve znát ovládací AT příkazy. Kde je získat? V nitru modulu Wisol je schovaný 868MHz vysílač AX-SFEU-1-01, jehož sada AT příkazů je opravdu velmi bohatá a najdete ji v tomto PDF dokumentu.

949084708
Některé informační AT příkazy, které modem podporuje. Teploměr uvnitř čipu je kupodivu poměrně přesný a voltmetr se může hodit pro sledování stavu baterie, pokud jej bude napájet.

Modem toho umí mnohem více, než jen odeslat zprávu. Uvnitř je třeba i docela slušný teploměr, který čip používá pro nejrůznější korekce. Aktuální teplotu se dozvíte příkazem AT$T?, jenž odpoví třeba hodnotou 2014 (tedy 20,14 °C). Příkaz AT$V? zase sdělí informaci o aktuálním napětí a pak tu jsou desítky příkazů pro kompletní ovládání několika rozšiřujících GPIO pinů na modemu, ADC převodníku aj.

Wisole, pošli zprávu!

Nás však zajímá komunikace. Pokud bude modem patřičně zaregistrovaný v systému a v dosahu signálu, stačí po připojení k Arduinu nebo počítači přes UART převodník zadat tento příkaz:

AT$SF=010FFF\r

Hlavičkou AT$SF= dáváme modemu najevo, že chceme poslat zprávu. Ta následuje hned poté, a jak jste si jistě všimli, jedná se o tři bajty 01, 0F a FF zapsané v šestnáctkové soustavě. Celý příkaz (stejně jako všechny ostatní) je pak třeba uzavřít řídícím znakem \r pro posun pozice kurzoru na začátek.

Jakmile modem zprávu během několika sekund odešle, napíše do sériové linky opět OK. V ten okamžik se také zpráva objeví ve webovém rozhraní Sigfoxu.

Kdybych zprávu trošku opravil a poslal příkaz:

AT$SF=010FFF,1\r

Jednička na konci dává systému vědět, že očekávám onen downlink a tedy 8 bajtů. Jakmile je modem získá, opět je vypíše do sériové linky, ačkoliv v tomto případě to může trvat až půl minuty.

Po úspěšném odeslání zprávy mohu modem přepnout do úsporného režimu:

AT$P=1\r

Ze kterého se modem asi do 1 s probudí, pokud mu přes sériovou linku pošlu jakýkoliv znak.

Anebo:

AT$P=2\r

Který přepne modem do hlubokého spánku a je třeba jej probudit třeba změnou napětí na jeho pinu RESET.

Takže si to shrňme. Zpráva může mít nejvýše 12 bajtů a modemu ji předávám v šestnáctkové soustavě. Z pohledu Arduina tedy stačí vytvořit pole o délce 12 bajtů, zkopírovat do něj proměnné, které chceme odeslat, a pak převést jednotlivé bajty na hexadecimální zápis a konečně vše odeslat.

Tak a teď kód sigfoxové meteostanice

Takto by mohl vypadat jednoduchý program pro Arduino, který na povel odešle skrze Sigfox údaje o teplotě, tlaku, vlhkosti a intenzitě světla.

924131826
Komentovaný program níže bude každé dvě sekundy do sériové linky vypisovat teplotu, tlak a vlhkost vzduchu z kombinovaného senzoru BME280 a intenzitu světla z luxmetru BH1750. Pokud Arduinu pošlu znak 1, vytvoří z těchto hodnot 7B zprávu a odešle ji skrze síť Sigfox.

Zpráva se skrze Sigfox odešle na ruční povel, stejně tak by se ale mohla odesílat třeba každých 15 minut s tím, že po zbytek času by se Arduino i modem přepnuly do úsporného režimu, aby je mohla pohánět baterie. Práci s úsporným režimem, kdy jsme Arduino probouzeli v přesně daný čas pomocí externích RTC hodin, jsme si už našem seriálu také vyzkoušeli.

/*
  V tomto prikladu odeslu pres Sigfox udaj z luxmetru BH1750 a
  teplotu, tlak a vlhkost ze senzoru BME280. K tomu potrebuji
  nasledujici knihovny.
*/
#include <Wire.h>
#include <BH1750.h>
#include <cactus_io_BME280_I2C.h>
#include <SoftwareSerial.h>

//TX a RX piny Wisolu pripojim na digitalni piny Arduina 2 a 3
SoftwareSerial sigfox(2, 3);

// Senzory luxmetru a tlakomeru
BH1750 luxmetr;
BME280_I2C bme(0x76);

// Promenne pro hodnoty z cidel
uint16_t svetlo = 0;
float tlak = 0;
float teplota = 0;
uint8_t vlhkost = 0;

// Funkce setup se zpracuje po spusteni Arduina
void setup() {
  // Start seriove linky do PC
  Serial.begin(9600);
  // Start seriove linky do modemu Wisol
  sigfox.begin(9600);

  // Start jednotlivych senzoru
  luxmetr.begin();
  bme.begin();
  bme.setTempCal(-2);

  // Nastaveni systemove LED diody, ktera se rozsviti pri odesilani dat
  pinMode(13, OUTPUT);
}

// Smycka loop se opakuje stale dokola
void loop() {
  /*
    Pokud v PC v seriovem terminalu odeslu Arduinu znak '1',
    modem Wisol odesle zpravu s hodnotami
  */
  while (Serial.available()) {
    char c = Serial.read();
    if (c == '1') {
      // Pokud se zprava odeslala, napis to do seriove linky
      if (odesliZpravu()) {
        Serial.println("Zprava uspesne odeslana!");
      }
      // Pokud pri odesilani nastala chyba, napis to do seriove linky
      else {
        Serial.println("Zpravu se nepodarilo odeslat!");
      }
    }
  }

  // Ziskej hodnotu z luxmetru a tlakomeru/vlhkomeru/teplomeru
  svetlo = luxmetr.readLightLevel();
  bme.readSensor();
  tlak = bme.getPressure_MB();
  teplota = bme.getTemperature_C();
  vlhkost = bme.getHumidity();

  // Vypis hodnoty do seriove linky na PC
  Serial.print(teplota); Serial.print("st.C ");
  Serial.print(tlak); Serial.print("hPa ");
  Serial.print(vlhkost); Serial.print("% ");
  Serial.print(svetlo); Serial.println("lx");

  // Pockej 2 sekundy a vse opakuj
  delay(2000);
}

// Funkce pro odeslani zpravy pres modem Sigfox
bool odesliZpravu() {
  // Navratova hodnota funkce
  bool retval = false;
  // Rozsvit systemovou LED diodu na Arduinu
  digitalWrite(13, HIGH);
  // Nase zprava bude 7 B dlouha, takze si pripravim pole
  uint8_t zprava[7];
  // Uloz cas, abychom mohli merit, jestli odesilani netrva dlouho
  long start = millis();
  // Znaky pro hexadecimalni vyjadreni jednotlivych bajtu
  char hexBajt[3];

  // Prevod 32bitove teploty na 16bitovou
  int16_t teplota16 = teplota * 100;
  // Prevod 32bitoveho tlaku na 16bitovy
  uint16_t tlak16 = (tlak - 900) * 100;

  //Zkopirovani teploty, tlaku, vlhkosti a svetla do pole zpravy
  memcpy(&zprava[0], &teplota16, 2);
  memcpy(&zprava[2], &tlak16, 2);
  memcpy(&zprava[4], &vlhkost, 1);
  memcpy(&zprava[5], &svetlo, 2);

  // Odeslani zpravy pres seriovou linku do modemu Sigfoxu
  Serial.println("Posilam zpravu...");
  sigfox.print("AT$SF=");
  // Projdu pole bajt po bajtu
  for (int i = 0; i < sizeof(zprava); i++) {
    // Pomoci funkce sprintf prevedu bajt na hexadecimalni zapis
    sprintf(hexBajt, "%02X", zprava[i]);
    // Poslu hexadecimalni podobu bajtu do modemu a pokracuji
    sigfox.print(hexBajt);
  }
  // Cela zprava je odeslana, a tak ji uzavru znakem \r
  sigfox.print("\r");

  // Nyni blokuji program, dokud od modemu nedostanu odpoved
  while (!sigfox.available()) {
    // Pokud ani po 30 s nedostanu odpoved, vratim chybu
    if ((millis() - start) > 30000) {
      // Vypni systemovou LED na Arduinu
      digitalWrite(13, LOW);
      return false;
    }
  }

  // Hura, dostal jsem od modemu nejakou odpoved
  while (sigfox.available()) {
    // Vypni systemovou LED na Arduinu
    digitalWrite(13, LOW);
    // Precti znaky odpovedi modemu
    char odpoved = sigfox.read();
    // Pokud je to 'O' (modem odpovedel 'OK'), vse probehlo v poradku
    if (odpoved == 'O') retval = true;
  }

  // Ukoncim funkci a vratim vysledek
  return retval;
}

Data jsou na serveru Sigfoxu, ale co teď?

Jedna věc je odeslat oněch pár bajtů na server Sigfoxu, ale co pak s nimi dál? Zde budete muset nastavit tzv. callback, který se zpracuje pokaždé, jakmile z vybraného modemu dorazí další zpráva a data přepošle konečně do cíle. Síť podporuje nejrůznější aplikační platformy od Amazonu a Microsoftu (AWS IoT, Azure IoT Hub), ale nechybí ani e-mail a hlavně HTTP GET a POST.

208332351
Jakmile zpráva z našeho programu pro Arduino docestuje do centrály Sigfoxu, objevím ji v administraci svého modemu

Takže když dorazí třeba hexadecimální zpráva FB07D61E270300, systém ji může okamžitě přeposlat na můj web buď jako HTTP GET v parametru adresy (třeba https://kloboukuv.cloud/sfx2db.php?raw=FB07D61E270300​), anebo v těle hlavičky HTTP POST.

Sigfox ale nabízí i vlastní dekodér, který šestnáctkový zápis rozloží na původní proměnné, což mi ušetří čas. Služba k tomu ve webové administraci používá speciální sadu maker, pomocí kterých dekodéru sdělím, co které bajty znamenají.

Takže řadu 7 bajtů:

FB 07 D6 1E 27 03 00

Mohu popsat jako:

teplota::int:16:little-endian tlak::uint:16:little-endian vlhkost::uint:8 svetlo::uint:16:little-endian

Přeloženo do lidštiny:

Prvních 16 bitů (FB 07) je celé číslo se znaménkem a bude to proměnná teplota. Dalších 16 bitů (D6 1E) je tlak, následuje 8 bitů (27) pro vlhkost vzduchu a vše uzavírá 16 bitů (03 00) pro intenzitu světla v luxech.

992545718 36109272
Dekodér pro příchozí hexadecimální zprávu a výsledek. Předchozí nicneříkající výpis se rázem proměnil a pod surovou zprávou nyní vidím i jednotlivé proměnné. Že se jedná o podivné hodnoty? Nezapomeňte, že jsem 32bitová čísla s desetinnou částí přepočítal na 16bitová celá čísla, abych ušetřil drahocenné bajty, takže je musím v definitivním cíli přepočítat zpět.

Proměnné, které jsem na Arduinu složil do kompaktního pole bajtů a převedl na hexadecimální text, mi tedy dokáže zpět na jednotlivé proměnné rozložit přímo Sigfox a na cílový web pak data pošle jako běžné parametry URL, které snadno zpracuji třeba i v Javascriptu.

https://kloboukuv.cloud/sfx2db.php?t={customData#teplota}&p={customData#tlak}&h={customData#vlhkost}&l={customData#svetlo}

138187699 127840352 440196583
Konečným cílem může být třeba databázový server. Takto mi ze soboty na neděli Sigfox zaznamenal intenzitu světla a postupnou spotřebu lithiové baterie, která napájela jak modem, tak Arduino Uno, které periodicky usínalo na 15 minut.

Bitva o IoT teprve začne

Takhle tedy z vývojářského hlediska vypadá stručná rozborka jedné z mnoha mobilních sítí pro internet věcí. Sigfox není jediný a na scéně se objevují další podobné technologie (LoRa, ČRa, Things.cz aj.). Jejich potřeba postupně poroste, protože se bude zvyšovat i počet autonomních krabiček všude kolem nás, které budou periodicky vysílat.

Na rozdíl od Wi-Fi ale v tomto případě nepůjde o rychlost a množství dat, ale právě o to, aby systém dokázal v reálném čase zpracovat miliony a miliardy podobných kratičkých stavových zpráv ze senzorů rozesetých napříč městy i venkovem a to s podmínkou, že to musí být celé maximálně energeticky úsporné.

Mobilní sítě pro IoT tedy mají úplně jiný charakter než třeba 3G, Wi-Fi a Bluetooth a je s nimi třeba do budoucna počítat i při výstavbě klasické mobilní infrastruktury. I proto se na podobný IoT messaging myslí při vývoji specifikace pro další generaci mobilních sítí 5G.

Diskuze (21) Další článek: Simulace ukáže, jak by dopadl jaderný útok na New York

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