Sistem de monitorizare a unui UPS

Dispozitivele de tip UPS (Uninterruptible Power Supply) asigură protecție pentru sistemele electronice împotriva variațiilor de tensiune ale rețelelor de alimentare și împotriva căderilor de tensiune permițând funcționarea continuă. În cazul căderilor de tensiune de scurtă durată sistemele nu își vor întrerupe funcționarea dar în cazul căderilor de mai mare durată sistemele electronice, mai ales sistemele de calcul și dispozitivele de stocare a datelor, trebuie închise în siguranță fără a exista pericolul defectării sau pierderilor de date. Procesul de închidere controlat se poate face de către utilizator, dacă este prezent, sau în mod automat dacă sistemul UPS are capabilitatea de a semnaliza căderea tensiunii de alimentare. În cadrul materialului de față ne propunem să prezentăm implementarea unui sistem de monitorizare a funcționării unui dispozitiv UPS care să permită închiderea automată, în siguranță, a sistemelor de calcul.

Pentru implementare vom utiliza o placă de dezvoltare Raspberry Pi Zero W (se poate utiliza și o placă Raspberry Pi 3) ce va comunica cu dispozitivul UPS printr-o conexiune USB. Se pot monitoriza orice dispozitive UPS care au facilitatea de raportare printr-o astfel de conexiune. În teste s-a utilizat un dispozitiv UPS APC Back-UPS ES550. Pentru conectarea la placa Raspberry Pi Zero W este necesar un adaptor OTG USB.

2

Ca sistem de operare pentru placa de dezvoltare Raspberry Pi Zero W a fost folosită versiunea Lite a sistemului de operare Raspbian, mai exact Raspbian Stretch Lite 2018-06-27. După copierea imaginii pe cardul microSD se recomandă configurarea pentru accesul la distanță înainte de pornirea plăcii de dezvoltare, a se vedea și „Raspberry Pi Zero Headless Quick Start”:

  • Se creează un fișier gol cu numele ssh pentru a activa conectarea de la distanță;
  • Se creează un fișier conf pentru conectarea la rețea cu următorul conținut:

    ctrl_interface=DIR=/var/run/wpa_supplicant

   GROUP=netdev

   update_config=1

   network={

        ssid=”YOURSSID”

        psk=”YOURPASSWORD”

        scan_ssid=1

    }

După pornirea sistemului și conectarea UPS-ului la placa de dezvoltare putem verifica conexiunea cu ajutorul comenzii:

# lsusb

3

Dacă totul este în regulă vom trece la instalarea pachetelor necesare supravegherii dispozitivului UPS:

# sudo apt-get update

# sudo apt-get upgrade (recomandat)

# sudo apt-get install apcupsd

Pentru mai multe informații asupra programului APC UPS Daemon puteți consulta manualul oficial. Înainte de utilizare trebuie să efectuăm câteva modificări în fișierul de configurare /etc/apcupsd/apcupsd.conf:

UPSNAME MyAPC

UPSCABLE usb

USBTYPE usb

DEVICE

și în fișierul /etc/default/apcupsd:

ISCONFIGURED=yes

Finalmente putem repornim serviciul:

# sudo apcupsd restart

Testarea comunicației cu dispozitivul UPS se va face cu ajutorul comenzii:

# apcaccess status

4

Supravegherea se poate face și prin intermediul unei interfețe web. Pentru acest lucru vom instala serverul web apache și componenta cgi a APC UPS Daemon:

# sudo apt-get install apache2 apcupsd-cgi

Pentru a activa execuția fișierelor cgi la nivel de server web este necesară realizarea unei legături simbolice la nivelul fișierelor de configurare apache:

# cd /etc/apache2/mods-enabled

# sudo ln -s ../mods-available/cgi.load

# sudo /etc/init.d/apache2 restart

Interfața web poate fi accesată la adresa:

http://YOUR_RPi_IP/cgi-bin/apcupsd/multimon.cgi

5

6

În fișierul de configurare /etc/apcupsd/apcupsd.conf putem personaliza diverși parametrii (precum procentul din baterie la care sistemul să se oprească automat, timpul de funcționare pe baterie):

ONBATTERYDELAY 6

BATTERYLEVEL 5

MINUTES 3

În mod implicit la apariția evenimentelor de cădere a alimentării și la revenirea alimentării serviciul APC UPS Daemon rulează scripturile /etc/apcupsd/onbattery și /etc/apcupsd/offbattery. Acestea pot fi personalizate pentru a efectua diverse operații dorite (să trimită email, să oprească automat alte sisteme de calcul etc.).

Pentru mai multe informații puteți consulta și proiectele:

Și ca o alternativă la software-ul de monitorizare:

Sistemul de monitorizare este capabil să comande oprirea în siguranță a mai multor sisteme de calcul inclusiv sisteme ce rulează sisteme de operare Microsoft Windows – a se vede materialul: „How to Remotely Shut Down or Restart Windows PCs”.

Repetor WiFi cu legătură GSM de siguranță

Dispozitivele de tip repetor au ca principal scop extinderea acoperirii semnalului pentru o rețea radio. Repetoarele WiFi extind acoperirea unei rețele WiFi astfel încât să nu fie necesară instalarea și managementul mai multor dispozitive de tip AP. În cadrul materialului de față vă propunem implementarea unui dispozitiv repetor WiFi cu o funcționalitate suplimentară față de un repetor standard: dirijarea traficului pe o conexiune de date GSM în cazul în care conexiunea WiFi se întrerupe. Astfel, sistemul se va comporta ca un repetor WiFi în mod obișnuit dar se va transforma într-un router WiFi GSM în cazul în care conexiunea principală are probleme (a se vedea și materialul „Router WiFi GSM utilizând LinkIt Smart 7688”).

Pentru implementare vom utiliza o placă de dezvoltare LinkIt Smart 7688 bazată pe circuitul SoC MediaTek MT7688AN și care rulează distribuția Linux OpenWRT. Această placă de dezvoltare oferă, la un preț redus, toate facilitățile de routare, filtrare și control al traficului TCP/IP oferite de sistemele de operare Linux. Pentru mai multe detalii legate de funcționarea și utilizarea plăcii de dezvoltare LinkIt Smart 7688 puteți consulta wiki-ul oficial. Pentru conexiunea de date GSM vom utiliza un modem USB GSM 3G. Conectarea modemului USB la placa de dezvoltare necesită un adaptor microUSB – USB. Alimentarea sistemului se va face la 5V, minim 500mA – preferabil 1A (orice încărcător de mobil de 1A și mufă microUSB e bun).

2

Placa de dezvoltare LinkIt Smart 7688 oferă posibilitatea de funcționare în mod repetor începând cu versiunea 0.9.4 de firmware. Nu vom utiliza modalitatea de configurare oferită de interfața web, configurarea inițială va fi de Station mode (client WiFi) deoarece vom avea nevoie de conexiunea Internet pentru a instala câteva pachete software suplimentare.

3

După configurarea și repornirea plăcii ne putem conecta la aceasta prin SSH (utilizând PUTTY de exemplu). IP-ul de conectare depinde de rețeaua locală. Vom rula următoarele comenzi pentru instalarea pachetelor software necesare configurării conexiunii de date GSM:

# opkg update

# opkg install comgt kmod-usb-serial kmod-usb-serial-option kmod-usb-serial-wwan usb-modeswitch usbtools

Eventual putem instala și un editor de text suplimentar dacă nu ne place vi :

# opkg install nano

Sistemul va avea două configurații diferite de rețea între care va comuta în cazul întreruperii / restaurării conexiunii WiFi principale. Vom crea în directorul /root două directoare config_wifi și config_3g și în fiecare vom crea 3 fișiere de configurare: firewall, network și wireless (se pot copia din /etc/config pentru a nu le tasta de la zero).

Fișierul network – varianta wifi – nu definește nici o interfață utilizată în funcționalitatea de repetor.

config interface ‘loopback’

option ifname ‘lo’

option proto ‘static’

option ipaddr ‘127.0.0.1’

option netmask ‘255.0.0.0’

config globals ‘globals’

option ula_prefix ‘fdea:6296:e400::/48’

config interface ‘lan’

option force_link ‘1’

option macaddr ‘9c:65:f9:1e:69:77’

option proto ‘static’

option netmask ‘255.255.255.0’

option ip6assign ’60’

option ipaddr ‘192.168.100.1’

option delegate ‘0’

option ifname ‘ra0’

config switch

option name ‘switch0’

option reset ‘1’

option enable_vlan ‘0’

config interface ‘wan’

option proto ‘dhcp’

Fișierul network – varianta 3G – va arăta identic dar va avea în plus definiția interfeței de comunicație GSM (se va adăuga la sfârșitul fișierului anterior). APN-ul și codul pin se vor personaliza în funcție de cartela SIM GSM.

config interface ‘gsm’

option proto ‘3g’

option device ‘/dev/ttyUSB0’

option service ‘umts’

option apn ‘net’

option pincode ‘0000’

Fișierul wireless – varianta WiFi – va defini funcționarea în mod mixt AP+STA. În fișier trebuie personalizate datele de acces la rețeaua WiFi (secțiunea STA) și datele de conectare la repetor (secțiunea AP) – pot fi identice, repetorul poate oferi acces cu aceleași credențiale ca și rețeaua WiFi originală.

config wifi-device ‘radio0’

option type ‘ralink’

option variant ‘mt7628’

option country ‘TW’

option hwmode ’11g’

option htmode ‘HT40’

option channel ‘auto’

option disabled ‘0’

option linkit_mode ‘apsta’

config wifi-iface ‘ap’

option device ‘radio0’

option mode ‘ap’

option network ‘lan’

option ifname ‘ra0’

option encryption ‘psk2’

option seq ‘1’

option ssid ‘xxxxxx’

option key ‘xxxxxx’

config wifi-iface ‘sta’

option device ‘radio0’

option mode ‘sta’

option network ‘wan’

option ifname ‘apcli0’

option led ‘mediatek:orange:wifi’

option ssid ‘xxxxx’

option key ‘xxxxx’

option encryption ‘psk2’

Fișierul wireless – varianta 3G  – va defini funcționarea doar în mod AP. În cazul în care definim aceleași credențiale ca și AP-ul principal, sistemul va suplini conexiunea WiFi și pentru clienții direcți ai AP-ului principal în cazul întreruperii conexiunii principale.

config wifi-device ‘radio0’

option type ‘ralink’

option variant ‘mt7628’

option country ‘TW’

option hwmode ’11g’

option htmode ‘HT40’

option channel ‘auto’

option disabled ‘0’

option linkit_mode ‘ap’

config wifi-iface ‘ap’

option device ‘radio0’

option mode ‘ap’

option network ‘lan’

option ifname ‘ra0’

option encryption ‘psk2’

option seq ‘1’

option ssid ‘xxxxxx’

option key ‘xxxxxx’

Fișierul firewall – variantele WiFi și 3G diferă de fișierul original din /etc/config doar prin linia option network a secțiunii wan.

———————————- WiFi ——————————-

config zone

option name ‘wan’

option network ‘wan wan6’

option output ‘ACCEPT’

option forward ‘REJECT’

option masq ‘1’

option mtu_fix ‘1’

option input ‘ACCEPT’

———————————- 3G ——————————-

config zone

option name ‘wan’

option network ‘gsm’

option output ‘ACCEPT’

option forward ‘REJECT’

option masq ‘1’

option mtu_fix ‘1’

option input ‘ACCEPT’

Scripturile care vor face comutarea între cele două configurații de rețea (între cele două funcționalități ale sistemului) se vor crea în directorul /root sub denumirile: switch și normal (nu uitați să dați drepturi de execuție pe cele două fișiere # chmod +x …). Fișierul switch va face comutarea pe conexiunea GSM în cazul în sistemul nu are conexiune la Internet:

#!/bin/ash

ping -q -c 1 -W 10 8.8.8.8 > /dev/null

if [ $? -ne 0 ]

then

cp -f /root/config_3g/network /etc/config/network

cp -f /root/config_3g/firewall

/etc/config/firewall

cp -f /root/config_3g/wireless

/etc/config/wireless

/etc/init.d/network restart

fi

Scriptul normal va verifica dacă este în modul GSM (prin verificarea conexiunii cu AP-ul principal – scriptul trebuie personalizat cu adresa IP a AP-ului principal) și va reîncerca reintrarea în mod repetor WiFi:

#!/bin/ash

ping -q -c 1 -W 10 XXX.XXX.XXX.XXX > /dev/null

if [ $? -ne 0 ]

then

cp -f /root/config_wifi/network

/etc/config/network

cp -f /root/config_wifi/firewall

/etc/config/firewall

cp -f /root/config_wifi/wireless

/etc/config/wireless

/etc/init.d/network restart

fi

Ambele scripturi vor fi rulate în mod automat de serviciul cron al sistemului de operare. Frecevența de execuție stă la latitudinea utilizatorului, testele au fost realizate cu o frecvență de o dată pe oră (la fix scriptul switch, la și jumătate scriptul normal), conținutul fișierului /etc/crontabs/root fiind:

00 * * * * /root/switch

30 * * * * /root/normal

Sistemul prezentat poate fi folosit în diverse scenarii, de exemplu:

  • Într-o locuință de dimensiuni mari pentru a extinde semnalul WiFi în toate camerele și pentru a oferi o conexiune de siguranță la Internet pentru cazurile de întrerupere a conexiunii principale. În acest caz credențialele de acces pot fi comune între AP-ul principal și repetor.
  • Pentru o rețea de senzori WiFi se poate oferi o rețea WiFi dedicată, eventual o zonă de acoperire specială utilizând o antenă direcțională, și care are legătură la Internet redundantă (ISP / GSM) având în vedere un posibil caracter critic a funcționalității.

Router WiFi GSM utilizând LinkIt Smart 7688 Duo

Chiar dacă implementarea funcționalității de router WiFi GSM utilizând familia de plăci LinkIt Smart 7688 nu este nouă în cadrul lecțiilor noastre, o să încercăm în materialul de față să propunem o versiune îmbunătățită a acestui tip de sistem. Placa de dezvoltare LinkIt Smart 7688 Duo, spre deosebire de placa LinkIt Smart 7688, deține un microcontroler ATmega32U4 ce poate fi utilizat în cadrul sistemului pentru diverse sarcini de timp real (comandă de motoare, interfață utilizator, achiziție de valori de la diverși senzori etc.). În cadrul sistemului nostru vom utiliza microcontrolerul prezent pe placa de dezvoltare pentru implementarea interfeței utilizator, mai exact vom adăuga sistemului un ecran ce va afișa în timp real date despre funcționarea routerului (număr de clienți WiFi, puterea semnalului GSM, traficul prin intermediul routerului).

Pentru configurarea de bază a routerului se vor efectua exact aceeași pași ca și în cazul plăcii LinkIt Smart 7688 (a se vedea și „Router WiFi GSM utilizând LinkIt Smart 7688”), mai exact (pe scurt):

  • Vom configura placa în mod client WiFi pentru a putea instala pachetele necesare funcționării modemului GSM;
  • Vom instala și configura modemul GSM prin definirea unei noi interfețe de rețea;
  • Noua interfață de rețea va fi introdusă în firewall în zoua wan și vom configura pornirea automată a interfeței la pornirea sistemului de operare;
  • Vom reconfigura placa în modul AP setând numele și parola de acces dorită.

Pentru afișare vom utiliza un ecran OLED monocrom ce va comunica cu placa de dezvoltare prin I2C:

  • Alimentarea se va face la 3.3V (3.3V conectat la 3.3V, GND la GND);
  • Pinul Data al afișajului la pinul D2 (SDA) al plăcii de dezvoltare;
  • Pinul Clk al afișajului la pinul D3 (SCL) al plăcii de dezvoltare;
  • Pinul Rst al afișajului la pinul D5 al plăcii de dezvoltare (opțional).

2

Programul (pentru microcontrolerul ATmega32U4) va utiliza bibliotecile Adafruit GFX și Adafruit SSD1306 pentru partea de comunicație cu ecranul OLED și biblioteca Process (Bridge) pentru a comunica cu sistemul de operare OpenWRT.

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#define OLED_RESET 5

Adafruit_SSD1306 display(OLED_RESET);

#include <Process.h>

Secțiunea setup() va inițializa ecranul OLED și comunicația cu sistemul de operare OpenWRT. Ecranul va afișa mesajul Initializing… pâna la încărcarea și inițializarea sistemului de operare (funcția Bridge.begin() va bloca programul până la stabilirea comunicației cu sistemul de operare).

3

void setup() {

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

  display.display();

  delay(2000);

  display.clearDisplay();

  display.setTextSize(1);

  display.setTextColor(WHITE);

  display.setCursor(0,0);

  display.println(“Initializing…”);

  display.display();

  delay(1);

  Bridge.begin();

  delay(1000);

}

Secțiunea loop() este responsabilă cu interogarea sistemului de operare și afișarea răspunsurilor pe ecranul OLED. Pe prima linie este afișată ora și data (utile pentru a verifica dacă sistemul funcționează corect, nu s-a blocat), a doua linie va afișa calitatea semnalului GSM (utilă pentru poziționarea unei antene externe), a treia linie va afișa numărul de clienți WiFi iar ultima linie cantitatea de informație (recepționată și transmisă) transferată prin intermediul conexiunii GSM (informații utile în cazul unui abonament de date cu limitări la datele transferate). Datele sunt împrospătate o dată la 30 de secunde.

4

void loop() {

  Process MyProc;

  display.clearDisplay();

  display.setTextSize(1);

  display.setTextColor(WHITE);

  display.setCursor(0,0);

  MyProc.runShellCommand(“date +%H:%M”);

  while (MyProc.available() > 0) {

    char c = MyProc.read();

  if (c!=’\n’) display.print((char)c);

  }

  display.print(” “);

  MyProc.runShellCommand(“date +%D”);

  while (MyProc.available() > 0) {

    char c = MyProc.read();

    if (c!=’\n’) display.print((char)c);

  }

  display.println();

  display.println();

  display.print(“RSSI:”);

  MyProc.runShellCommand(“/root/get_rssi”);

  while (MyProc.available() > 0) {

      char c = MyProc.read();

      if (c!=’\n’) display.print((char)c);

  }

  display.println();

  display.println();

  display.print(“Clients:”);

  MyProc.runShellCommand(“/root/clients”);

  while (MyProc.available() > 0) {

      char c = MyProc.read();

      if (c!=’\n’) display.print((char)c);

  }

  display.println();

  display.println();

  MyProc.runShellCommand(“ifconfig 3g-gsm | grep ‘RX bytes’ | awk ‘{ print $1 $3 $4 }'”);

  while (MyProc.available() > 0) {

    char c = MyProc.read();

    if (c!=’\n’) display.print((char)c);

  }

  display.println();

  MyProc.runShellCommand(“ifconfig 3g-gsm | grep ‘RX bytes’ | awk ‘{ print $5 $7 $8}'”);

  while (MyProc.available() > 0) {

    char c = MyProc.read();

    if (c!=’\n’) display.print((char)c);

  }

  display.display();

  delay(30000);

}

Este posibil ca legătura dintre microcontrolerul ATmega32U4 și sistemul de operare OpenWRT să fie oprită implicit (să fie oprit serviciul responsabil la nivel de sistem de operare). În acest caz este necesară rularea următoarelor comenzi în linia de comenzi a sistemului de operare:

# uci set yunbridge.config.disabled=’0’

# uci commit

# reboot

Pentru rularea scripturilor de interogare a puterii semnalului și a numărului de clienți este necesară instalarea pachetului bash sub sistemul de operare OpenWRT:

# opkg update

# opkh install bash

Scriptul de interogare a puterii semnalului se va salva în diretorul /root sub denumirea get_rssi (tebuie acordate permisiuni de execuție #chmod +x get_rssi). Scriptul va interpreta o valoare pentru calitatea semnalului mai mare de 25 ca fiind excelentă, între 19 și 25 bună, între 13 și 19 medie, între 7 și 13 slabă și sub 7 foarte slabă. Lipsa semnalului poate însemna atât aflarea într-o zonă fără semnal dar și o problemă cu modemul GSM (deconectat?) sau cu SIM-ul GSM (neintrodus, fără credit?).

#!/bin/bash

rssi=`printf “%s\n” $((/usr/sbin/chat -V -s ” ‘AT+CSQ’ ‘OK’ ” > /dev/ttyUSB2 < /dev/ttyUSB2) 2>&1 | /bin/grep CSQ: | /usr/bin/awk ‘{print $2}’)`

rssi=”${rssi//,/.}”

rssi=$(printf “%.0f” $rssi)

if [ $rssi -gt 25 ]; then

        echo “$rssi Excellent”

elif [ $rssi -gt 19 ] && [ $rssi -le 25 ]; then

        echo “$rssi Good”

elif [ $rssi -gt 13 ] && [ $rssi -le 19 ]; then

        echo “$rssi Average”

elif [ $rssi -gt 7 ] && [ $rssi -le 13 ]; then

        echo “$rssi Low”

elif [ $rssi -gt 0 ] && [ $rssi -le 7 ]; then

        echo “$rssi Very low”

else

        echo “No signal”

fi

Scriptul de interogare a numărului de clienți WiFi se va salva în diretorul /root sub denumirea clients (tebuie acordate permisiuni de execuție #chmod +x clients). Scriptul va verifica numărul de înregistrări ARP din rețeaua WiFi. Atenție!!! Conectarea unui nou client WiFi va conduce la incrementarea imediată a numărului de clienți dar deconectarea nu va conduce la o decrementare decât în momentul în care expiră cache-ul ARP.

nr=0

for ip in $(cat /proc/net/arp | grep -v IP | awk ‘{print

$1}’); do

    nr=$((nr+1))

done

echo $nr

 

Dacă doriți să explorați și alte variante de implementare puteți vedea și „Smart Router With WiFi Connection Visualization”.

Router WiFi GSM utilizând LinkIt Smart 7688

Asigurarea conexiunii la Internet în cazul absenței unei conexiuni terestre (prin cablu sau fibră optică) se poate face, bineînțeles, apelând la serviciile oferite de companiile de telefonie mobilă prin intermediul unei cartele SIM ce oferă transfer de pachete de date. Există multe opțiuni comerciale pentru implementarea acestei facilități de routare între o rețea de date WiFi și o rețea GSM: routere WiFi GSM, telefoane mobile ce funcționează ca AP (tethering) ș.a.m.d. dar majoritatea acestor soluții nu oferă o flexibilitate sau un control al conexiunilor foarte bune. Din acest motiv realizarea unui router „personalizat” se poate dovedi și o soluție mult mai ieftină și o metodă de a implementa mecanisme de filtrare, autentificare, control al conexiunilor mult mai sofisticate.

Pentru implementare vom utiliza o placă de dezvoltare LinkIt Smart 7688 bazată pe circuitul SoC MediaTek MT7688AN și care rulează distribuția Linux OpenWRT. Această placă de dezvoltare oferă, la un preț redus, toate facilitățile de routare, filtrare și control al traficului TCP/IP oferite de sistemele de operare Linux. Pentru mai multe detalii legate de funcționarea și utilizarea plăcii de dezvoltare LinkIt Smart 7688 puteți consulta wiki-ul oficial. Pentru conexiunea de date GSM vom utiliza un modem USB GSM – testele au fost realizate utilizând un modem Huawei E220 dar se poate utiliza orice alt modem USB GSM compatibil. Conectarea modemului USB la placa de dezvoltare necesită un adaptor microUSB – USB. Alimentarea sistemului se va face la 5V, minim 500mA – preferabil 1A (orice încărcător de mobil de 1A și mufă microUSB e bun).

2

La punere în funcțiune a plăcii de dezvoltare aceasta funcționează în mod AP. Ne vom conecta la AP-ul LinkIt_Smart_7688_XXXXXX și apoi la interfața de administrare web (IP 192.168.100.1).

3

La prima conectare se va stabili parola utilizatorului root (contul de administrare a sistemului de operare).

4

Pentru a putea instala pachetele software necesare funcționării modemului USB GSM vom configura placa de dezvoltare ca și client WiFi – Station Mode (pentru a avea conexiune Internet).

ATENȚIE!!! Placa de dezvoltare are definită implicit o interfață de rețea cu IP-ul 192.168.100.1 . Orice încercare de a introduce placa de dezvoltare într-o rețea ce oferă prin DHCP adrese IP în clasa 192.168.100.0/24 va eșua.

După configurarea și repornirea plăcii ne putem conecta la aceasta prin SSH (utilizând PUTTY de exemplu). IP-ul de conectare depinde de rețeaua locală. Vom rula următoarele comenzi pentru instalarea pachetelor software necesare configurării conexiunii de date GSM:

# opkg update

# opkg install comgt kmod-usb-serial kmod-usb-serial-option kmod-usb-serial-wwan usb-modeswitch

Eventual putem instala și un editor de text suplimentar dacă nu ne place vi :

# opkg install nano

Având conectat modemul USB GSM vom reporni placa de dezvoltare. Ne vom reconecta prin SSH și vom verifica dacă modemul este recunoscut de sistemul de operare în mod corect (vom rula comanda dmesg).

6

În cazul în care modemul este recunoscut corect de sistemul de operare vom regăsi în jurnalul de pornire a sistemului de operare (consultat anterior cu ajutorul comenzii dmesg) linii care indică instalarea modemului GSM ca dispozitiv specific USB (ttyUSB0 de exemplu). În cazul în care modemul este văzut ca alt tip de dispozitiv (de stocare în masă – memorie usb de exemplu) înseamnă că pachetul usb-modeswitch care se ocupă de autoconfigurarea modemului nu are în baza de date proprie modelul de modem utilizat. Este recomandat să căutăm un modem care să fie deja în baza de date a pachetului software. Configurarea manuală a modemului este destul de dificilă. Pentru mai multe informații se poate parcurge materialul „Use 3g/UMTS USB Dongle for WAN connection”.

Pentru a putea accesa Internetul prin intermediul modemului USB GSM este nevoie să avem o cartelă SIM funcțională (se poate testa prealabil modemul pe un sistem de calcul obișnuit) și să realizăm următoarele configurări în fișierele sistemului de operare. În fișierul /etc/config/network vom adăuga la final (pinul și APN-ul sunt specifice cartelei SIM utilizate):

config interface ‘gsm’

        option proto ‘3g’

        option service ‘umts’

        option device ‘/dev/ttyUSB0’

        option apn ‘net’

        option pincode ‘0000’

În fișierul /etc/config/firewall vom adăuga noua interfață de rețea în categoria wan :

config zone

        option name ‘wan’

        list network ‘gsm’

        …

Pentru ca intefața GSM să fie pornită automat după repornirea sistemului vom adăuga în fișierul /etc/rc.local linia ifup gsm (comanda de pornire a conexiunii GSM) înainte de linia exit 0 .

ifup gsm

exit 0

După finalizarea configurării conexiunii GSM (se poate reporni sistemul și verifica prin intermediul comenzii route dacă există conexiune Internet GSM) se va trece sistemul în configurație AP din interfața web de administrare (se va stabili numele și parola de acces pentru rețeaua WiFi).

7

După o ultimă repornire a sistemului routerul WiFi GSM este gata de utilizare. Acesta va oferi adrese în clasa 192.168.100.0/24 și vom putea accesa interfața de administrare prin intermediul adresei IP 192.168.100.1 . Pentru configurări avansate (firewall, port-forwarding) se poate accesa consola Luci specifică sistemului de operare OpenWRT (link în interfața de administrare, încercuit cu roșu în imaginea precedentă).

În cazul în care se efectuează modificări ale sistemului de operare care conduc la stări nefericite din care nu știm cum să ieșim, există întotdeauna posibilitatea de a reseta placa la setările inițiale și de a relua procesul de configurare de la început. Pentru resetarea plăcii la setările inițiale se va ține apăsat minim 20 de secunde butonul WiFi Reset.

9

O posibilă îmbunătățire a sistemului nostru este adăugarea unei antene WiFi externe pentru creșterea puterii semnalului. Placa are un conector special I-PEX pentru acest lucru dar utilizarea acestuia necesită dezlipirea de pe placă a unei rezistențe (imagine de mai jos).

10

ESP8266 Geolocation

Localizarea geografică este o problemă rezolvată cu ajutorul mai multor tehnologii actuale. Tehnologia GPS, cea mai cunoscută și utilizată modalitate de localizare, necesită funcționarea în spații deschise și utilizarea unui receptor specializat. În dispozitivele actuale această tehnologie se utilizează în combinație cu alte metode pentru a crește acuratețea localizării și pentru a oferi posibilitatea de localizare inclusiv în interiorul clădirilor. De exemplu, în telefoanele mobile inteligente, tehnologia GPS este combinată cu triangularizarea semnalelor radio GSM  și WiFi. În cadrul materialului de față vom arăta cum putem utiliza tehnica de localizare bazată pe triangularizarea semnalului WiFi utilizând o placă de dezvoltare WiFi ESP8266 și pe serviciul cloud Google Geolocation API. O astfel de soluție permite realizarea unui dispozitiv de localizare mult mai ieftin decât dispozitivele comerciale bazate pe soluții GPS și care permite localizarea inclusiv în interiorul clădirilor. Singura cerință de funcționare mai specială a dispozitivului este prezența unor rețele WiFi cartografiate de compania Google (cerință îndeplinită cu siguranță în mediul urban).

Pentru implementare am ales o placă de dezvoltare Adafruit Feather HUZZAH dar poate fi utilizată orice placă bazată pe ESP8266. Unul dintre avantajele oferite de placa de dezvoltare aleasă este posibilitatea de alimentare directă de la un acumulator LiPo de 3.7V permițând astfel realizarea unui sistem portabil. Pentru partea de afișare, utilă mai ales în cazul utilizării mobile a dispozitivului implementat, am utilizat un afișaj SHARP Memory Display ce are un consum extrem de redus (4µA @ 3.3V) și un contrast foarte bun.

Cele două componente ale sistemului vor comunica prin intermediul unei conexiuni SPI unidirecționale (doar 3 fire). Asftel, vom conecta:

  • Pinii 3.3V și GND al ecranului la pinii corespondenți ai plăcii de dezvoltare;
  • Pinul CLK al ecranului la pinul 14 al plăcii de dezvoltare;
  • Pinul DI al ecranului la pinul 13 al plăcii de dezvoltare;
  • Pinul CS al ecranului la pinul 5 al plăcii de dezvoltare.

2

Pinul 16 (Wake) al plăcii va fi conectat la pinul RST dacă dorim ca sistemul să intre în modul de consum redus între două localizări (util pentru funcționarea mobilă cu alimentare bazată pe acumulator). Conexiunea trebuie realizată după încărcarea programului pe placa de dezvoltare.

Programul sistemului a fost testat utilizând mediul de dezvoltare Arduino IDE 1.8.5 având instalate extensia ESP8266 Community 2.4.1 și bibliotecile Adafruit GFX 1.2.3, Adafruit SHARP Memory Display 1.0.6 (pentru controlul ecranului) și WifiLocation 1.2.2 (pentru interacțiunea cu Geolocation API).

#include <ESP8266WiFi.h>

#include <WifiLocation.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SharpMem.h>

În cadrul programului trebuie personalizate datele de acces la o rețea WiFi (ssid și passwd) și cheia de acces la serviciile cloud Google (googleApiKey). Pentru a obține cheia de acces trebuie să vă înregistrați ca dezvoltator pe site-ul Google Developers, să activați funcționalitatea GeoLocation API și să solicitați cheia de acces. Accesul este gratuit până la o limită de 2500 de interogări pe zi (evitați o utilizare la un interval mai mic de 30 de secunde).

const char* googleApiKey = “…”;

const char* ssid = “…”;

const char* passwd = “…”;

WifiLocation location(googleApiKey);

#define SHARP_SCK  14

#define SHARP_MOSI 13

#define SHARP_SS   5

Adafruit_SharpMem display(SHARP_SCK, SHARP_MOSI, SHARP_SS, 96, 96);

#define BLACK 0

#define WHITE 1

Directiva debug poate fi utilizată (decomentată) dacă doriți să vedeți mesajele generate de sistem în consola serială.

//#define debug

3

În cadrul secțiunii setup() se va realiza scanarea rețelelor WiFi din zona în care se află sistemul, obținerea coordonatelor geografice de la serviciul cloud de localizare pe baza puterii semnalului fiecărei rețea WiFi observate și afișarea coordonatelor pe ecran (și în consola serială dacă este activată directiva debug). După un ciclu de localizare sistemul va intra în stare de consum redus (deepSleep) pentru 10 minute. Datele afișate vor conține latitudinea și longitudinea precum și acuratețea localizării (exprimată în metri).

4

void setup() {

#ifdef debug

Serial.begin(115200);

#endif

display.begin();

display.clearDisplay();

display.refresh();

WiFi.mode(WIFI_STA);

WiFi.begin(ssid, passwd);

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

#ifdef debug

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

Serial.println(ssid);

Serial.print(“Status = “);

Serial.println(WiFi.status());

#endif

delay(500);

}

location_t loc = location.getGeoFromWiFi();

#ifdef debug

Serial.println(“Location request data”);

Serial.println(location.getSurroundingWiFiJson());

Serial.println(“Latitude: ” + String(loc.lat, 7));

Serial.println(“Longitude: ” + String(loc.lon, 7));

Serial.println(“Accuracy: ” + String(loc.accuracy));

#endif

display.setTextColor(BLACK);

display.setCursor(12,10);

display.setTextSize(1);

display.println(“Latitude:”);

display.setCursor(5,19);

display.setTextSize(2);

display.println(String(loc.lat, 3));

display.setCursor(12,37);

display.setTextSize(1);

display.println(“Longitude:”);

display.setCursor(5,46);

display.setTextSize(2);

display.println(String(loc.lon, 3));

display.setCursor(12,64);

display.setTextSize(1);

display.println(“Accuracy:”);

display.setCursor(5,73);

display.setTextSize(2);

display.println(String(loc.accuracy));

display.refresh();

ESP.deepSleep(600L*1000000L);

}

void loop() {

}

 

Solar Power GPRS Test

Întrebarea la care vom încerca să răspundem în cadrul acestui proiect este: putem construi un sistem IoT cu comunicație GPRS total independent de alimentarea de la rețeaua de energie? Sistemul propus pentru testare este un sistem ce se bazează exclusiv pe alimentare solară. Un astfel de sistem poate fi folosit pentru locații izolate în care nu există disponibile alimentare cu energie electrică și Internet.

Ca soluție de alimentare solară vom utiliza o componentă MPPT: Sunny Buddy – MPPT Solar Charger. Această componentă permite conectarea unei celule solare cu ieșirea între 6V și 20V și încărcarea unui acumulator LiIon sau LiPo cu o singură celulă (3.7V). Curentul maxim de încărcare este de 450mA deci este necesară utilizarea unui acumulator de capacitate minimă 450mAh. În testul nostru vom utiliza o celulă solară de 2.5W / 9V și un acumulator LiPo de 800mAh.  Pentru mai multe detalii despre funcționarea componentei MPTT puteți consulta materialul „Sunny Buddy Solar Charger V13 Hookup Guide”.

Pentru partea de achiziție și raportare IoT vom utiliza placa de dezvoltare Adafruit Feather 32u4 FONA echipată cu un microcontroler ATmega32U4 (la fel ca și placa de dezvoltare Arduino Leonardo) și un controler GSM/2G SIM800 quad-band (850/900/1800/1900MHz).

2

Placa va supraveghea nivelul de încărcare a acumulatorului și va raporta prin Internet (prin intermediul conexiunii GPRS) valorile către serviciul cloud iot.robofun.ro. Placa de dezvoltare se va alimenta de la acumulatorul LiPo conectat la componenta MPPT și va servi ca element de descărcare pentru acesta. Pentru mai multe detalii despre funcționarea și utilizarea plăcii de dezvoltare Adafruit Feather 32U4 FONA puteți consulta materialul „Overview | Adafruit Feather 32u4 FONA | Adafruit Learning System”.

Diagrama de interconectare între componentele sistemului de test este următoarea:

4

Funcționarea plăcii de dezvoltare necesită o antenă GSM uFL. Pentru a minimiza consumul și pentru a putea controla inițializarea sistemului (mai ales în cazul în care acumulatorul sistemului nu este încărcat suficient) pinul KEY al modulului GSM se va deconecta de la masă (necesită tăierea jumperului KEY de pe spatele plăcii) și se va conecta la pinul 0 al plăcii de dezvoltare (firul galben din schema de interconectare).  În acest fel modulul GSM de pe placă nu va mai fi activ continuu ci doar în cazul în care îl vom activa din software. ATENȚIE!!! Această operație conduce la pierderea garanției oferite de producător.

Programul sistemului a fost dezvoltat și testat utilizând Arduino IDE 1.8.5 având instalate extensia Adafruit AVR Boards 1.4.11 și bibliotecile Adafruit FONA Library 1.3.3 și Sleep_n0m1 1.1.1.

#include “Adafruit_FONA.h”

#include <Wire.h>

#define FONA_RX 9

#define FONA_TX 8

#define FONA_RST 4

#define FONA_RI 7

#define FONA_KEY 1

#define FONA_ALARM 13

Definirea constantelor apn, apnusername și apnpassword sunt specifice rețelei de telefonie mobile al SIM-ului GSM utilizat. ATENȚIE!!! Placa de dezvoltare necesită un SIM GSM ce suportă standardul 2G, comunicația GSM nu va funcționa în cazul unui SIM GSM exclusiv 3G/4G.

#define apn “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);

#include <Sleep_n0m1.h>

Sleep sleep;

În cadrul secțiunii setup() se vor inițializa pinii de control utilizați pentru controlul modulului GSM (FONA_KEY este utilizat pentru activarea modulului GSM, FONA_ALARM este conectat la LED-ul de semnalizare al plăcii de dezvoltare și va fi utilizat pentru avertizarea imposibilității inițializării corecte a modulului GSM).

void setup() {

  pinMode(FONA_KEY,OUTPUT);

  digitalWrite(FONA_KEY,HIGH);

  pinMode(FONA_ALARM,OUTPUT);

  digitalWrite(FONA_ALARM,LOW);

}

Secțiunea loop() conține algortimul complet de inițializare și comandă pentru modulul GSM, achiziția nivelului de încărcare a bateriei și transmiterea prin Internet a valorilor către serviciul IoT. Primul pas în execuția algoritmului este intrarea în starea de consum redus pentru o oră – stare obligatorie pentru revenirea sistemului dintr-o stare de oprire completă generată de consumarea completă a acumulatorului (acumulatorul este încărcat suficient pentru inițializarea microcontrolerului ATmega32U4 dar nu și pentru inițializarea modulului GSM).

void loop() {

  sleep.pwrDownMode();

  sleep.sleepDelay(3600000);

Pornirea modulului GSM necesită un impuls de 2 secunde pe pinul FONA_KEY. Sistemul va încerca de 10 ori inițializarea modulului GSM după care va relua perioada de o oră de consum redus.

  digitalWrite(FONA_KEY,LOW);

  digitalWrite(FONA_ALARM,HIGH);

  delay(2000);

  digitalWrite(FONA_KEY,HIGH);

  digitalWrite(FONA_ALARM,LOW);

  delay(2000);

  fonaSerial->begin(4800);

  byte i = 0;

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

      i++;

      if (i==10) break;

      digitalWrite(FONA_KEY,LOW);

      digitalWrite(FONA_ALARM,HIGH);

      delay(2000);

      digitalWrite(FONA_KEY,HIGH);

      digitalWrite(FONA_ALARM,LOW);

      delay(2000);      

  }

În cazul în care modulul GSM s-a inițializat corect se va încerca deblocarea cartelei SIM pe baza codului PIN (trebuie modificat în program în funcție de codul cartelei folosite). Dacă deblocarea cartelei SIM nu se poate face se va relua perioada de o oră de consum redus – este posibil ca acumulatorul să scadă sub pragul de alimentare corectă a modulului GSM între inițializare și deblocarea cartelei SIM.

if (i!=10) {

    if (! fona.unlockSIM(“0000”) ) {

digitalWrite(FONA_ALARM,HIGH);

delay(1000); i=10; }

    else {  

Programul va aștepta înregistrarea în rețeaua GSM a cartelei SIM a sistemului pentru o perioadă de 100 de secunde.

    uint8_t n = fona.getNetworkStatus();

     i=0;

      while (n!=1) {

        i++;

        if (i==10) break;

        digitalWrite(FONA_ALARM,HIGH);

        delay(5000);

        digitalWrite(FONA_ALARM,LOW);

        delay(5000);

        n = fona.getNetworkStatus();

       }

     }

Postarea valorii de încărcare a acumulatorului se va face doar dacă se va inițializa cu succes partea de comunicații de date (fona.enableGPRS). Măsurarea se va face chiar de modulul GSM. În cadrul programului trebuie personalizate cheile de autentificare (SENSOR_TOKEN1 și SENSOR_TOKEN2) obținute prin înregistrarea gratuită în cadrul serviciului iot.robofun.ro.

if(i!=10) {

      fona.setGPRSNetworkSettings(F(apn),

F(apnusername),F(apnpassword));

      if (fona.enableGPRS(true)) {

      uint16_t vbat;

      uint16_t pbat;

      fona.getBattVoltage(&vbat);

      fona.getBattPercent(&pbat);

      delay(1000);

      uint16_t statuscode;

      int16_t length;

      String SENSOR_TOKEN1=”…”;

      String SENSOR_TOKEN2=”…”;

      String data =

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

      char url[100];

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

      fona.HTTP_GET_start(url, &statuscode,

(uint16_t *)&length);

      while (length > 0) {

          while (fona.available()) {

            char c = fona.read();

            length–;

            if (! length) break;

          }

          break;

      } 

      fona.HTTP_GET_end();

      delay(100);

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

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

      fona.HTTP_GET_start(url, &statuscode,

(uint16_t *)&length);

      while (length > 0) {

          while (fona.available()) {

            char c = fona.read();

            length–;

            if (! length) break;

          }

          break;

      } 

      fona.HTTP_GET_end();

      delay(100);

    }

La final, înainte de reintrarea în modul de consum pentru o oră, se va opri modulul GSM printr-un puls de 2 secunde pe pinul FONA_KEY.

      digitalWrite(FONA_KEY,LOW);

      delay(2000);

      digitalWrite(FONA_KEY,HIGH);

    }

  }

}

Testul a fost efectuat pornind cu acumulatorul sistemului complet consumat (tensiune sub 3.3V). După o zi cu soare, când tensiunea acumulatorului a ajuns la 3.7V, sistemul s-a inițializat complet cu succes și a început să posteze pe serviciul IoT. Acest lucru înseamnă că sistemul își poate reveni dintr-o stare de oprire completă generată de descărcarea acumulatorului (mai multe zile fără lumină solară) fără intervenție umană.

5

În timpul unei zile cu soare acumulatorul câștigă aproximativ 30% din nivelul de încărcare iar procentul de descărcare într-o zi înorată este de circa 15%. Asta înseamnă că o zi cu soare poate fi urmată de două zile înorate fără ca sistemul să descarce acumulatorul. Dacă acumulatorul sistemului este complet încărcat, sistemul poate funcționa fără lumină solară pentru un interval de 6-7 zile

6

Testul efectuat dovește că se poate construi un sistem de raportare IoT GSM/GPRS care să funcționeze în mod autonom pe baza energiei solare fără să fie nevoie de intervenția umană în cazuri speciale de descărcare a acumulatorului.

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: