Finala Competiției Internet of Things Student Challenge 2017

Dorim să vă invităm la Finala Competiției Internet of Things Student Challenge 2017 în data de 22 Iunie 2017, ora 15 din partea Departamentului de Automatică, Facultatea de Automatică și Calculatoare, Universitatea Tehnică din Cluj-Napoca. În cadrul competiției s-au înscris 14 echipe care au dezvoltat proiecte Internet of Things și Building Automation. Competiția este strâns legată de Conferința Științifică Internațională AQTR (International Conference on Automation, Quality and Testing, Robotics) și va avea loc anual, ridicând ștacheta tot mai sus.

Evenimentul va fi de asemenea transmis LIVE! pe pagina de Facebook: https://www.facebook.com/events/251297775277832??ti=ia

Pagini oficiale ale competiției:
http://contest.aqtr.ro/
https://www.facebook.com/Internet.of.Things.Student.Challenge

Locația evenimentului:
Facultatea de Automatică și Calculatoare, Departamentul de Automatică,
Strada Dorobanților, Nr.71-73, Sala C01, data 22.06.2017, orele 15-22

Cu respect,
IoT Student Challenge 2017 – Organizing Committe

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/input/” + SENSOR_TOKEN1 + “/” + 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/input/” + SENSOR_TOKEN2 + “/” + 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/input/” + SENSOR_TOKEN3 + “/” + 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/input/” + SENSOR_TOKEN4 + “/” + 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/input/TOKEN/” + 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.