Let’s PI: Zero to IoT

Apariția Raspberry Pi Zero a făcut disponibile funcționalitățile familiei Raspberry Pi la o dimensiune și un cost mult mai mici. La jumătatea dimensiunii unei plăci obișnuite Raspberry Pi, varianta Zero oferă un microprocesor BCM2835 la 1GHz frecvență de funcționare, 512MB memorie RAM, ieșire video mini HDMI, port micro USB OTG, conector cameră și toate facilitățile oferite de sistemul de operare Raspbian.

Singura problemă pentru a utiliza această variantă a plăcii Raspberry Pi este conectivitatea de rețea. Fără a apela la versiunea Zero W, ce oferă conectivitate WiFi, putem utiliza placa Raspberry Pi Zero în proiecte IoT fără nici un fel de problemă. Este recomandată achiziționarea unui kit ce include adaptoarele HDMI – mini HDMI și micro USB OTG – USB precum și bareta de pini deoarece ele sunt absolut necesare în utilizarea plăcii Raspberry Pi Zero. Pentru punerea în funcțiune mai sunt necesare și un card microSD pentru sistemul de operare, se recomandă un card de calitate, și un alimentator de 5V.

După copierea imaginii sistemului de operare pe cardul de memorie avem următoarele opțiuni pentru interacțiunea cu placa Raspberry Pi Zero:

  • Conectăm placa la un monitor cu intrare HDMI (prin intermediul adaptorului mini HDMI – HDMI) și la o tastatură USB (prin intermediul adaptorului micro USB – USB). Această variantă de utilizare ne permite utilizarea plăcii de dezvoltare dar nu oferă nici o facilitate de conectare la Internet.
  • Conectăm, prin intermediul adaptorului micro USB – USB, o placă de rețea USB. Interacțiunea cu placa Raspberry Pi Zero se va face în linie de comandă prin intermediul protocolului SSH (utilizând programul PUTTY de exemplu). Majoritatea plăcilor de rețea, mai ales cea indicată, vor fi văzute în mod automat de sistemul de operare Raspbian și nu vor necesita nici o operație de instalare / configurare suplimentară. Pentru a activa serviciul SSH încă de la prima pornire a plăcii este necesară creare unui fișier gol cu numele ssh pe cardul pe care copiem sistemul de operare (a se vedea și „Enable SSH when creating SD card”). Bineînțeles, se poate utiliza un adaptor de rețea WiFi în locul celui Internet dar probabilitatea ca acest tip de adaptoare să necesite operații suplimentare de instalare / configurare este mai mare, cu alte cuvinte nu ne vom putea conecta din prima la placă fără tastatură și monitor.
  • Este posibilă combinarea celor două soluții anterioare dar este necesară utilizarea unui hub USB – placa de dezvoltare are un singur port USB OTG și este necesară conectarea tastaturii și a adaptorului de rețea. Este o soluție ce complică destul de mult utilizarea plăcii, este de preferat achiziționarea unei plăci Raspberry Pi 3.

Vom exemplifica realizarea sistemului IoT utilizând cea de a doua opțiune: placa Raspberry Pi Zero, adaptor micro USB – USB și placă de rețea USB. Ca serviciu IoT vom utiliza serviciul gratuit Robofun IoT iar datele raportate vor proveni de la un senzor digital de temperatură și umiditate SHT11. Conectarea dintre senzorul digital și placa de dezvoltare se face în felul următor:

3

Senzorul se va alimenta la 3.3V, pinul SCK se va conecta la pinul 23 iar pinul DAT la pinul 18. Pentru configurarea și scrierea programului IoT ne vom conecta la placa Raspberry Pi Zero prin SSH utilizând Putty. Este recomandată aducerea la zi a pachetelor software:

# sudo apt-get update

# sudo apt-get upgrade

Programul va fi scris în limbajul Python și va utiliza biblioteca pi-sht1x, pentru instalarea acesteia vom executa:

# sudo apt-get install python3-pip

# pip3 install pi-sht1x

Testele au fost realizate sub Raspbian 9, kernel 4.14.34+, Python 3.5.3 și pi-sht1x 1.0.9. Programul utilizat este următorul (PiZeroIoT.py):

import RPi.GPIO as GPIO

from pi_sht1x import SHT1x

import urllib.request

DATA_PIN = 18

SCK_PIN = 23

with SHT1x(DATA_PIN, SCK_PIN, gpio_mode=GPIO.BCM) as sensor:

temp = sensor.read_temperature()

humidity = sensor.read_humidity(temp)

SENSOR1_TOKEN="…"

SENSOR2_TOKEN="…"

urllib.request.urlopen("http://iot.robofun.ro/api/v1/senzor/"+SENSOR1_TOKEN+"/input?value="+str(temp)).read()

urllib.request.urlopen("http://iot.robofun.ro/api/v1/senzor/"+SENSOR2_TOKEN+"/input?value="+str(humidity)).read()

Variabilele SENSOR1_TOKEN și SENSOR2_TOKEN trebuie completate cu datele obținute în urma definirii a doi senzori în cadrul platformei Robofun IoT. Pentru a executa programul în mod automat la anumite intervale de timp vom crea o intrare în fișierul de configurare a serviciului cron (/etc/crontab) de forma (execuție la 10 minute):

*/10 *  * * *   pi      python3 /home/pi/PiZeroIoT.py

După repornirea sistemului, fără a ne conecta la placă, programul se va executa în mod automat și vom putea vedea graficele pentru temperatură și umiditate în interfața serviciului IoT:

4

5

Hunting the Heat

Măsurarea temperaturii este o operație simplă de achiziție din punct de vedere al unui sistem electronic. Monitorizarea temperaturii însă ridică câteva provocări cu privire la înregistrarea datelor și vizualizarea acestora. În cadrul proiectului de față vom da exemplu de două soluții de monitorizare a temperaturii prin intermediul unui serviciu de cloud.

Pentru trimiterea datelor în cloud vom utiliza placa de dezvoltare Adafruit Feather HUZZAH bazată pe microprocesorul WiFi ESP8266. Prima variantă de monitorizare va utiliza sensorul digital de temperatură și umiditate SHT11 – o soluție de precizie recomandată când dorim să monitorizăm temperatura din aer (ambientală). Din punct de vedere al confortului termic monitorizarea temperaturii trebuie însoțită de monitorizarea umidității din aer. Schema de interconectare dintre placa de dezvoltare și senzor este următoarea:

2

Senzorul se va alimenta la 3.3V iar liniile de comunicație se vor conecta la pinii 13 (pinul DAT al senzorului) și 15 (pinul SCK al senzorului) ai plăci de dezvoltare. Pentru intergrarea plăcii de dezvoltare în mediul Arduino IDE este necesară parcurgerea materialului „Adafruit Feather HUZZAH – WiFi with built-in battery charging for IoT on-the-go!”.

Ca serviciu de monitorizare în cloud vom utiliza serviciul Robofun IoT. Pentru utilizarea acestuia este necesară înregistrarea gratuită.

4

După înregistrare și conectare este necesară definirea a doi noi senzori (Adauga senzor) pentru a putea înregistra cele două valori măsurate (temperatură și umiditate).

5

După definirea celor doi senzori este necesar să copiem cheile de autentificare (Token) pentru a le utiliza în program.

3

Programul a fost dezvoltat și testat utilizând Arduino IDE 1.8.3 cu extensia esp8266 2.3.0 instalată și biblioteca SHT1x commit be7042c. În cadrul programului trebuie personalizate datele de conectare WiFi (ssid și pass) precum și cheile de autentificare oferite de procesul de înregistrare a senzorilor pe platforma Robofun IoT (SENSOR_TOKEN1 și SENSOR_TOKEN2).

#include <ESP8266WiFi.h>

#include <ESP8266HTTPClient.h>

char ssid[] = ““;    

char pass[] = ““;   

WiFiClient client;

#include <SHT1x.h>

#define dataPin  13

#define clockPin 15

SHT1x sht1x(dataPin, clockPin);

void setup() {

  Serial.begin(9600);

  delay(10);

  Serial.println();

  Serial.println();

  Serial.print(“Connecting to “);

  Serial.println(ssid);

  WiFi.begin(ssid, pass);

    while (WiFi.status() != WL_CONNECTED) {

    delay(500);

    Serial.print(“.”);

  }

  Serial.println(“”);

  Serial.println(“WiFi connected”); 

  Serial.println(“IP address: “);

  Serial.println(WiFi.localIP());

}

unsigned long lastConnectionTime = 0;

const unsigned long postingInterval = 60L * 1000L;

void loop() {

  if (millis() – lastConnectionTime > postingInterval) {

    IoTpublish();

  }

}

void IoTpublish() {

  String SENSOR_TOKEN1=”“;

  String SENSOR_TOKEN2=”“;

  float temp_c;

  float humidity;

  temp_c = sht1x.readTemperatureC();

  humidity = sht1x.readHumidity();

  Serial.print(“Temperature: “);

  Serial.print(temp_c, DEC);

  Serial.print(“C “);

  Serial.print(” Humidity: “);

  Serial.print(humidity);

  Serial.println(“%”);

   HTTPClient http;

  String data = String(“http” + “://iot.robofun.ro/api/v1/senzor/”) + SENSOR_TOKEN1 + “/input?value=” + String(temp_c, DEC);

  http.begin(data);

  int httpCode = http.GET();

  http.end();

  data = String(“http” + “://iot.robofun.ro/api/v1/senzor/”) + SENSOR_TOKEN2 + “/input?value=” + String(humidity, DEC);

  http.begin(data);

  httpCode = http.GET();

  http.end();

  lastConnectionTime = millis();

}

După încărcarea programului și punerea în funcțiune a sistemului putem monitoriza on-line valorile măsurate:

3

4

Cea de a doua variantă propusă pentru monitorizarea temperaturii este specifică monitorizării temperaturii materialelor și spațiilor de echipamente. Pentru măsurarea temperaturii vom utiliza senzorul digital DS18B20 ce permite realizarea unei rețele de senzori pe o magistrală cu un singur fir (1-Wire) facilitând astfel supravegherea temperaturii în mai multe puncte. Vom utiliza un modul brick DS18B20 ca prim element în rețeaua de senzori și mai mulți sensori DS18B20+ pentru diverse puncte de supraveghere.

Soluția bazată pe comunicația 1-Wire a fost aleasă pentru distanța mare la care pot fi plasați senzorii față de placa de dezvoltare (aproximativ 200 de metri) și a unui număr mare de senzori care pot fi conectați simultan (având în vedere faptul că fiecare senzor are o adresă proprie din fabricație pe 64 de biți nu există o limitare de protocol privind numărul de senzori dintr-o rețea). A se vedea și: „Guidelines for Reliable Long Line 1-Wire Networks”.

Prin intermediul rețelei de senzori DS18B20 sistemul va putea monitoriza din punct de vedere al măsurării temperaturii un număr ”nelimitat” de zone. Conectarea cu placa de dezvoltare implică conectarea componentei brick în felul următor: pinul GND al modulului la pinul de GND al plăcii de dezvoltare, pinul 5V la pinii de 3V al plăcii de dezvoltare (senzorii DS18B20 acceptă alimentare de la 3V la 5.5V) și pinul DQ al modulului la pinul 3 al plăcii de dezvoltare. Următorii senzori atașați în rețea se vor conecta la modulul brick prin intermediul conectorului cu șurub respectând semnificația pinilor.

5

Programul a fost dezvoltat și testat utilizând Arduino IDE 1.8.3 cu extensia esp8266 2.3.0 instalată și bibliotecile OneWire 2.3.3 și DallasTemperature 3.7.6. În cadrul programului trebuie personalizate datele de conectare WiFi (ssid și pass) precum și cheile de autentificare oferite de procesul de înregistrare a senzorilor pe platforma Robofun IoT (vectorul SENSOR_TOKEN).

#include <ESP8266WiFi.h>

#include <ESP8266HTTPClient.h>

char ssid[] = ““;    

char pass[] = ““;   

WiFiClient client;

#include <DallasTemperature.h>

#include <OneWire.h>

#define ONE_WIRE_BUS 2

#define MAX_ATTACHED_DS18B20 10

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

int numSensors=2;

void setup() {

  sensors.begin();

  delay(100);

  Serial.begin(9600);

  delay(100);

  Serial.println();

  Serial.println();

  Serial.print(“Connecting to “);

  Serial.println(ssid);

  WiFi.begin(ssid, pass);

    while (WiFi.status() != WL_CONNECTED) {

    delay(500);

    Serial.print(“.”);

  }

  Serial.println(“”);

  Serial.println(“WiFi connected”); 

  Serial.println(“IP address: “);

  Serial.println(WiFi.localIP());

}

unsigned long lastConnectionTime = 0;

const unsigned long postingInterval = 60L * 1000L;

void loop() {

  if (millis() – lastConnectionTime > postingInterval) {

    IoTpublish();

  }

}

void IoTpublish() {

  String SENSOR_TOKEN[] = {““,”“};

  HTTPClient http;

  Serial.print(“Requesting temperatures…”);

  sensors.requestTemperatures();

  Serial.println(“DONE”);

  for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++)  {

    float temperature = sensors.getTempCByIndex(i);

    Serial.print(“Temperature for the device “); Serial.print(i); Serial.print(” is: “);

    Serial.println(temperature); 

    String data = String(“http” + “://iot.robofun.ro/api/v1/senzor/”) + SENSOR_TOKEN[i] + “/input?value=” + String(temperature, DEC);

    http.begin(data);

    int httpCode = http.GET();

    if(httpCode > 0) {

      Serial.printf(“[HTTP] GET… code: %d\n”, httpCode);

      if(httpCode == HTTP_CODE_OK) {

        String payload = http.getString();

        Serial.println(payload);

      }

      } else {

      Serial.printf(“[HTTP] GET… failed, error: %s\n”,

             http.errorToString(httpCode).c_str());

      }

    http.end();

  }

  lastConnectionTime = millis();

}

Programul va prezenta în consolă desfășurarea procesului de achiziți și înregistrare cloud (exemplificare cu doi senzori conectați):

6

dar monitorizarea se va face online:

7

8