Imprimanta Robofun 20-20-20 – HOW TO

Inainte de a incepe acest articol, te rog sa citesti cu mare atentie cele de mai jos.

Imprimanta 3D se alimenteaza in priza de 220 V. NICIODATA si sub nici un motiv nu desface carcasa imprimantei, nu introduce obiecte metalice in zona sursei de alimentare. Daca observi probleme in zona sursei sau a firelor de conexiune la priza, deconecteaza imediat imprimanta de sub tensiune si returneaz-o pentru reparatii. PERICOL DE ELECTROCUTARE !

De asemenea, nu lasa niciodata imprimanta 3D sub tensiune (conectata la priza) fara supraveghere. 

 

Pasii pentru a pune in functiune o imprimanta 3D Robofun  sunt cei de mai jos :

  1. descarca si instaleaza Cura (software-ul care proceseaza modelul 3D si il face usor de inteles pentru imprimanta)
  2. descarca si instaleaza Repetier (software-ul care gestioneaza procesul de printare)
  3. pune imprimanta sub tensiune si testeaza ca totul este OK din punct de vedere mecanic si software
  4. calibreaza distanta de start pe axa Z, daca este cazul
  5. calibreaza orizontalitatea bed-ul, daca este cazul
  6. primul print

 

Cand vei termina filamentul, va fi necesar sa il schimbi, conform instructiunilor de mai jos.

1. Instalare Cura

Cura este acel software care analizeaza obiectul 3D (pe care il ai in format STL) si genereaza un cod sursa pe care imprimanta il intelege (in format gcode).

Mergi la adresa web https://ultimaker.com/en/products/cura-software/list si descarca “Version: 2.3.1” (pe 32 de biti sau pe 64 de biti, in functie de ce arhitectura ai la PC; daca esti in dubiu, alege 32 de biti, va functiona oricum). Sigur ca poti alege si versiuni mai noi, insa tutorialul de mai jos este creat pentru Cura 2.3.1 Am ales aceasta versiune pentru ca este ultima care mai suporta versiune de 32 de biti.

Deschide fiecare grup de setari din partea dreapta si asigura-te ca totul este ca mai jos.

Optiunile “Retraction Distance” si “Retraction Speed” probabil ca nu sunt vizibile by default. Este necesar sa accesezi optiunea “Configure Settings Vizibility” din meniul “Settings” si sa le activezi (fa o cautare dupa “retract” – introdu acest text in campul “Filter” si va fi simplu).

 

 

2. Instalare Repetier

Repetier este acel software care se ocupa efectiv de procesul de printare. Rolul lui este de a trimite progresiv codul gcode la imprimanta si a monitoriza parametri de printare.

Descarca “Repetier Host Windows 2.0.5” de la adresa – https://www.repetier.com/download-now/ . Sigur, poti descarca si o versiune mai noua daca vrei, insa tutorialul de mai jos este pentru versiunea 2.0.5

 

3. Teste preliminare imprimanta

A. conectare cablu USB

Folosind cablul USB primit o data cu imprimanta, conecteaza imprimanta la PC, ca in poza de mai jos.

Nu toate cablurile USB sunt la fel de bune, asa ca pentru inceput, te rog sa folosesti cablul primit o data cu imprimanta. Mai tarziu, dupa ce printezi cateva zile, il poti schimba daca vrei, insa daca apar orice fel de probleme, intoarce-te la cablul USB original.Viteza de transfer este destul de mare, asa ca ai nevoie de un cablu care sa o poata suporta.

 

B. drivere si port USB

Ar trebui ca PC-ul sa vada automat imprimanta si sa creeze un nou port serial pentru comunicarea cu aceasta.

Deschide Control Panel, apoi Device Manager, si verifica sectiunea “Ports”. Ar trebui sa ai o inregistrare similara cu cea de mai jos. Probabil ca la tine numarul portului va fi mult mai mic (gen COM4, sau COM5).

Daca nu vezi o astfel de inregistrare in Device Manager, inseamna ca driver-ele nu sunt corect instalate. Ne poti contacta la adresa de email contact [at] robofun [dot] ro si te vom ajuta cu placere sa rezolvi problema.

C. conectare Repetier

Conecteaza imprimanta la 220 V, in priza. Inca o data, repet avertismentul de la inceput. NU deschide carcasa imprimantei si NU introduce obiecte metalice in zona sursei. Pericol de electrocutare !

Deschide programul “Repetier-Host”, instalat la pasul precedent.

Din meniul “Config”, alege optiunea “Printer Settings”. Selecteaza portul pe care l-ai vazut mai devreme in Device Manager, apoi selecteaza o viteza de transfer (Baud Rate) de 115200, si apasa OK.

Apasa butonul “Connect”, din stanga sus. Ar trebui ca eticheta butonului sa se schimbe in “Disconnect”, iar in partea de jos a ecranului sa vezi o serie de mesaje primite de la imprimanta, ca mai jos.

Daca nu vezi aceste mesaj, inseamna ca exista o problema si nu vei putea printa. Verifica inca o data in Device Manager numarul portului serial COM, si asigura-te ca este corect introdus in Printer Settings. Asigura-te ca viteza este de 115200. Daca nu reusesti, ne poti contacta la adresa de email contact [at] robofun [dot] ro si te vom ajuta cu placere sa rezolvi problema.

D. teste miscare din Repetier

Deschide tab-ul “Manual Control” (dreapta sus). Aceasta sectiune iti permite sa iti controlezi imprimanta manual, pentru teste.

Apasa “HOME X”. Ar trebui sa vezi ca axa X (hotend-ul) se misca. Apasa butonul “HOME Y”. Ar trebui sa vezi ca axa Y (bed-ul) se misca.

Daca nu se intampla asta, verifica daca imprimanta este in priza, si daca in priza chiar ai curent 🙂

 

 

E. teste incalzire din Repetier

In zona inferioara a tab-ul “Manual Control” vezi temperaturile curente ale bed-ului si ale extruderului. Ar trebui sa vezi temperatura ambianta in acest moment. Apasa pe icon-ul “INCALZIRE BED”, apoi apasa pe icon-ul “INCALZIRE HOTEND”, astfel incat sa nu mai fie taiate cu linie rosie. Vei observa ca si bed-ul si hotend-ul incep sa se incalzeasca.

 

F. test extrudare din Repetier

Dupa ce hotend-ul a atins 200 de grade (verifici temperatura afisata), apasa butonul “AVANS FILAMENT”. In functie de unde anume apesi, vei scoate 10 mm, 50 de mm sau 100 de mm de filament. Recomand sa apesi astfel incat sa scoti 50 de mm de filament. Motorul montat in partea de sus, cel care actioneaza extruder-ul va incepe sa se miste si vei observa cum filamentul iese prin hotend (este “extrudat”).

Miscarea filamentului trebuie sa fie continua, si la fel si curgerea filamentului topit prin hotend.

 

4. Calibrare pe axa Z

Este foarte important ca distanta dintre bed si hotend sa fie exact cat trebuie atunci cand incepe procesul de printare. Daca este prea mare, filamentul nu va adera la bed. Daca este prea mica, filamentul nu va avea loc sa iasa din cauza bed-ul. Acest lucru se regleaza din elementul din stanga.

Rolul lui este de a lovi in butonul mic, de culoare rosie, si de a semnaliza astfel pozitia de zero pe axa verticala. Este prins pe surub, astfel incat daca il rotesti spre dreapta, surubul se insurubeaza in prindere, iar elementul de reglaj se misca in sus. Daca il rotesti spre stanga, surubul se desurubeaza, iar elementul de reglaj de misca in jos. Atunci cand se misca in sus, el va lovi mai tarziu butonul, astfel incat distanta de start va fi mai mica. Cand se misca in jos, va lovi mai devreme butonul, deci distanta de start va fi mai mare.

Misca cu mana hotend-ul si bed-ul astfel incat hotend-ul sa se afle relativ in centrul bed-ul. Pune o coala de hartie obisnuita pe bed si apasa butonul “HOME Z”. Vei vedea ca hotend-ul incepe sa coboare. In momentul in care elementul de reglaj din poza de mai sus atinge butonul, hotend-ul se va opri. Foaia de hartie este prinsa intre hotend si bed in acest moment. Incearca sa o misti. Ar trebui sa o poti misca, dar cu un pic de rezistenta.

Daca este foarte bine fixata si nu o poti misca, inseamna ca distanta este prea mica. Apasa pe butonul “Z UP” ca sa misti axa Z in sus cu 10 mm, apoi roteste elementul de reglaj spre stanga, ca sa il deplasezi in jos (astfel incat sa loveasca mai devreme butonul) si apasa iar pe butonul “HOME Z”.

Daca foaia de hartie se misca liber, inseamna ca distanta este prea mare. Apasa pe butonul “Z UP” ca sa misti axa Z in sus cu 10 mm, apoi roteste elementul de reglaj spre dreapta, ca sa il deplasezi in sus (astfel incat sa loveasca mai tarziu butonul), si apasa iar pe butonul “HOME Z”.

Repeta pasii pana cand foaia de hartie se misca, dar cu un pic de rezistenta.

 

 

5. Calibrarea orizontalitatii bed-ului

Misca cu mana bed-ul si hotend-ul astfel incat sa duci hotend-ul in fiecare dintre cele patru colturi ale bed-ului, si repeta teste cu foaia de hartie de mai sus pentru fiecare colt. Ca diferenta, distanta o reglezi de data aceasta NU din elementul mobil folosit la pasul 4, ci direct din piulita de prindere a bed-ului din acel colt.

Bed-ul este prin pe arcuri, asa ca prin rasucirea piulitei de prindere poti ridica si cobori fiecare colt. Continua pana cand poti misca foaia de hartie relativ liber in fiecare colt.

 

6. Primul print

Descarca obiectul STL de aici – https://www.robofun.ro/docs/x-carriage.stl

Deschide Cura (instalat la unul dintre pasii anteriori)

Din meniul “File”, alege “Open File”. Selecteaza fisierul STL descarcat.

Apasa butonul “Save to File” (dreapta jos). Salveaza fisierul gcode unde vrei tu.

Deschide Repetier. Incarca fisierul gcode (butonul “Load”). Atentie mare la acest pas, incarca fisierul cu extensia .gcode si NU cel cu extensia .STL !

Apasa butonul “Start Print”.

Dupa ce hotend-ul se incalzeste la 210 grade, imprimanta va incepe sa printeze.

 

 

 

 

Calendar de Crăciun

Calendarul de Crăciun sau Calendarul de Advent este o modalitate de a face să treacă timpul mai ușor în așteptarea sărbătorii de Crăciun. Acest calendar indică câte zile au trecut și câte zile mai sunt (în luna decembrie bineînțeles) până în dimineața zilei de Crăciun. Pentru copii există variante care oferă zilnic mici surprize (bomboane sau ciocolată) pentru a atenua nerăbdarea așteptării cadourilor de Crăciun dar, în cadrul proiectului de față, propunem construirea unui calendar de Crăciun bazat pe 24 de LED-uri: un calendar de Crăciun cu luminițe.

Pentru a comanda mai ușor cele 24 de LED-uri vom utiliza LED-uri RGB adresabile WS2812. Acestea nu necesită comandă individuală, este suficientă o singură linie de comandă între cele 24 de LED-uri și placa de dezvoltare. Se pot utiliza LED-uri NeoPixel  sau module WS2812 breakout. Pentru mai multe detalii legate de funcționarea LED-urilor WS2812 se recomandă parcurgerea materialului: „Adafruit NeoPixel Überguide”.

2

Pentru comandă vom utiliza placa de dezvoltare WiDo echipată cu un microcontroler ATmega32U4 (prezent și pe placa Arduino Leonardo) și un controler WiFi CC3000. Această combinație este perfectă pentru implementarea sistemului nostru: microcontrolerul ATmega32U4 va asigura comanda LED-urilor la o tensiune de 5V iar controlerul WiFi va fi utilizat pentru a putea ști în ce zi calendaristică ne aflăm (sincronizare de timp de tip NTP).

3

Conexiunile dintre placa de dezvoltare și LED-uri sunt prezentate în schema următoare. Sistemul necesită o alimentare de 5V minim 2A (pentru placa de dezvoltare și cele 24 de LED-uri). Pinul de comandă este pinul D6. Comanda se va transmite serial de la un LED la următorul. LED-urile pot fi aranjate pe un carton pictat cu un brad de crăciun sau orice alt suport doriți (o căsuță de poveste sau o ilustrată de Crăciun).

4

Programul a fost dezvoltat și testat utilizând Arduino IDE 1.8.3 și bibliotecile Adafruit Neopixel 1.1.3 și o versiune modificată a bibliotecii Adafruit CC3000. Placa se va programa în Arduino IDE ca o placă Arduino Leonardo obișnuită.

#include <Adafruit_NeoPixel.h>

#ifdef __AVR__

  #include <avr/power.h>

#endif

#define PIN 6

#define NUMPIXELS 24

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

#include <Adafruit_CC3000.h>

#include <ccspi.h>

#include <SPI.h>

#define WiDo_IRQ   7

#define WiDo_VBAT  5

#define WiDo_CS    10

Adafruit_CC3000 WiDo = Adafruit_CC3000(WiDo_CS, WiDo_IRQ,  WiDo_VBAT,SPI_CLOCK_DIVIDER);

În cadrul programului trebuie personalizate datele de conectare la rețeaua WiFi (WLAN_SSID și WLAN_PASS).

#define WLAN_SSID       “…”          

#define WLAN_PASS       “…”

#define WLAN_SECURITY   WLAN_SEC_WPA2

Adafruit_CC3000_Client client;

#include <TimeLib.h>

Pentru sistemul final, directiva debug se poate comenta pentru a suprima mesajele din consola serială.

#define debug

void setup() {

  #ifdef debug

    SerialUSB.begin(115200);

    while(!SerialUSB) { ; }

    SerialUSB.println(F(“Calendar de Craciun\n”));

    SerialUSB.println(F(“\nInitialising the CC3000 …”));

  #endif

  if (!WiDo.begin())  {

    #ifdef debug

      SerialUSB.println(F(“Unable to initialise the

CC3000! Check your wiring?”));

    #endif

    while(1);   }

 if (!WiDo.connectToAP(WLAN_SSID,WLAN_PASS,WLAN_SECURITY)) {

    #ifdef debug

      SerialUSB.println(F(“Failed to connect to AP!”));

    #endif

    while(1);   }

  #ifdef debug

    SerialUSB.println(F(“Connected to AP!”));

    SerialUSB.println(F(“Request DHCP”));

  #endif

  while (!WiDo.checkDHCP())  {    delay(100);  } 

  while (! displayConnectionDetails()) {

      delay(1000);

    }

  setSyncProvider(getTime);

  pinMode(6,OUTPUT);

  pixels.begin();

  randomSeed(analogRead(0));

  startprogram();

}

bool displayConnectionDetails(void)

{

  uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;

  if(!WiDo.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))  {

    #ifdef debug

      SerialUSB.println(F(“Unable to retrieve the IP Address!\r\n”));

    #endif

    return false;

  }

  else

  {

    #ifdef debug

      SerialUSB.print(F(“\nIP Addr: “));

     WiDo.printIPdotsRev(ipAddress);

      SerialUSB.print(F(“\nNetmask: “));

      WiDo.printIPdotsRev(netmask);

      SerialUSB.print(F(“\nGateway: “));

      WiDo.printIPdotsRev(gateway);

      SerialUSB.print(F(“\nDHCPsrv: “));

      WiDo.printIPdotsRev(dhcpserv);

      SerialUSB.print(F(“\nDNSserv: “));

      WiDo.printIPdotsRev(dnsserv);

      SerialUSB.println();

    #endif

    return true;

  }

}

Procedura startprogram(), apelată o singură dată în secțiunea setup(), aprinde toate LED-urile de trei ori în trei culori diferite: roșu, verde, albastru. Este o procedură de verificare a montajului ce se execută la fiecare pornire a sistemului.

void startprogram() {

  for (int i=0; i<NUMPIXELS; i++) {

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

    pixels.show();

    delay(100);

  }

  for (int i=0; i<NUMPIXELS; i++) {

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

  }

  pixels.show();

  delay(100);

  for (int i=0; i<NUMPIXELS; i++) {

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

    pixels.show();

    delay(100);

  }

  for (int i=0; i<NUMPIXELS; i++) {

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

  }

  pixels.show();

  delay(100);

  for (int i=0; i<NUMPIXELS; i++) {

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

    pixels.show();

    delay(100);

  }

  for (int i=0; i<NUMPIXELS; i++) {

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

  }

  pixels.show();

  delay(100);

}

Secțiunea loop() va aștepta realizarea sincronizării de timp după care va verifica o dată la 10 minute data calendaristică. Între 1 decembrie și 24 decembrie va aprinde un număr de LED-uri egal cu data calendaristică. Culoarea va fi de fiecare dată generată aleatoriu. În data de 25 decembrie programul va executa un joc de lumini pe toată perioada zilei (va aprinde toate cele 24 de LED-uri treptat în culori aleatorii). În restul anului LED-urile vor rămâne stinse.

void loop() {

   #ifdef debug

    if(timeStatus()==timeNotSet) SerialUSB.println(“Time Not Set”);

    if(timeStatus()==timeNeedsSync) SerialUSB.println(“Time Needs Sync”);

   #endif

   while(timeStatus()==timeNotSet) delay(1000);

   for (int i=0; i<NUMPIXELS; i++) {

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

    }

   pixels.show();

   delay(100);

   if(month()==12) {

    if (day()<25) {

      #ifdef debug

        SerialUSB.print(“Days to Christmas: “); SerialUSB.println(25-day());

      #endif

      for (int i=0; i<NUMPIXELS; i++) {

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

      }

      pixels.show();

      delay(100);

      for (int i=0; i<day(); i++) {

        pixels.setPixelColor(i,pixels.Color(random(0,255),random(0,255),random(0,255)));

      }

      pixels.show();

    }

    if (day()==25) {

        for (int i=0; i<NUMPIXELS; i++) {

          pixels.setPixelColor(i,pixels.Color(random(0,255), random(0,255),random(0,255)));

         pixels.show();

         delay(1000);

        }

    }

   }

   delay(600000);

}

Funcția getTime() este folosită de biblioteca Time pentru sincronizarea de timp NTP.

const unsigned long

  connectTimeout  = 15L * 1000L,

  responseTimeout = 15L * 1000L;

unsigned long getTime(void) {

  uint8_t       buf[48];

  unsigned long ip, startTime, t = 0L;

  #ifdef debug

    SerialUSB.print(F(“Locating time server…”));

  #endif

  if(WiDo.getHostByName(“pool.ntp.org”, &ip)) {

    static const char PROGMEM

      timeReqA[] = { 227,  0,  6, 236 },

      timeReqB[] = {  49, 78, 49,  52 };

    #ifdef debug

      SerialUSB.println(F(“\r\nAttempting

                 connection…”));

    #endif

    startTime = millis();

    do {

      client = WiDo.connectUDP(ip, 123);

    } while((!client.connected()) &&

            ((millis() – startTime) < connectTimeout));

    if(client.connected()) {

      #ifdef debug

        SerialUSB.print(F(“connected!\r\nIssuing

                 request…”));

      #endif

      memset(buf, 0, sizeof(buf));

      memcpy_P( buf    , timeReqA, sizeof(timeReqA));

      memcpy_P(&buf[12], timeReqB, sizeof(timeReqB));

      client.write(buf, sizeof(buf));

      #ifdef debug

        SerialUSB.print(F(“\r\nAwaiting response…”));

      #endif

      memset(buf, 0, sizeof(buf));

      startTime = millis();

      while((!client.available()) &&

            ((millis() – startTime) < responseTimeout));

      if(client.available()) {

        client.read(buf, sizeof(buf));

        t = (((unsigned long)buf[40] << 24) |

             ((unsigned long)buf[41] << 16) |

             ((unsigned long)buf[42] <<  8) |

              (unsigned long)buf[43]) – 2208988800UL;

        #ifdef debug

          SerialUSB.print(F(“OK\r\n”));

        #endif

      }

      client.close();

    }

  }

  #ifdef debug

    if(!t) SerialUSB.println(F(“error”));

  #endif

  return t;

}

Pentru idei suplimentarea în realizarea artistică a aranjamentului se pot vedea și următoarele două proiecte:

Cum putem utiliza prognoza meteo oferită de Weather Underground

Așa cum am arătat și în proiectul „Mini stație meteo”, serviciul Weather Undergroud este un serviciu independent (nu este un serviciu al unei țări sau structuri oficiale) de predicție a vremii. Acest serviciu Internet permite realizarea de prognoze locale pe baza informațiilor provenite de la o stații meteo personale (PWS – Personal Wether Station) sau corelând informațiile de la mai multe stații meteo personale aflate într-o anumită zonă.

Dacă în lecția proiectul „Mini Stație Meteo Weather Underground” am arătat cum să construim o mini stație meteo care să raporteze date către Weather Underground, în lecția de față vom arăta cum putem utiliza datele de prognoză calcultate de Weather Underground. Pentru acest lucru este necesar să solicităm o cheie API (API Key) de conectare de la adresa:

2

Furnizarea prognozei meteo este un serviciu comercial (se plătește) dar pentru dezvoltatori (developers) există un plan tarifar gratuit (Stratus Plan) ce permite efectuarea de 500 de interogări pe zi (maxim 10 interogări pe minut) – limitări ce nu afectează sistemul prezentat în această lecție.

3

Odată obținută cheia de conectare la platforma Weather Underground putem scrie aplicații proprii care să prezinte prognoza meteo fără a fi necesară accesarea site-ului Weather Underground sau utilizarea aplicației mobile Weather Underground. Mai multe informații se pot consulta în pagina de suport a platformei unde sunt prezentate exemple pentru mai multe limbaje de programare. Funcțiile API puse la dispoziție de platforma Weatgher Underground se pot accesa și de pe un sistem embedded simplu. Pentru exemplificarea acestui lucru vom utiliza sistemul descris în proiectul „Ceas IoT cu programare OTA” format dintr-o placă NodeMCU și un ecran LCD grafic 84×48 pixeli:

5

Sistemul va păstra funcționalitatea de ceas și senzor de temperatură IoT dar va afișa și prognoza meteo pentru ziua curentă și ziua următoare.

Vom pleca de la programul scris pentru sistemul Ceas IoT. Programul a fost dezvoltat și testat utilizând Arduino IDE 1.8.3 având instalată extensia ESP8266 Community 2.3.0. Pentru accesarea funcțiilor API Weather Underground vom utiliza bibliotecile Json Streaming Parser 1.0.5 și ESP8266 Weather Station 1.3.2. Programul Ceas IoT se va completa cu următoarele declarații inițiale (este necesară completarea cheii API – constanta WUNDERGROUND_API_KEY și, dacă este cazul, modificarea localității pentru care se dorește obținerea prognozei meteo – constantele WUNDERGROUND_ZMW_CODE și WUNDERGR_UND_CITY):

#include <JsonListener.h>

#include “WundergroundConditions.h”

#include “WundergroundForecast.h”

const String  WUNDERGRROUND_API_KEY = “…”;

const boolean IS_METRIC = true;

const boolean USE_PM = false;

const String WUNDERGROUND_ZMW_CODE = “00000.26.WLRBS”;

const String  WUNDERGRROUND_LANGUAGE = “EN”;

const String  WUNDERGR_UND_STATE_OR_COUNTRY = “RO”;

const String  WUNDERGR_UND_CITY = “Bucharest”;

WundergroundConditions wunderground(IS_METRIC);

WundergroundForecast wundergroundf(IS_METRIC);

WGConditions conditions;

WGForecast forecasts[3];

La sfârșitul secțiunii setup() se vor adăuga următoarele două instrucțiuni:

wunderground.updateConditions(&conditions, WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_ZMW_CODE);

wundergroundf.updateForecast(forecasts, 3, WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGR_UND_STATE_OR_COUNTRY, WUNDERGR_UND_CITY);

În cadrul secțiunii loop() se va modifica partea de afișare astfel încât să avem patru stări de afișare (patru ecrane diferite) care se vor succeda la un interval de 15 secunde (fiecare ecran va rămâne afișat timp de 15 secunde): primul ecran va afișa ora și data (la fel ca și în lecția precedentă), al doilea ecran va afișa temperatura interioară și statusul conexiunii IoT (la fel ca și în lecția precedentă), al treilea ecran va afișa prognoza pentru ziua curentă iar al patrulea pentru ziua următoare.

6

7

Din păcate, chiar dacă funcțiile API Weather Underground au implementată traducerea informațiilor în limba română, vom utiliza în program prognoza în limba engleză deoarece setul de caracter a ecranului LCD nu include și diacritice. În capturile anterioare se poate observa că pentru ziua curentă avem cer senin (Clear) și pentru prognoza zilei următoare se preconizează cer noros și câteva picături de ploaie.

if (second()<15) {

       // codul rămâne neschimbat față de proiectul anterior

    }

else if (second()<30) {

      // codul rămâne neschimbat față de proiectul anterior

    }

else if (second()<45) {

      display.drawLine(0,0,83,0,BLACK);

      display.drawLine(0,47,83,47,BLACK);

      display.setTextColor(BLACK);

      display.setTextSize(1);

      display.setCursor(10,2);

      display.print(“Vremea acum”);

      display.drawLine(0,11,83,11,BLACK);

      display.setCursor(30,14);

      display.print(conditions.currentTemp);

      display.print((char)247);

      display.print(“C”);

      display.setCursor(35,22);

      display.print(conditions.humidity);

      display.setCursor(27,30);

      display.print(conditions.pressure);

      display.setCursor((84-(5*conditions.weatherText.length()))/2,38);

      display.print(conditions.weatherText);

      display.display();

    }

    else {

      display.fillScreen(BLACK);

      display.drawLine(0,1,83,1,WHITE);

      display.drawLine(0,46,83,46,WHITE);

      display.setTextColor(WHITE);

      display.setTextSize(1);

      display.setCursor(5,3);

      display.print(“Vremea maine”);

      display.drawLine(0,12,83,12,WHITE);

      display.setCursor(20,14);

      display.print(“Min:”);

      display.print(forecasts[2].forecastLowTemp);

      display.print((char)247);

      display.print(“C”);

      display.setCursor(20,22);

      display.print(“Max:”);

      display.print(forecasts[2].forecastHighTemp);

      display.print((char)247);

      display.print(“C”);

      String temp = forecasts[2].forecastText;

      int prim = temp.indexOf(‘.’);

      display.setCursor((84-(5*prim))/2,30);

      display.print(temp.substring(0,prim));

      display.setCursor(0,38);

     display.print(temp.substring(prim+2, temp.indexOf(‘.’,prim+2)));

      display.display()     }

if (millis() – lastConnectionTime > postingInterval) {

      wunderground.updateConditions(&conditions,

WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_ZMW_CODE);

      wundergroundf.updateForecast(forecasts, 3, WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGR_UND_STATE_OR_COUNTRY,  WUNDERGR_UND_CITY);

      // codul rămâne neschimbat față de proiectul anterior

    }

Prognoza meteo oferită de Weather Underground are o acoperire de zece zile. În cadrul sistemului prezentat nu am utilizat decât ziua curentă și ziua următoare dar programul poate fi ușor modificat pentru afișarea unei prognoze pe mai multe zile. În plus există mai multe facilități ce nu au fost utilizate în exemplul nostru dar pot constitui dezvoltări ulterioare interesante: avertizări de vreme extremă (a se vedea exemplul WundergroundAlertsDemo din cadrul bibliotecii ESP8266 Weather Station) sau elemente de evoluție astronomică (a se vedea exemplul WundergroundAstronomyDemo).

O altă posibilă direcție de îmbunătățire posibilă a sistemului de predicție meteo este utilizarea simbolurilor grafice oferite de Weather Underground pentru o reprezentare sugestivă a evoluției meteo.

8

Un exemplu de proiect ce utilizează aceste simboluri este „ESP8266 Weather Widget”, proiect ce utilizează un ecran grafic OLED de rezoluție mai mare.

Mini Stație Meteo Weather Underground

Serviciul Weather Undergroud este un serviciu independent (nu este un serviciu al unei țări sau strucutură oficială) de predicție a vremii. Acest serviciu Internet permite realizarea de prognoze locale pe baza informațiilor provenite de la o stație meteo personală (PWS – Personal Wether Station) sau corelând informațiile de la mai multe stații meteo personale aflate într-o anumită zonă. Serviciul Weather Underground permite completarea funcționalității unei stații meteo personale cu partea de istoric și predicție a evoluției vremii și oferă o modalitate convenabilă în care utilizatorul poate consulta informațiile furnizate de stația meteo de oriunde prin Internet.

În cadrul proiectului de față vom prezenta realizarea unei mini stații meteo (măsoară doar temperatura, umiditatea și presiunea atmosferică) ce raportează datele măsurate către serviciul Weather Underground. Pentru partea de achiziție vom utiliza un singur senzor capabil să măsoare toți cei trei parametrii: BME280. Bineînțeles, sistemul prezentat poate fi extins și cu alți senzori specifici unei stații meteo: senzori pentru viteza și direcția vântului, senzor pentru cantitatea de precipitații sau senzor pentru indexul radiațiilor ultraviolete.

2

Ca placă de dezvoltare vom utiliza Adafruit HUZZAH ESP8266 breakout ce ne va permite o conectare simplă la Internet prin WiFi la un cost scăzut. Schema de interconectare între placa de dezvoltare și senzorul BME280 este următoarea:

3

Comunicația între senzor și placa de dezvoltare se bazează pe protocolul I2C prin urmare legărutile sunt:

  • Pinul SDA al senzorului se conectează la pinul #4 al plăcii de dezvoltare;
  • Pinul SCL al senzorului se conectează la pinul #5 al plăcii de dezvoltare;
  • Pinii 3.3V și GND ai senzorului se conectează la pinii 3V și GND ai plăcii.

Placa va trimite la un interval de 60 de minute (1 oră) datele achiziționate către serviciul Weather Underground iar între două postări se va afla în mod de consum redus. Din acest motiv există o legătură între pinul #16 și pinul RST al plăcii. Pinul #16 are funcționalitate de Wake ce permite resetarea plăcii pentru a ieși din modul de consum redus. Pentru mai multe informații despre modul de consum redus al circuitului ESP8266 puteți consulta materialul „ESP8266 Deep Sleep with Arduino IDE”.

Pentru alimentarea plăcii puteți un regulator de 3.3V sau una sau mai multe baterii ce furnizează între 4V și 6V (alimentarea se va face în acest caz prin intermediul pinului Vbat). Având în vedere consumul redus al sistemului funcționarea pe baterii se poate face pe perioade lungi de timp.

Pentru programarea plăcii Adafruit HUZZAH ESP8266 este nevoie de un programator FTDI sau de un cablu FTDI. Pentru mai multe informații despre funcționarea plăcii de dezvoltare Adafruit HUZZAH ESP8266 puteți consulta materialul „Adafruit HUZZAH ESP8266 breakout – Adorable bite-sized WiFi microcontroller, at a price you like!”.

Programul a fost dezvoltat și testat utilizând Arduino IDE 1.8.3 având instalate extensia ESP8266 Community 2.3.0 și biblioteca Sparkfun BME280 1.1.0. În cadrul programului trebuie personalizate datele de conectare la rețeaua WiFi (ssid și pass) precum și datele de autentificare la platforma Weather Underground (ID și PASSWORD).

#include <ESP8266WiFi.h>

#include <ESP8266HTTPClient.h>

#include “SparkFunBME280.h”

#include “Wire.h”

BME280 mySensor;

char ssid[] = “…”;

char pass[] = “…”;

WiFiClient client;

void setup() {

  WiFi.begin(ssid, pass);

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

      delay(500);

    }

  mySensor.settings.commInterface = I2C_MODE;

  mySensor.settings.I2CAddress = 0x77;

  mySensor.settings.runMode = 3;

  mySensor.settings.tStandby = 0;

  mySensor.settings.filter = 0;

  mySensor.settings.tempOverSample = 1;

  mySensor.settings.pressOverSample = 1;

  mySensor.settings.humidOverSample = 1;

  mySensor.begin();

  delay(100); }

void loop() {

  float tempC = mySensor.readTempC();

  float humidity = mySensor.readFloatHumidity();

  float pressure = mySensor.readFloatPressure();

  delay(100);

  String url = “http” + “://weatherstation.wunderground.com/”

  url += “weatherstation/updateweatherstation.php?”

  url += “ID=…&PASSWORD=…”

  url += “&dateutc=now&=&action=updateraw&”;

  url += “baromin=” + String(pressure * 29.92 / 101325);

  url += “&tempf=” + String(9/5.0 * tempC + 32.0);

  url += “&humidity=” + String(humidity);

  url += “&dewptf=” + String(9/5.0 * (tempC – (100.0 –

humidity) /5.0) + 32.0);

  HTTPClient http;

  http.begin(url);

  int httpCode = http.GET();

  delay(1000);

  http.end();

  delay(1000);

  ESP.deepSleep(3600L*1000000L);  }

Așa cum am precizat și anterior, serviciul Weather Underground este un serviciu independent de prognoză meteorologică bazată în principal de rețele de stații meteo proprii (în SUA) sau private (PWS – Personal Weather Station, în restul lumii). Platforma online a acestui serviciu permite înregistrarea datelor provenite de la orice PWS și realizarea de prognoze de evoluție a vremii zonale ca o alternativă mult mai rafinată la serviciile naționale de meteorologie. Serviciul este gratuit dar necesită înregistrare. Un utilizator poate înregistra mai multe stații meteo aflate în locații diferite. Imediat după înregistrarea stației meteo personale se poate porni sistemul și datele înregistrate vor apărea imediat în fereastra asociată stației respective.

4

După o perioadă de 24 – 48 de ore, dacă datele raportate sunt valide – se încadrează într-un interval de valori decent de apropiat ca celelalte stații meteo din zonă, stația meteo va apărea și în WunderMap și va putea fi văzută de orice alt utilizator al serviciului. WunderMap poate fi consultată în varianta web sau în varianta de mobil (la fel și prognozele meteorologice furnizate de Weather Underground).

5

Buton Sonerie WiFi

Chiar dacă vechile sonerii (manuale sau cu fir) își au un farmec aparte, totuși, soneriile fără fir au devenit un lucru obișnuit la momentul actual datorită ușurinței de instalare. În cadrul lecției de față vă propunem realizarea unei sonerii formată doar din butonul de afară – avertizarea sonoră specifică va fi înlocuită, grație unei conexiuni WiFi, cu trimiterea unui email sau o avertizare pe telefonul mobil. Utilizând o astfel de sonerie puteți fi anunțat că este cineva la ușă chiar dacă nu sunteți acasă.

Pentru implementare vom utiliza un modul WiFi ESP8266-01S. Acest tip de modul bazat pe circuitul ESP8266 are un cost foarte mic dar este destul de dificil de utilizat spre deosebire de alte plăci de dezvoltare bazate pe același circuit. Modulul este gândit să fie utilizat ca modul WiFi serial pentru alte plăci de dezvoltare, vine preprogramat cu un firmware ce acceptă comenzi de tip AT. În plus, forma conectorului de pe acest modul nu dă posibilitatea de a fi folosit cu un breadboard. În cadrul lecției de față vom programa direct modulul fără a utiliza facilitatea de comunicație serială AT, vom utiliza modulul ca placă de dezvoltare. Pentru interconectarea modulului recomandăm utilizarea unor fire de interconectare de tip mamă-tată pentru a putea face legăturile cu un breadboard. Pentru mai multe informații legate de funcționarea modulului puteți consulta și materialul „ESP8266 WiFi Module for Dummies”.

3

Programarea modulului necesită un modul FTDI de 3.3V și instalarea extensiei ESP8266 Community sub Arduino IDE. Pentru mai multe detalii puteți consulta și materialul „How to Install the ESP8266 Board in Arduino IDE”. Conexiunile dintre modulul ESP8266-01S și programatorul FTDI necesare încărcării programului sunt următoarele:

  • Pinii GND și GPIO0 ai modulului ESP8266 se conectează la pinul GND al programatorului. Pinul GPIO0 este necesar să fie conectat la masă pentru programare.
  • Pinii VCC și CH_PD ai modulului ESP8266 se conectează la pinul VCC (adică 3.3V!!!) al programatorului. Pinul CH_PD se va menține conectat la VCC pe tot parcursul funcționării modulului – este pinul de activare al modulului.

4

  • Pinul RX al modulului ESP8266 se conectează la pinul TX al programatorului.
  • Pinul TX al modulului ESP8266 se conectează la pinul RX al programatorului.

Programul a fost dezvoltat și testat utilizând Arduino IDE 1.8.3 cu extensia ESP8266 Community 2.3.0 instalată. Pentru programare se selectează placa de dezvoltare ”Generic ESP8266 Module”. În cadrul programului trebuie personalizate datele de conectare WiFi (variabilele ssid și pass).

#include <ESP8266WiFi.h>

#include <ESP8266HTTPClient.h>

char ssid[] = “…”;

char pass[] = “…”;

WiFiClient client;

void setup() {

  WiFi.begin(ssid, pass);

  delay(5000);

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

    delay(60000);

    ESP.restart();

  }

  IFTTTpublish();

  ESP.deepSleep(0);

}

void loop() {

}

Programul transmite prin Internet către serviciul IFTTT evenimentul de apăsare a butonului (procedura IFTTTpublish). Serviciul IFTTT permite redirectarea evenimentului către utilizator sub forma unui email, a unui avertizări pe telefonul mobil sau orice altă variantă dorită. În cadrul procedurii trebuie personalizate datele de identificare a evenimentului IFTTT Webhooks (variabilele KEY și EVENT) prin care se fac legătura între sistemul nostru și platforma IFTTT.

void IFTTTpublish() {

  String KEY = “…”;

  String EVENT = “ButonSonerie”;

  HTTPClient http;

  String data = String(“http” + “://maker.ifttt.com/trigger/” + EVENT + “/with/key/”) + KEY ;

  http.begin(data);

  int httpCode = http.GET();

  delay(500);

  http.end();

}

Sistemul nostru va funcționa în regim de consum redus în mod continuu (indus de instrucțiunea ESP.deepSleep(0) din secțiunea setup). Butonul va fi conectat pe pinul de RESET al modulului și va activa sistemul doar pentru a semnaliza evenimentul către platforma IFTTT după care va intra din nou în regim de consum redus. Acest lucru este extrem de util dacă dorim să alimentăm sistemul nostru de la o baterie sau un acumulator. Pentru buton vom utiliza un brick pentru o interconectare mai ușoară. Brick-ul este gândit să tragă linia OUT la VCC dar pinul de RESET al modulului ESP8266 necesită tragerea la masă din acest motiv vom inversa conectarea brick-ului (vom conecta VCC la GND și GND la VCC):

5

Atenție!!! Modulul ESP8266-01S nu are regulator de tensiune integrat. El trebuie alimentat fix la 3.3V. În plus necesită un curent destul de mare, nu poate fi alimentat din programatorul FTDI decât pe perioada programării. Pentru testare recomandăm o sursă de breadboard și pentru funcționarea autonomă un regulator Step-Down de 3.3V (de exemplu) pentru o alimentare de la un acumulator LiPo de 3.7V sau 7.2V.

Utilizarea serviciului IFTTT necesită înregistrare (gratuită). După înregistrare și conectarea la platforma IFTTT vom crea o nouă aplicație (New Applet) în care evenimentul this va fi de tipul Webhooks iar efectul that va fi de tipul Android Device / play a specific song.

6 7 8

Bineînțeles, așa cum am precizat anterior, efectual poate fi modificat după dorință în Email, SMS, postare web etc. sau ce vi se pare potrivit ca avertizare pentru butonul de sonerie. Este adevărat că sistemul propus în această lecție poate servi la fel de bine ca buton de panică, buton de recepție sau buton pentru servitori 😊. În cadrul efectului Play a specific song se va specifica denumirea unei piese aflată pe mobilul care trebuie să aibă aplicație IFTTT instalată. Dacă melodia nu este găsită se va deschide în mod automat pagina Youtube și va fi căutată. Vă recomandăm să încercați ”jinjer words of wisdom”.

Ceas IoT cu programare OTA

Realizarea unui ceas electronic este un proiect simplu dacă utilizăm o placă de dezvoltare programabilă dar asta nu înseamnă că nu există anumite provocări și în acest caz. Una din provocările majore ale implementării unui ceas electronic este acuratețea menținerii orei (asigurarea orei exacte). Acest lucru se realizează de obicei prin utilizarea unui modul RTC dar în cadrul proiectului de față vom utiliza o placă de dezvoltare NodeMCU care prin conectivitatea WiFi de care dispune ne va permite să realizăm o sincronizare de timp în rețea de tip NTP. Astfel nu vom avea nevoie de nici o componentă suplimentară pentru a asigura ora exactă.

Pentru afișare vom utiliza un ecran LCD grafic cu rezoluția de 84×48 pixeli de tip PCD8544 (LCD de Nokia 5110).

2

Funcționalitatea specială propusă în această lecție este adăugarea sistemului unei funcționalități de tip IoT adică raportarea prin Internet a unui parametru de mediu către o platformă IoT. Sistemul va măsura (și afișa) temperatura și o va trimite pentru înregistrare către platforma Robofun IoT. Astfel sistemul nostru nu va avea simpla funcționalitate de ceas/termometru electronic ci și de senzor IoT. Pentru măsurarea temperaturii vom utiliza un senzor digital brick DS18B20. Acest senzor are o acuratețe mare în măsurarea temperaturii, nu necesită decât 3 fire pentru conectarea la placa de dezvoltare și, cel mai interesant, permite de conectarea (pe aceleași trei fire) a mai multor senzori – sistemul poate fi extins foarte ușor prin adăugarea de noi senzori ce măsoară temperatura în zone diferite (interior / exterior, diverse camere etc.).

3

Ultima funcționalitate interesantă propusă pentru sistemul prezentat în această lecție este posibilitatea de programare la distanță – programare OTA (Over-The-Air). Pentru a reprograma / reîncărca programul nu este nevoie să desfacem carcasa sistemului și să conectăm placa de dezvoltare la calculator ci acest lucru poate fi făcut prin conexiunea WiFi a plăcii de dezvoltare. Singura limitare a acestei metode este că dimensiunea programului nu poate depăși jumătate din memoria program a plăcii de dezvoltare dar nu este cazul sistemului nostru.

4

Interconectarea componentelor (placă de dezvoltare, senzor de temperatură și ecran LCD) este prezentată în diagrama următoare:

5

Senzorul de temperatură va avea pinul D0 conectat la pinul D2 al plăcii de dezvoltare iar pinii 5V și GND la pinii 3.3V și GND ai plăcii de dezvoltare (senzorul funcționează la tensiuni între 3V și 5.5V). Chiar dacă programul prezentat în cele ce urmează este gândit pentru un sistem cu un singur senzor, sistemul acceptă adăugarea pe aceleași 3 fire a mai multor senzori de temperatură pe distanțe de până la 200 de metri.

Ecranul LCD comunică cu placa de dezvoltare prin protocoul SPI și implică următoarele conexiuni:

  • Pinul 1 (RST) al ecranului LCD se conectează la pinul D0 al plăcii de dezvoltare;
  • Pinul 2 (CE) al ecranului la pinul D1 al plăcii de dezvoltare;
  • Pinul 3 (DC) al ecranului la pinul D6 (HMISO) al plăcii de dezvoltare;
  • Pinul 4 (DIN) al ecranului la pinul D7 (HMOSI) al plăcii de dezvoltare;
  • Pinul 5 (CLK) al ecranului la pinul D5 (HSCLK) al plăcii de dezvoltare;
  • Pinul 6 (VCC) al ecranului la un pin de 3.3V al plăcii de dezvoltare;
  • Pinul 7 (LIGHT) al ecranului nu este conectat în schema noastră. Acest pin comandă aprinderea luminii de fundal a ecranului. Se poate conecta la un pin digital liber pentru comandă digitală sau PWM;
  • Pinul 8 (GND) al ecranului la un pin GND al ecranului.

Programul a fost dezvoltat și testat utilizând Arduino IDE 1.8.3 cu extensia ESP8266 Community 2.3.0 instalată. Prima încărcare a programului necesită conectarea plăcii la calculator prin intermediul cablului USB dar ulterior placa va putea fi reprogramată prin OTA (calculatorul de pe care se face programarea trebuie să fie în aceiași rețea ca placa NodeMCU):

6

#include <ESP8266WiFi.h>

#include <ESP8266HTTPClient.h>

#include <ESP8266mDNS.h>

#include <WiFiUdp.h>

#include <ArduinoOTA.h>

Programul utilizează și următoarele biblioteci: Time 1.5.0 – pentru a menține data și ora, sincronizarea NTP se face automat de către bibliotecă la intervale mai mari de timp; OneWire 2.3.3 și DallasTemperature 3.7.6 – pentru comunicația cu senzorul de temperatură; Adafruit GFX 1.2.2 și Adafruit PCD8544 versiune modificată pentru ESP8266 – pentru partea de afișare pe ecranul LCD. În cadrul programului trebuie personalizate datele de conectarea WiFi (variabilele ssid[] și pass[]). Constanta timeZone indică fusul orar (2 sau 3 pentru România, oră de iarnă sau vară).

#include <TimeLib.h>

const int timeZone = 3;

WiFiUDP Udp;

const int NTP_PACKET_SIZE = 48;

byte packetBuffer[NTP_PACKET_SIZE];

unsigned int localPort = 2390;   

char ssid[] = “…”;

char pass[] = “…”;

WiFiClient client;

#define HOSTNAME “ESP8266-OTA-“

#include <DallasTemperature.h>

#include <OneWire.h>

#define ONE_WIRE_BUS D2

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

#include <SPI.h>

#include <Adafruit_GFX.h>

#include <Adafruit_PCD8544.h>

const int8_t RST_PIN = D0;

const int8_t CE_PIN = D1;

const int8_t DC_PIN = D6;

Adafruit_PCD8544 display =

Adafruit_PCD8544(DC_PIN, CE_PIN, RST_PIN);

Secțiunea setup() se va ocupa cu inițializarea conexiunii WiFi (în cazul unei erori pe ecranul LCD va apărea mesajul !WiFi și sistemul va intra într-o buclă de reinițializarea până la conectarea la rețea), inițializarea rețelei OneWire de senzori, inițializarea ecranului și a rutinei de programare OTA. În cazul unei inițializări normale pe ecranul LCD vor apărea informații legate de inițializarea sistemului (denumirea OTA, denumirea rețelei WiFi, adresa IP).

void setup() {

  sensors.begin();

  delay(100);

  display.begin();

  display.setContrast(60);

  display.setTextColor(BLACK);

  display.setCursor(0,0);

  display.setTextSize(1);

  display.clearDisplay();

  display.display();

  String hostname(HOSTNAME);

  hostname += String(ESP.getChipId(), HEX);

  WiFi.hostname(hostname);

  display.println(“Hostname:” + hostname);

  display.display();

  WiFi.begin(ssid, pass);

  delay(5000);

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

    display.clearDisplay();

    display.setCursor(17,16);

    display.setTextSize(2);

    display.print(“!WiFi”);

    display.display();

    delay(10000);

    ESP.restart();

  }

  display.print(“Connected to “);

  display.println(ssid);

  display.print(“IP:”);

  display.println(WiFi.localIP());

  Udp.begin(localPort);

  setSyncProvider(getNtpTime);

  ArduinoOTA.setHostname((const char *)hostname.c_str());

  ArduinoOTA.begin();

  display.display();

  delay(1000);

  display.clearDisplay();

  display.display(); }

Secțiunea loop() se va ocupa cu achiziția parametrului temperatură și cu partea de afișare. Apelarea rutinei de postare IoT se va face la un interval de o oră (constanta postingInterval). Pe ecranul LCD vor apărea alternativ (câte 30 de secunde fiecare) ora/data și temperatura. Ecranul de afișare al temperaturii va conține și mesajul OK/Fail indicând dacă ultima postare IoT s-a efectuat cu succes sau nu (astfel sistemul are și o funcționalitate de supraveghere a bunei funcționări a serviciului IoT).

7

8

unsigned long lastConnectionTime = 0;

const unsigned long postingInterval = 60L * 60L * 1000L;

boolean myiot_ok;

void loop() {

    ArduinoOTA.handle();

    sensors.requestTemperatures();

    delay(100);

    float temperature = sensors.getTempCByIndex(0);

    display.clearDisplay();

    if (second()<30) {

      display.drawRoundRect(2,2,80,44,3,BLACK);

      display.setTextColor(BLACK);

      display.setCursor(13,10);

      display.setTextSize(2);

      printDigits(hour(),false);

      printDigits(minute(),true);

      display.println();

      display.setTextSize(1);

      display.setCursor(13,26);

      display.print(day());

      display.print(“/”);

      display.print(month());

      display.print(“/”);

      display.print(year());

      display.println();

      display.display(); 

    }

    else {

      display.fillScreen(BLACK);

      display.drawRoundRect(2,2,80,44,3,WHITE);

      display.setTextColor(WHITE);

      display.setTextSize(2);

      display.setCursor(22,10);

      display.print((int)temperature);

      display.print((char)247);

      display.println(“C”);

      display.setTextSize(2);

      if (myiot_ora!=-1) {

        if (myiot_ok) { 

          display.setCursor(30,26);

          display.println(“OK”);    }

        else {

          display.setCursor(20,26);

          display.println(“FAIL”); }

      }

      display.display();

    }

    if (millis() – lastConnectionTime > postingInterval) {

      if (IoTpublish(temperature)>0)

        { myiot_ok=true; }

      else

        { myiot_ok=false; }

    }

}

Funcția IoTpublish este responsabilă cu postarea IoT și returnează codul returnat de operația HTTP GET efectuată. În cadrul acesteia trebuie completată cheia de autentificare oferită de serviciul Robofun IoT (variabila SENSOR_TOKEN). Procedura printDigits este folosită pentru afișarea mai simplă a orei.

int IoTpublish(float temperature) {

  String SENSOR_TOKEN = “…”;

  HTTPClient http;

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

  http.begin(data);

  int httpCode = http.GET();

  delay(100);

  if(httpCode > 0) {

      if(httpCode == HTTP_CODE_OK) {

        String payload = http.getString();

      }

   }

  http.end();

  lastConnectionTime = millis();

  return httpCode;

}

void printDigits(int digits, boolean dots){

   if (dots) display.print(“:”);

  if(digits < 10)

    display.print(‘0’);

  display.print(digits);

}

Funcțiile getNtpTime și sendNTPpacket sunt apelate automat de către biblioteca Time și asigură partea de comunicație NTP. Constanta ntpServerName indică serverul NTP care este utilizat pentru sincronizarea de timp.

IPAddress timeServerIP;

const char* ntpServerName = “time.nist.gov”;

time_t lastsyncr;

time_t getNtpTime() {

  WiFi.hostByName(ntpServerName, timeServerIP);

  while (Udp.parsePacket() > 0) ;

  sendNTPpacket(timeServerIP);

  uint32_t beginWait = millis();

  while (millis() – beginWait < 2500) {

    int size = Udp.parsePacket();

    if (size >= NTP_PACKET_SIZE) {

      Udp.read(packetBuffer, NTP_PACKET_SIZE);

      unsigned long secsSince1900;

      secsSince1900 =  (unsigned long)packetBuffer[40]

<< 24;

      secsSince1900 |= (unsigned long)packetBuffer[41]

<< 16;

      secsSince1900 |= (unsigned long)packetBuffer[42]

<< 8;

      secsSince1900 |= (unsigned long)packetBuffer[43];

      lastsyncr = (time_t) (secsSince1900 – 2208988800UL +

timeZone * SECS_PER_HOUR);

      return lastsyncr;

    }

  }

  return 0;

}

void sendNTPpacket(IPAddress &address) {

  memset(packetBuffer, 0, NTP_PACKET_SIZE);

  packetBuffer[0] = 0b11100011;  

  packetBuffer[1] = 0; 

  packetBuffer[2] = 6; 

  packetBuffer[3] = 0xEC; 

  packetBuffer[12]  = 49;

  packetBuffer[13]  = 0x4E;

  packetBuffer[14]  = 49;

  packetBuffer[15]  = 52;

  Udp.beginPacket(address, 123);

  Udp.write(packetBuffer, NTP_PACKET_SIZE);

  Udp.endPacket(); }

După o oră după punerea în funcțiune a sistemului se pot consulta datele înregistrate în cadrul platformei Robofun IoT. Mai jos este o captură de ecran cu datele înregistrate de către sistemul de test în decursul unei zile.

9