Pedometru IoT

Dispozitivele de tip pedometru (dispozitive ce contorizează numărul de pași) sunt din ce în ce mai populare. La acest lucru a condus pe de o parte scăderea prețului dispozitivelor electronice dar și necesitatea psihologică de a avea un ”martor” la eforturile personale de a ne menține în formă. Pedometrele variază ca funcționalitate de la simple dispozitive ce afișează pe un ecran numărul de pași până la dispozitive ce raportează prin protocoale fără fir către telefon sau tabletă numărul de pași permițând astfel generarea de rapoarte pe diverse intervale de timp și chiar clasamente între mai multe persoane.

În cadrul proiectului de față vă propunem implementarea unui dispozitiv de tip pedometru ce raportează numărul de pași prin Internet către serviciul cloud Robofun IoT. Serviciul cloud Robofun IoT este gratuit și permite înregitrarea și vizualizarea datelor prin intermediul unei interfețe web, pentru mai multe detalii puteți consulta documentația oficială a serviciului.

Există mai multe exemple de proiecte ce își propun implementarea funcționalității de pedometru dar nu și funcționalitatea de înregistrare online a datelor. Totuși, putem parcurg câteva astfel de proiecte pentru a înțelege diverse soluții de implementare: „Arduino Pedometer”, „Simple, Easy and Cheap DIY Pedometer With Arduino”, „Arduino Pedometer Watch, With Temperature, Altitude and Compass!”.

Dispozitivul prezentat va utiliza, pentru a putea sesiza fenomenul de ”pas”, un accelerometru digital ADXL345. Analiza fenomenelor fizice implicate (accelerații, recunoașterea tiparului generat de efectuarea unui pas) nu fac subiectul acestei lecții dar recomandăm parcurgerea suplimentară a următorului material: „Full-Featured Pedometer Design Realized with 3-Axis Digital Accelerometer”.

Partea de achiziție a datelor și de comunicație în rețea va fi asigurată de o placă de dezvoltare Sparkfun ESP32 Thing – placă echipată cu microprocesorul ESP32 de la Espressif ce asigură conectivitate WiFi și BLE (chiar dacă dispozitivul prezentat exemplifică doar partea de conectivitate WiFi asta nu înseamnă că acesta nu poate fi dezvoltat suplimentar pentru a putea asigura conectivitate BLE cu dispozitive mobile de tip telefon sau tabletă). Pe lângă puterea de procesare și conectivitatea WiFi placa de dezvoltare oferă avantajul de a funcționa alimentată de la un acumulator LiPo de 3.7V permițând astfel ca sistemul să fie portabil.

Schema de interconectare între placa de dezvoltare și accelerometru este următoarea (accelerometrul se va alimenta la 3.3V, pinul SDA se va conecta la pinul 21 al plăcii de dezvoltare iar SCL la pinul 22, pinul CS se va conecta la 3.3V iar SD0 la GND):

2

Pentru integrarea plăcii Sparkfun ESP32 Thing în mediul Arduino IDE este necesar să parcurgeți materialul „ESP32 Thing Hookup Guide” deoarece sunt necesare operații manuale de copiere și instalare a utilitarelor aferente.

Programul va utiliza, pentru detecția numărului de pași, bibliotecile Pedometer și Accelerometer_ADXL345 a celor de la Seeed-Studio.

Programul a fost dezvoltat și testa utilizând Arduino IDE 1.8.3. În program trebuie personalizate datele de conectare la rețeaua WiFi (networkName și networkPswd).

#include <WiFi.h>

#include “pedometer.h”

#include <ADXL345.h>

Pedometer pedometer;

#include <Wire.h>

const char * networkName = ““;

const char * networkPswd = ““;

const char * hostDomain = “iot.robofun.ro”;

const int hostPort = 80;

const int BUTTON_PIN = 0;

const int LED_PIN = 5;

În cadrul secțiunii setup() se vor realiza inițializările necesare. Placa de dezvoltare are integrate un led (pinul 5) și un buton (pinul 0). Ledul va indica (se va aprinde) activitățile de rețea din program (conectare AP, postare IoT) iar butonul va fi utilizat pentru a reseta numărul de pași efectuați.

void setup() {

  Serial.begin(115200);

  pinMode(BUTTON_PIN, INPUT_PULLUP);

  pinMode(LED_PIN, OUTPUT);

  digitalWrite(LED_PIN, HIGH);

  pedometer.init();

  connectToWiFi(networkName, networkPswd);

  digitalWrite(LED_PIN, LOW); }

Constanta INTERVAL va indica perioda de timp (în milisecunde) la care se va face transmiterea numărului de pași efectuați către serviciul IoT.

#define INTERVAL 60000

unsigned long lastPost = 0;

void loop() {

  if (digitalRead(BUTTON_PIN) == LOW)

pedometer.stepCount = 0;

  if((millis() – lastPost) > INTERVAL) {

    digitalWrite(LED_PIN, HIGH);

    if (WiFi.status() != WL_CONNECTED)

connectToWiFi(networkName, networkPswd);

    requestURL(hostDomain, hostPort);

    digitalWrite(LED_PIN, LOW);

    lastPost = millis();

  }

  delay(10);

}

Procedura connectToWiFi() este responsabilă cu conectarea la rețeaua WiFi.

void connectToWiFi(const char * ssid, const char * pwd)

{ int ledState = 0;

  Serial.println(“Connecting to WiFi network: ” + String(ssid));

  WiFi.begin(ssid, pwd);

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

    digitalWrite(LED_PIN, ledState);

    ledState = (ledState + 1) % 2;

    delay(500);

    Serial.print(“.”);

  }

  Serial.println();

  Serial.println(“WiFi connected!”);

  Serial.print(“IP address: “);

  Serial.println(WiFi.localIP());

}

Procedura requestURL() este responsabilă cu postarea către serviciul IoT. În cadrul acesteia trebuie completată valoarea cheii de autentificare (TOKEN) obținute în urma înregistrării în cadrul serviciului Robofun IoT.

void requestURL(const char * host, uint8_t port) {

  Serial.println(“Connecting to domain: ” + String(host));

  WiFiClient client;

  if (!client.connect(host, port))  {

    Serial.println(“connection failed”);

    return;

  }

  Serial.println(“Connected!”);

  pedometer.stepCalc();

client.print((String)”GET /api/v1/senzor/TOKEN/input?value=” + String(pedometer.stepCount) + “HTTP/1.1\r\n” +  “Host: ” + String(host) + “\r\n” +  “Connection: close\r\n\r\n”);

  unsigned long timeout = millis();

  while (client.available() == 0)

  {

    if (millis() – timeout > 5000)

    {

      Serial.println(“>>> Client Timeout !”);

      client.stop();

      return;

    }

  }

  while (client.available())  {

    String line = client.readStringUntil(‘\r’);

    Serial.print(line);

  }

  Serial.println();

  Serial.println(“closing connection”);

  client.stop();

}

Sistemul va posta în mod automat numărul de pași la un interval de 10 minute. În cazul în care ieșim din aria de acoperire WiFi sistemul va contoriza în continuarea numărul de pași efectuați și la reîntoarcere va realua raportarea. Astfel vom putea evalua numărul de pași efectuați și ”în casă” și afară. Resetarea numărului de pași se va face apăsând butonul de pe pinul 0 al plăcii de dezvoltare.

3

IoT Power Monitor

Măsurarea consumului echipamentelor electronice este o preocupare continuă în domeniul monitorizării utilizării energiei electrice. Evoluția sistemelor IoT a făcut posibilă apariției unor echipamente de monitorizare a consumului ce raportează datele măsurate prin intermediul rețelei Internet direct către un serviciu cloud. În cadrul acestui proiect vom prezenta construcția unui astfel de sistem IoT de monitorizare a puterii electrice consumate.

Sistemul se va baza pe placa de dezvoltare LinkIt Smart 7688 Duo ce oferă o combinație extrem de puternică (asemănătoare și compatibilă software cu placa de dezvoltare Arduino Yun) între un microprocesor MediaTek MT7688 ce rulează sistemul de operare OpenWRT și un microcontroler ATmega32U4.

2

Pentru a utiliza conectivitatea de rețea oferită de componenta MT7688 este nevoie de configurarea conexiunii WiFi. Configurarea conexiunii WiFi necesită conectarea la AP-ul (Access Point) LinkIt_Smart_7688_XXXXXX (XXXXXX este un identificator specific fiecărei plăci în parte) cu ajutorul unui laptop sau un terminal inteligent WiFi (telefon inteligent, tabletă). După conectare se deschide cu ajutorul unui client web (browser) adresa http://192.168.100.1 sau http://mylinkit.local ce permite accesul la interfața de administrare a componentei MT7688 / a sistemului de operare OpenWRT. La prima conectare se va stabili și parola utilizatorului root (utilizator cu drepturi de administrator).

3

Modificările necesare conectării plăcii LinkIt Smart 7688 Duo la Internet presupun trecerea componentei WiFi din mod AP în mod client (Station mode) și configurarea conectării la un AP ce oferă conectivitate Internet. Ambele modificări se fac din secțiunea Network a interfeței de administrare.

4

5

Atenție!!! Nu introduceți placa de dezvoltare într-o subrețea 192.168.100.0/24 deoarece chiar și în modul client interfața AP cu adresa 192.168.100.1 este activă și o altă adresă IP din aceiași subrețea va deruta mecanismul de rutare TCP/IP.

După configurare accesului la Internet, placa se poate accesa prin intermediul interfeței web prezentată anterior sau prin intermediul protocolului SSH, utilizând IP-ul oferit de AP-ul configurat. Utilizatorul necesar conectării este root și parola stabilită anterior. Pentru mai mult informații legate de configurarea plăcii LinkIt Smart 7688 Duo se poate consulta și „Get Started with the LinkIt Smart 7688 Duo Development Board”.

A doua operație de configurare, necesară pentru a utiliza biblioteca Bridge (bibliotecă specifică plăcii Arduino Yun) sub mediul Arduino IDE, necesită conectarea la consola plăcii de dezvoltare LinkIt Smart 7688 Duo prin intermediul unui client SSH (putty (3), de exemplu) și executarea următoarelor comenzi:

uci set yunbridge.config.disabled=’0′ 

uci commit 

reboot

Pentru măsurarea consumului vom utiliza senzorul de curent INA219 – senzor digital I2C ce permite măsurarea de tensiuni de până la 26V și curenți de până la 3.2A cu o precizie de 1%. Interconectarea cu placa de dezvoltare se va face prin intermediul magistralei I2C:

6

Senzorul se va alimenta la 3.3V iar pinii SCL și SDA se vor conecta la pinii D3 respectiv D2 ai plăcii de dezvoltare. Pentru a putea măsura curentul și tensiunea este necesar să trecem linia de alimentare a dispozitivului electronic monitorizat prin senzor. Acest lucru se poate face prin secționarea firului de alimentare sau prin conectarea unei perechi de mufe jack mamă – tată care să permită conectarea mufei de alimentare la senzor și senzorul la dispozitivul electronic. ATENȚIE!!! Inserarea senzorului se face pe linia de tensiune nu pe cea de masă.

Având în vedere scopul de monitorizare IoT a sistemului realizat în cadrul lecției de față vom utiliza cloud Robofun IoT. Pentru utilizarea acestui serviciu este necesară înregistrarea gratuită.

4

După înregistrare și conectare este necesară definirea unui senzor (Adauga senzor) pentru a putea înregistra puterea măsurată.

5

După definirea senzorului este necesar să copiem cheia de autentificare (Token) pentru a o utiliza în program.

3

Programul a fost realizat și testat utilizând Arduino IDE 1.8.3 cu extensia LinkIt Smart 7688 Duo 0.1.8 instalată și biblioteca Adafruit INA219 1.0.0.

#include <Bridge.h>

#include <HttpClient.h>

#include <Wire.h>

#include <Adafruit_INA219.h>

Adafruit_INA219 ina219;

Decomentarea directivei #define debug va permite supravegherea mesajelor de funcționare în consola serială.

//#define debug

void setup(void) {

  #ifdef debug

    SerialUSB.begin(115200);

    while (!SerialUSB);

  #endif

  ina219.begin();

  Bridge.begin();

}

În cadrul secțiunii loop() este necesară completarea valorii TOKEN obținută în procesul de înregistrare a senzorului în platforma Robofun IoT.

void loop(void) {

  float shuntvoltage = 0;

  float busvoltage = 0;

  float current_mA = 0;

  float loadvoltage = 0;

  float power = 0;

  shuntvoltage = ina219.getShuntVoltage_mV();

  busvoltage = ina219.getBusVoltage_V();

  current_mA = ina219.getCurrent_mA();

  loadvoltage = busvoltage + (shuntvoltage / 1000);

  power = loadvoltage * current_mA;

  #ifdef debug

    SerialUSB.print(“Bus Voltage:   “);

   SerialUSB.print(busvoltage);

   SerialUSB.println(” V”);

    SerialUSB.print(“Shunt Voltage: “);

    SerialUSB.print(shuntvoltage);

   SerialUSB.println(” mV”);

    SerialUSB.print(“Load Voltage:  “);

   SerialUSB.print(loadvoltage);

   SerialUSB.println(” V”);

    SerialUSB.print(“Current:       “);

   SerialUSB.print(current_mA); 

   SerialUSB.println(” mA”);

    SerialUSB.print(“Power:       “);

   SerialUSB.print(power);

   SerialUSB.println(” mW”);

    SerialUSB.println(“”);

  #endif

  HttpClient client;

  String temp = “http: ” + “//iot.robofun.ro/api/v1/senzor/TOKEN/input?value=” + String(power,2);

  client.get(temp);

  while (client.available()) {

    char c = client.read();

    #ifdef debug

      SerialUSB.print(c);

    #endif

  }

  #ifdef debug

    SerialUSB.println();

    SerialUSB.flush(); 

  #endif

  delay(60000);

}

Programul va trimite la un interval de 1 minut (60 secunde = 60000 milisecunde) valoarea calculată (puterea instantanee) pe baza curentului și tensiunii măsurate.

Testele au fost realizate monitorizând un dispozitiv de tip router WiFi HUAWEI HG8247H alimentat la 12V DC (curent continuu).

Graficul de valori înregistrate pe ultima zi (toate datele) – se poate observa un consum constant de minim 6600mW (6.6W):

7

Graficul de valori înregistrate pe ultima săptămână (cu mediere) – se poate observa o variație a consumului între 6619mW și 6800mW:

8

IoT UV Monitor

Razele ultraviolete din lumina solară reprezintă un factor de risc pentru om. Monitorizarea nivelului de radiații UV (UV index) se face pe o scară de la 1 la 10 (11 fiind deja un nivel extrem). Realizarea unui sistem electronic ce măsoară cu precizie indexul UV poate oferi informații utile pentru modul în care putem să ne protejăm (îmbrăcăminte, ochelari de protecție, creme de protecție etc.) în activitățile de zi cu zi.

În cadrul proiectului de față vom realiza un sistem care să măsoare indexul UV și să înregistreze datele măsurate pe serviciul cloud Robofun IoT. Pentru utilizarea acestui serviciu este necesară înregistrarea gratuită.

4

După înregistrare și conectare este necesară definirea unui senzor (Adauga senzor) pentru a putea înregistra valorile măsurate (UV index).

5

După definirea senzorului este necesar să copiem cheia de autentificare (Token) pentru a o utiliza în program.

3

Pentru implementarea hardware vom utiliza o placă de dezvoltare Adafruit Feather 32U4 FONA și senzorul digital I2C Si1145. Schema de interconectare între cele două componente este:

2.png

Senzorul se va alimenta de la pinul BAT al plăcii de dezvoltare. Pinul SDA al senzorului se va conecta la pinul 2 al plăcii de dezvoltare iar pinul SCK la pinul 3. Atenție!!! Placa Adafruit Feather 32U4 FONA necesită conectarea unui acumulator LiPo de 3.7V chiar dacă este alimentată prin intermediul cablului USB de programare. Componenta GSM FONA se alimentează direct din acumulator nu din alimentarea USB. Pentru mai multe detalii legate de funcționarea plăcii Adafruit Feather 32U4 FONA se poate parcurge materialul „Adafruit Feather 32u4 FONA – Take your Feather anywhere in the world”.

Funcționarea sistemului necesită o cartelă GSM 2G cu capabilități de transfer de date. Pentru acest lucru vă propunem utilizarea unui SIM Simfony Mobile M2M – cartelă GSM ce oferă exclusiv servicii mobile de date. Cartela este disponibilă gratuit prin comandă promoțională pe site-ul companiei Simfony Mobile SRL sau împreună cu un produs din gama GSM pe site-ul Robofun. Cartela necesită înregistrarea și introducerea codului promoțional pentru activare și oferă gratuit 10MB de date mobile valabile 3 luni. Ulterior costurile de funcționare sunt de 0.25EURO, 0.5EURO, 1EURO pentru 1MB, 5MB respectiv 10MB trafic de date. Chiar dacă traficul inclus are valori modice pentru un sistem de raportare IoT este suficient iar costurile sunt rezonabile. O caracteristică importantă a cartelei SIM Simfony este indepența de un operator de telefonie anume, dispozitivul GSM ce utilizează cartela Simfony poate utiliza orice operator de telefonie mobilă în funcție de zona în care se află chiar și afara României.

3

Programul a fost dezvoltat și testat utilizând Arduino IDE 1.8.3 cu extensia Adafruit AVR Boards 1.4.9 instalată și bibliotecile Adafruit FONA Library 1.3.2 (pentru partea de comunicație cu componenta GSM FONA) și Adafruit SI1145 1.0.0 (pentru comunicația cu senzorul Si1145). În program este necesară completarea cheii de autentiricare (Token) oferite de serviciul cloud (variabila temp).

#include “Adafruit_FONA.h”

#define FONA_RX  9

#define FONA_TX  8

#define FONA_RST 4

#define FONA_RI  7

#define FONA_DTR 5

#define apn “internet.simfony.net”

#define apnusername “” 

#define apnpassword “” 

char replybuffer[255];

#include <SoftwareSerial.h>

SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);

SoftwareSerial *fonaSerial = &fonaSS;

Adafruit_FONA fona = Adafruit_FONA(FONA_RST);

uint8_t type;

#include <Wire.h>

#include “Adafruit_SI1145.h”

Adafruit_SI1145 uv = Adafruit_SI1145();

Decomentarea directivei #define debug va permite urmărirea funcționării sistemului în consola serială.

//#define debug

void setup() {

  #ifdef debug

    while (!Serial);

    Serial.begin(115200);

    Serial.println(“Initializing…”);

  #endif

  if (! uv.begin()) {

    #ifdef debug

      Serial.println(“Didn’t find Si1145”);

    #endif

    while (1);

  }

  digitalWrite(FONA_DTR,LOW);

  fonaSerial->begin(4800);

  if (! fona.begin(*fonaSerial)) {

    #ifdef debug

      Serial.println(F(“Couldn’t find FONA”));

    #endif

    delay(1);

    while (1);

  }

  #ifdef debug

    type = fona.type();

    Serial.println(F(“FONA is OK”));

    Serial.print(F(“Found “));

    switch (type) {

      case FONA800L:

        Serial.println(F(“FONA 800L”)); break;

      case FONA800H:

        Serial.println(F(“FONA 800H”)); break;

      case FONA808_V1:

        Serial.println(F(“FONA 808 (v1)”)); break;

      case FONA808_V2:

        Serial.println(F(“FONA 808 (v2)”)); break;

      case FONA3G_A:

        Serial.println(F(“FONA 3G (American)”)); break;

      case FONA3G_E:

        Serial.println(F(“FONA 3G (European)”)); break;

      default:

        Serial.println(F(“???”)); break;

    }

   #endif

   #ifdef debug

   char imei[15] = {0};

   uint8_t imeiLen = fona.getIMEI(imei);

   if (imeiLen > 0) {

      Serial.print(“Module IMEI: “); Serial.println(imei);

    }

   #endif

   fona.getSIMCCID(replybuffer); 

  #ifdef debug

    Serial.print(F(“SIM CCID = “));

Serial.println(replybuffer);

  #endif

  if (!fona.enableNetworkTimeSync(true)) {

     #ifdef debug

      Serial.println(F(“Failed to enable NTS”));

     #else

      ;

     #endif

  }

  delay(5000);

  fona.setGPRSNetworkSettings(F(apn),F(apnusername),

F(apnpassword));

  uint8_t n=0;

  #ifdef debug

    Serial.print(“Connecting to network.”);

  #endif

  while (n!=5) {

    n = fona.getNetworkStatus();

    #ifdef debug

      Serial.print(“.”);

    #endif

    delay(1000);

  }

  #ifdef debug

    Serial.println(“OK”);

  #endif

  #ifdef debug

    n = fona.getRSSI();

    int8_t r;

    if (n == 0) r = -115;

    if (n == 1) r = -111;

    if (n == 31) r = -52;

    if ((n >= 2) && (n <= 30)) { r = map(n, 2, 30, -110, –

54); }

    Serial.print(r); Serial.println(F(“dBm”));

  #endif

  delay(5000);

}

void loop() {

  while (!fona.enableGPRS(true)) {

    #ifdef debug

      Serial.println(F(“Failed to turn on GPRS”));

    #endif

    delay(5000);

  }

#ifdef debug

  uint16_t vbat;

  uint16_t pbat;

  if (fona.getBattVoltage(&vbat)) {

Serial.print(F(“VBat = “));

Serial.print(vbat); Serial.println(F(” mV”)); }

  if (fona.getBattPercent(&pbat)) {

Serial.print(F(“VPct = “));

Serial.print(pbat); Serial.println(F(“%”));   }

    Serial.println(“—————————“);

#endif

float UVindex = uv.readUV();

UVindex /= 100.0; 

#ifdef debug

    int light = uv.readVisible();

    Serial.print(“Vis: “); Serial.println(light);

    Serial.print(“UV: “);  Serial.println(UVindex);

#endif

String temp = “http” + “://iot.robofun.ro/api/v1/senzor/TOKEN/input?value=” + String(UVindex,2);

uint16_t statuscode;

int16_t length;

char url[100];

temp.toCharArray(url,temp.length()+1);

#ifdef debug

    Serial.println(url);

    if (!fona.HTTP_GET_start(url, &statuscode, (uint16_t*)&length)) Serial.println(“Failed read HTTP!”);

#else

    fona.HTTP_GET_start(url, &statuscode, (uint16_t*)&length);

#endif

while (length > 0) {

          while (fona.available()) {

            char c = fona.read();

            #ifdef debug

              Serial.write(c);

            #endif

            length–;

            if (! length) break;

          }

          #ifdef debug

            Serial.println();

          #endif

          break;

fona.HTTP_GET_end();

delay(100);

#ifdef debug

    Serial.println(“—————————-“);

    if (!fona.enableGPRS(false))

Serial.println(F(“Failed to turn off GPRS”));

#else

    fona.enableGPRS(false);

#endif

delay(100);

digitalWrite(FONA_DTR,HIGH);

delay(600000);

digitalWrite(FONA_DTR,LOW);

}

Programul va citi valorile indexului UV și va înregistra datele on-line la un interval de 10 minute (60 secunde = 60000 milisecunde). Intervalul de măsurare poate fi modificat în funcție de dinamica monitorizării dorite. Graficul de supraveghere va arăta în felul următor (se poate observa că, într-o zi însorită, indexul UV poate ajunge la valori periculoase în intervalul 15:00-17:00 iar într-o zi noroasă / cu ploaie rămâne la valori subunitare):

4

My Heart Will Go IoT

Măsurarea pulsului, a numărului de bătăi ale inimii pe minut, este un instrument de evaluare atât a stării de sănătate dar și a stării emoționale sau a efortului fizic depus. Apariția de senzori optici performanți fac această evaluare foarte simplă permițând măsurarea pulsului cu telefonul mobil sau cu diverse dispozitive de tip brățară. În cadrul proiectului de față vom explica construirea unui astfel de dispozitiv dar, în plus față de  dispozitivele clasice de măsurare a pulsului, vom înregistra datele obținute în cloud.

Atenție!!! Dispozitivul prezentat nu este un dispozitiv medical! Dispozitivul din acest proiect nu poate fi folosit pentru evaluarea stării de sănătate! Proiectul de față prezintă un principiu de măsurare și înregistrare nu și o metodă exactă de calibrare a datelor măsurate.

Pentru implementarea dispozitivului vom utiliza o placă de dezvoltarea Adafruit Feather M0 WiFi și un senzor de particule și puls MAX30105. Schema de interconectare dintre cele două componente este următoarea:

2

Senzorul comunică cu placa de dezvoltare prin intermediul magistralei I2C și atunci conexiunile dintre cele două componente sunt evidente: pinul SCL al senzorului la pinul 4 (SCL) al plăcii de dezvoltare și pinul SDA al senzorului la pinul 3 (SDA) al plăcii de dezvoltare. Pinul /INT al senzorului nu este folosit. Alimentarea senzorului se va face la 5V – pinul 5V se va conecta la pinul USB al plăcii de dezvoltare atâta timp cât placa se alimentează prin intermediul cablului USB. Dacă doriți să transformați sistemul într-un sistem portabil, alimentând placa de la un acumulator LiPo, atunci pinul de 5V al senzorului se va conecta la pinul BAT al plăcii de dezvoltare – senzorul se va alimenta la 3.7V (producătorul specifică posibilitatea de a alimenta senzorul la tensiuni între 3.3V și 5V dar explică că o tensiune de peste 3.5V va asigura o funcționare mai bună a senzorului).

Pentru punerea în funcțiune și pentru integrarea plăcii de dezvoltare cu mediul Arduino IDE este necesară parcurgerea materialului „Adafruit Feather M0 WiFi with ATWINC1500 – ARM Cortex M0+ with fast & fun wireless built in”. Pentru înțelegerea mai bună a modului de funcționare a senzorului de puls se poate parcurge materialul „MAX30105 Particle and Pulse Ox Sensor Hookup Guide”.

Programul sistemului se bazează pe exemplul Example5_HeartRate al bibliotecii software Sparkfun MAX3010x Pulse and Proximity Sensor Library. Programul a fost testat utilizând Arduino IDE 1.8.3 cu extensia Adafruit SAMD Boards 1.0.17 instalată și bibliotecile WiFi101 0.14.3 și Sparkfun MAX3010x 1.0.0. Atenție!!! Pentru a compila programul pentru placa Feather M0 este necesară adăugarea unei linii (#define BUFFER_LENGTH 32) în fișierul MAX30105.cpp al bibliotecii Sparkfun MAX3010x.

#include <SPI.h>

#include <WiFi101.h>

#define WINC_CS   8

#define WINC_IRQ  7

#define WINC_RST  4

#define WINC_EN   2 

Datele de conectare WiFi trebuie personalizate în program. Programul va înregistra datele măsurate în cloud utilizând serviciul Robofun IoT.

char ssid[] = ““;

char pass[] = ““; 

WiFiClient client;

int status = WL_IDLE_STATUS;

char server[] = “iot.robofun.ro”;

Constanta postingInterval va dicta intervalul (în milisecunde) la care se face înregistrarea datelor în cloud.

unsigned long lastConnectionTime = 0;

const unsigned long postingInterval = 30L * 1000L;

#include <Wire.h>

#include “MAX30105.h”

#include “heartRate.h”

MAX30105 particleSensor;

const byte RATE_SIZE = 4;

byte rates[RATE_SIZE];

byte rateSpot = 0;

long lastBeat = 0;

float beatsPerMinute;

int beatAvg;

Decomentarea directivei debug va permite vizualizarea datelor măsurate în concola serială.

//#define debug

3

În cadrul secțiunii setup() se va inițializa conexiunea WiFi și comunicația cu senzorul de puls. Mesajele de eroare vor apărea în consola serială doar dacă este activată directiva debug.

void setup() {

  #ifdef debug

    Serial.begin(115200);

    while (!Serial) { ; }

    Serial.println(“Initializing…”);

  #endif

  WiFi.setPins( 8,7,4,2);

  if (WiFi.status() == WL_NO_SHIELD) {

    #ifdef debug

      Serial.println(“WiFi shield not present”);

    #endif

    while (true);

  }

  while (status != WL_CONNECTED) {

    #ifdef debug

      Serial.print(“Attempting to connect to SSID: “);

      Serial.println(ssid);

    #endif

    status = WiFi.begin(ssid, pass);

    delay(10000);

  }

  #ifdef debug

    Serial.println(“Connected to wifi”);

  #endif

  if (!particleSensor.begin(Wire, I2C_SPEED_FAST))

  {

    #ifdef debug

      Serial.println(“MAX30105 was not found. Please check wiring/power. “);

    #endif

    while (1);

  }

  #ifdef debug

    Serial.println(“Place your index finger on the sensor with steady pressure.”);

  #endif

  particleSensor.setup();

  particleSensor.setPulseAmplitudeRed(0x0A);

  particleSensor.setPulseAmplitudeGreen(0);

}

În cadrul secțiunii loop() se va efectua atât citirea senzorului de puls (BPM – bătăi pe minut, medie – Avg BPM) cât și postarea către serviciul Robofun IoT. În cadrul codului trebuie personalizată cheia de autentificare (TOKEN) primită la înregistrarea senzorului în cadrul serviciului IoT. Intervalul de postare se contorizează începând cu detecția degetului pe senzor, dacă se ia degetul de pe senzor nu se mai efectuează înregistrarea valorilor în cloud. Se recomandă utilizarea unui elastic pentru a asigura o presiune constantă pe senzor.

4

void loop() {

  long irValue = particleSensor.getIR();

  if (checkForBeat(irValue) == true)

  {

    long delta = millis() – lastBeat;

    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);

    if (beatsPerMinute < 255 && beatsPerMinute > 20) {

      rates[rateSpot++] = (byte)beatsPerMinute;

      rateSpot %= RATE_SIZE;

      beatAvg = 0;

      for (byte x = 0 ; x < RATE_SIZE ; x++)

        beatAvg += rates[x];

      beatAvg /= RATE_SIZE; }

  }

  #ifdef debug

    Serial.print(“IR=”);

    Serial.print(irValue);

    Serial.print(“, BPM=”);

    Serial.print(beatsPerMinute);

    Serial.print(“, Avg BPM=”);

    Serial.print(beatAvg);

  #endif

  if (irValue < 50000) {

    #ifdef debug

      Serial.print(” No finger?”);

    #endif

    lastConnectionTime = millis();

  }

  #ifdef debug

    Serial.println();

  #endif

  if ((millis() – lastConnectionTime > postingInterval) && (beatAvg > 20))

  {   String temp = “GET /api/v1/senzor/TOKEN/input?value=” + String(beatAvg) + ” HTTP/1.1″;

      char param[100];

      temp.toCharArray(param,temp.length()+1);

      if (client.connect(server, 80)) {

        client.println(param);

        client.println(“Host: iot.robofun.ro”);

        client.println(“Connection: close”);

        client.println();

      }

      client.stop();

      lastConnectionTime = millis();

      lastBeat = 0;

  }

}

Pentru a utiliza serviciul Robofun IoT este necesară înregistrarea gratuită.

4

După înregistrare și conectare este necesară definirea unui noi senzor (Adauga senzor).

5

După definirea senzorului este necesar să copiem cheia de autentificare (Token) pentru a o utiliza în program.

3

După configurarea serviciului IoT și încărcarea programului pe placa de dezvoltare putem începe utilizarea dispozitivului și putem observa datele înregistrate on-line:

5

O facilitate foarte interesantă a serviciului Robofun IoT este posibilitatea de partajare a graficelor (Share senzor) sau de integrare a acestora în alte pagini web. Putem astfel să adăugăm paginii web personale sau blog-ului personal un grafic live cu numărul de bătăi ale propriei inimi.

6

Proiect Blynk IoT

Sparkfun Blynk ESP8266 este o placă de dezvoltare care, pe lângă avantajele oferite de serviciul cloud Blynk (prezentate în cadrul proiectului Cum să realizăm un sistem IoT fără să scriem nici o linie de cod?), oferă o combinație de componente extrem de interesante.

1

Procesorul WiFi ESP8266, senzorul digital de temperatură și umiditate Si7021 integrat și posibilitatea de alimentare de la un acumulator fac din placa Sparkfun Blynk ESP8266 o excelentă platformă pentru experimente IoT. În cadrul proiectului de față vom programa această placă utilizând Arduino IDE și nu vom utiliza platforma cloud specifică ci noul serviciu Robofun IoT.

2

Pentru punerea în funcțiune și programarea plăcii Blynk se recomandă parcurgerea materialului Blynk Board Arduino Development Guide. Pentru prima parte a proiectului nu avem nevoie decât de placa de dezvoltare și cablul USB de încărcare a programului – senzorul de temperatură și umiditate ce va furniza informațiile transmise către serviciul IoT este integrat pe placă.

Programul a fost dezvoltat și testat utilizând Arduino IDE 1.8.1, extensia esp8266 2.1.0 și bibliotecile Sparkfun Si7021 Humidity and Temperature Sensor 1.0.0 și Adafruit NeoPixel 1.1.1 (pe placa de dezvoltare se află și un led RGB WS2812 pe care îl vom comanda utilizând această bibliotecă). Declarațiile inițiale ale programului sunt următoarele:

#include <Wire.h>
#include “SparkFun_Si7021_Breakout_Library.h”
#include <Adafruit_NeoPixel.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

În cadrul programului trebuie personalizate datele de conectare WiFi:

char ssid[] = ““;

char pass[] = ““;

WiFiClient client;

float humidity = 0;

float tempC = 0;

Weather sensor;

#define PIN  4

#define NUMPIXELS 1

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

Varialbila postingInterval indică intervalul de timp între două raportări IoT (în milisecunde, în cazul dat ca exemplu: 10 minute)

unsigned long lastConnectionTime = 0;

const unsigned long postingInterval = 600L * 1000L;

Dacă doriți ca programul să afișeze informații despre execuție se va decomenta următoarea linie:

//#define debug

3

În cadrul secțiunii setup() se va inițializa conexiunea WiFi – pe durata inițializării led-ul RGB de pe placă va lumina roșu.

void setup() {

  pixels.begin();

  pixels.setPixelColor(0, pixels.Color(150,0,0));

  pixels.show();

  #ifdef debug

    Serial.begin(9600);

  #endif

  int status = WL_IDLE_STATUS;

  while (status != WL_CONNECTED)

  {

    status = WiFi.begin(ssid, pass);

    delay(10000);

  }

  #ifdef debug

    Serial.println(“Connected to wifi”);

  #endif

  sensor.begin();

  pixels.setPixelColor(0, pixels.Color(0,0,0));

  pixels.show();

}

Secțiunea loop() va verifica timpul scurs de la ultima raportare și dacă este depășit intervalul specificat se va apela procedura IoTPublish() care se ocupă de citirea senzorului Si7021 și de trimiterea datelor către Robofun IoT. Pe durata execuției procedurii led-ul de pe placă va lumina verde.

void loop() {

  if (millis() – lastConnectionTime > postingInterval)

  {

    pixels.setPixelColor(0, pixels.Color(0,150,0));

    pixels.show();

    IoTpublish();

    pixels.setPixelColor(0, pixels.Color(0,0,0));

    pixels.show();

  }

}

Procedura IoTpublish() va posta datele oferite de senzorul de temperatură și umiditate către serviciul IoT. Postarea se face prin două apeluri HTTP GET, câte unul pentru fiecare parametru trimis (temperatură și umiditate). Apelurile HTTP vor returna răspunsul 1 dacă totul este în regulă sau alte valoare dacă a apărut o eroare. Pentru utilizarea serviciului Robofun IoT este necesară înregistrarea gratuită a unui cont.

4

După înregistrare și conectare este necesară definirea a doi noi senzori.

5

Fiecare senzor va avea propria cheie de autentificare (token) și pentru fiecare dintre cei doi senzori este necesar să copiem această cheie în program (SENZOR_TOKEN1 și SENZOR_TOKEN2).

void IoTpublish() {

  String SENSOR_TOKEN1=”“;

  String SENSOR_TOKEN2=”“;

  HTTPClient http;

  humidity = sensor.getRH();

  tempC = sensor.getTemp();

  String data =

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

  http.begin(data);

  int httpCode = http.GET();

  #ifdef debug

    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());

    }

  #endif

  http.end();

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

  http.begin(data);

  httpCode = http.GET();

  #ifdef debug

    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());

    }

  #endif

  http.end();

  lastConnectionTime = millis();

}

După încărcarea programului pe placa de dezvoltare și scurgerea unui interval de funcționare mai lung decât postingInterval vom putea vedea deja pe graficul oferit de interfața serviciului valorile achiziționate de senzorul plăcii. În capturile de ecran următoare putem vedea un grafic pe o perioadă mai lungă de timp (temperatura – vizualizare a tuturor valorilor, umiditate – vizualizare a valorilor medii la nivel de săptămână).

6

7

Un atu foarte important al plăcii de dezvoltare Sparkfun Blynk ESP8266 este posibilitatea de alimentare utilizând un acumulator LiPo de 3.7V. Asta conferă sistemului portabilitate – vom dispune de un sistem de achiziție IoT de dimensiunea a două cutii de chibrituri. Totuși, o problemă majoră care se naște în acest caz este evaluarea autonomiei de funcționare a sistemului – determinarea nivelului de încărcare a acumulatorului. Utilizarea convertorului analog-numeric al plăcii în acest scop presupune construirea unui divizor de tensiune (convertorul poate măsura tensiuni între 0V și 3.3V) dar această soluție conduce la descărcarea mai rapidă a acumulatorului. O soluție mult mai elegantă pentru rezolvarea acestei probleme este utilizarea unei componente specializate de măsurare: LiPo Fuel Gauge. Conectarea acestei componente, între conectorul de alimentare al plăcii și acumulator, este prezentată în diagrama următoare:

8

Circuitul integrat MAX17043G+U al componentei de măsurare va supraveghea nivelul de tensiune al acumulatorului și îl va raporta către placa de dezvoltarea prin intermediul magistralei I2C – placa de dezvoltare are un conector special I2C la care se poate conecta componenta de măsurarea. Introducerea componentei de măsurare nu va influența în nici un fel posibilitatea de încărcarea a acumulatorului prin intermediul mufei microUSB de pe placă și nici nu va scădea durata de viață a acumulatorului.

În cadrul programului vom adăuga următoarele funcții și proceduri necesare lucrului cu circuitul MAX17043:

unsigned int vcellMAX17043() {

unsigned int vcell;

vcell = i2cRead16(0x02);

vcell = vcell >> 4;

return vcell; }

float percentMAX17043() {

unsigned int soc;

float percent;

soc = i2cRead16(0x04);

percent = (byte) (soc >> 8);

percent += ((float)((byte)soc))/256;

return percent; }

void qsMAX17043() {

i2cWrite16(0x4000, 0x06); }

unsigned int i2cRead16(unsigned char address) {

int data = 0;

Wire.beginTransmission(MAX17043_ADDRESS);

Wire.write(address);

Wire.endTransmission();

Wire.requestFrom(MAX17043_ADDRESS, 2);

while (Wire.available() < 2) ;

data = ((int) Wire.read()) << 8;

data |= Wire.read();

return data; }

void i2cWrite16(unsigned int data, unsigned char address) {

Wire.beginTransmission(MAX17043_ADDRESS);

Wire.write(address);

Wire.write((byte)((data >> 8) & 0x00FF));

Wire.write((byte)(data & 0x00FF));

Wire.endTransmission(); }

La începutul programului vom defini adresa I2C a circuitului MAX17043:

#define MAX17043_ADDRESS 0x36

Iar în cadrul procedurii IoTpublish() vom adăuga:

float batVoltage;

float batPercentage;

String SENSOR_TOKEN3=”…”;

String SENSOR_TOKEN4=”…”;

….

qsMAX17043();

batPercentage = percentMAX17043();

batVoltage = (float) vcellMAX17043() * 1/800;

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

http.begin(data);

httpCode = http.GET();

#ifdef debug

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());

}

#endif

http.end();

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

http.begin(data);

httpCode = http.GET();

#ifdef debug

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());   }

#endif

http.end();

Înainte de încărcarea noii versiuni de program este necesar să definim doi noi senzori (unul pentru tensiunea acumulatorului altul pentru procentul de încărcare) și să copiem cheile de autentificare în variabilele asociate: SENZOR_TOKEN3 și SENZOR_TOKEN4. După rularea programului vom putea vedea evoluția parametrilor acumulatorului folosit:

9

10

Proiect Noise-o-Meter IoT

Zgomotul este un factor de stres la fel de puternic ca și căldura, suprasolicitarea sau evenimentele cu impact emoțional dar de cele mai multe ori este ignorat și încadrat în „normalitatea” urbană cotidiană. Cât de mult ne afectează zgomotul înconjurător? Depinde de nivelul de zgomot la care suntem expuși. Cum putem evalua zgomotul din jurul nostru? Aparatele profesionale de măsurat puterea sunetelor sunt destul de scumpe și nu oferă o evaluare pe termen lung. În cadrul acestei lecții prezentăm implementarea unui sistem de măsură a nivelului de zgomot ambiental care, cu ajutorul serviciilor IoT, va permite evaluarea pe termen lung a acestui factor de stres.

Sistemul va utiliza placa de dezvoltare Arduino Leonardo ETH și un modul breakout cu microfon pentru achiziția nivelului de zgomot. Schema de interconectare este următoarea:

schema_bb

Modulul breakout se va alimenta la 3.3V (pinul VCC al modulului se va conecta la pinul 3.3V al plăcii de dezvoltare, pinul GND la pinul GND) și ieșirea analogică a modulului, pinul AUD, se va conecta la pinul de achiziție analogică A0 al plăcii de dezvoltare.

Pentru mai multe detalii despre utilizarea modulului breakout puteți consulta și materialul „Electret Mic Breakout Board Hookup Guide”. Pentru punerea în funcțiune și utilizarea plăcii de dezvoltare Arduino Leonardo ETH puteți consulta materialul „Start with Arduino Leonardo ETH”.

Placa de dezvoltare va realiza partea de achiziție a nivelului de zgomot și va trimite valorile, prin intermediul rețelei Internet, către serviciul Robofun IoT. Serviciul Robofun IoT este un serviciu gratuit ce permite stocarea datelor și vizualizarea evoluției acestora. Serviciul necesită înregistrare (secțiunea Cont nou):

4

După înregistrare și conectare este necesară definirea unui nou senzor (secțiunea Adaugă senzor):

5

După definirea senzorului este necesar să copiem cheia de autentificare (Token) pentru a o utiliza în program.

3

Programul a fost dezvoltat și testat utilizând Arduino IDE 1.8.1 având instalate extensia Arduino AVR Boards 1.6.19 și biblioteca Ethernet2 1.0.4. Pentru ca sistemul să funcționeze este necesară conectarea plăcii Arduino Leonardo ETH la o rețea locală cu servicii DHCP și conectivitate Internet.

#include <SPI.h>

#include <Ethernet2.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

EthernetClient client;

char server[] = “iot.robofun.ro”;

const int pinAdc = A0;

În cazul în care placa nu va putea obține configurația de rețea prin DHCP led-ul conectat pe pinul 13 va începe să clipească și programul se va bloca (bucla infinită while(1)) – se va verifica în acest caz conectarea cablului de rețea și se va reseta placa.

void setup() {

      Serial.begin(9600);

      if (Ethernet.begin(mac) == 0) {

        pinMode(13,OUTPUT);

        while(1) {       

         digitalWrite(13,LOW);

         delay(1000);

         digitalWrite(13,HIGH);

         delay(1000);

        }

      }

}

În cadrul secțiunii loop() este necesară completarea cheii de autentificare specifice senzorului definit în cadrul serviciului Robofun IoT (TOKEN).

void loop() {

    float sound = getSound();

    Serial.println(sound);

   String temp = “GET /api/v1/senzor/TOKEN/input?value=” + String(sound) + ” HTTP/1.1″;

    char param[100];

    temp.toCharArray(param,temp.length()+1);

    if (client.connect(server, 80)) {

      client.println(param);

      client.println(“Host: iot.robofun.ro”);

      client.println(“User-Agent: arduino-ethernet”);

      client.println(“Connection: close”);

      client.println();

    }

    client.stop();

}

Funcția getSound() va analiza semnalul analogic transmis de modul pe o perioadă de timp egală cu sampleWindow. Analiza va determina amplitudinea maximă a semnalului (variabila peakToPeak) și va face transformarea din valoare eșantionată (interval 0 – 1024) în tensiune (interval 0 – 3.3).

float getSound(){

   const int sampleWindow = 5000;

   unsigned int sample;

   unsigned long startMillis= millis();

   unsigned int peakToPeak = 0; 

   unsigned int signalMax = 0;

   unsigned int signalMin = 1024;

   while (millis() – startMillis < sampleWindow)   {

      sample = analogRead(pinAdc);

      if (sample < 1024)     {

         if (sample > signalMax)         {

            signalMax = sample;         }

         else if (sample < signalMin)         {

            signalMin = sample;         }

      }

   }

   peakToPeak = signalMax – signalMin;

   float volts = (peakToPeak * 3.3) / 1024.0; 

   return volts;

 }

Evoluția zgomotului ambiental se poate observa local deschizând Serial Plotter din meniul Tools al mediului Arduino IDE (programul raportează și pe serială valorile măsurate) dar supravegherea pe termen lung se va face prin interfața web a serviciului Robofun IoT:

robofun

Atenție!!! Valorile măsurate nu sunt calibrate, nu au o unitate de măsură asociate – nu reprezintă valori in decibeli. Valorile măsurate reprezintă doar o intensitate a zgomotului pe o scară de la 0 la 3.3 dar pot da o imagine destul de bună a variației zgomotului în mediul ambiental.

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