Prodotti
gbm
Datalogging con Ethernet Shield Wiznet
Tutorials -
Domenica 04 Marzo 2012 04:25
Scritto da gbm

Con questo tutorial vedremo come realizzare un sistema di datalogging basato su protocollo HTTP grazie a una shield Ethernet Wiznet (ufficiale o cinese) che comunica tramite GET alcuni dati ottenuti da sensori ad un server che li processa e salva in un database MySQL, in piu' vedremo come rappresentarli graficamente in una pagina web grazie a Google Charts. Questo è solo una parte di un progetto che sto portando avanti che consiste in un gestionale e logger di dati per il mio impianto fotovoltaico autocostruito. Qui potete vedere il pannello che mostra il log della luce ambientale rilevatalo zip contenente tutti i file necessari a realizzare questo sistema.

 

Questa è la prima volta che scrivo un tutorial che tocca cosi' tanti campi di interesse diversi del mondo dell'informatica, infatti piu' in basso vedremo insieme ovviamente Wiring, un po' di basi di HTTP, Php, Javascript, MySQL e un infarinatura di CSS3. Per questo se non conoscete bene questo ambito vi consiglio prima di leggere Primi passi lato client con Ethernet Shield Wiznet.

 

Ma la Wiznet è buggata oppure no?!

Cerchero' di chiarire alcuni dei dubbi che sono scaturiti dalla mia discussione sul forum di Arduino, riguardo alla Ethernet shield Wiznet. Il chip scelto dal team Arduino per la gestione Ethernet ha un bug hardware. Per esempio puo' capitare che la board si inchiodi / blocchi / freezi dopo un dato periodo di funzionamento corretto. Dopo essermi letto un po' di documentazione a riguardo, ho provato a far girare la board per alcuni minuti ed effettivamente, effettuando tante operazioni complesse e accedendo alla memoria della SD, questa puo' smettere di funzionare correttamente ed è possibile riportarla al suo normale stato di funzionameno soltanto resettandola. Io credo che sia un'assurdità cercare di costruire un server basato su queste MCU, quando è possibile averlo gratuitamente su internet oppure con una piccolissima spesa.

Quindi la mia visione del problema è questo: se questa scheda viene utilizzata per effettuare dei GET o POST, quindi lato client va benissimo, per sicurezza inserirei un reset automatico alla fine del ciclo (come vedremo dopo) anche se non sono nemmeno sicuro sia necessario, se l'uso del chip Wiznet si risolve a una semplice richiesta inframezzata da un intervallo dato. 

 

Lato Client (Arduino + Ethernet Shield) 

In questo esempio utilizzeremo un semplice LED come sensore di luce. Per farlo connetteremo il polo positivo del LED alla porta analogica 4 e il polo negativo a una qualsiasi porta GND di Arduino. Appena acceso, l'Arduino esegue un delay di 10 secondi, dopodichè effettua una lettura analogica sul PIN del sensore comunica grazie alla Ethernet Shield con il protocollo HTTP e il metodo GET i dati ottenuti a un server che li riceverà grazie a una pagina Php. Alla fine della comunicazione Arduino si auto resetta, per evitare eventuali Freeze. Caricate il sorgente, ricordandovi di includere le librerie SPI e Ethernet (le stesse dell'esempio WebClient).

//  Web client
//  Questo sketch si connette a un server
//  usando una shield Arduino Wiznet Ethernet
//  effettua un GET per comunicare a un server
//  la  luminosità percepita

//Circuito:
//  Ethernet shield connessa ad Arduino con i PIN 10, 11, 12, 13
//  Polo positivo LED analog 4 polo negativo GND Arduino

// Inserisci MAC address
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 11,11,111,111 }; // IP Arduino + Wiz
byte server[] = { 11,111,111,111 }; // IP server

// Inizializza libreria
// La porta 80 è quella di default per il protocollo HTTP:
Client client(server, 80);
void(* Riavvia)(void) = 0; // Reset software
int temp = 0; //variabile in cui salvare temperatura
void setup() {
  // Inizializza connessione Ethernet
  Ethernet.begin(mac, ip);
  pinMode(A4, INPUT);
  digitalWrite(A4, LOW);
  
  Serial.begin(9600);
  delay(10000);
  Serial.println("Provo a connettermi...");
}

void loop() {
 for(;;) {
   if (client.connect()) {
     Serial.println("Connesso");
     // Fai la richiesta
     int light = analogRead(A4); // lettura luce ambientale
     client.print("GET /index.php?light=");
     client.print(light);
     client.print("&temp");
     client.print(temp);
     client.println(" HTTP/1.1");
     client.println("Host: www.tuosito.it");
     client.println();
     Riavvia();
   }
 };
}

 

Lato Server

Per questo esempio io ho utilizzato il server di gioblu.com, ma è possibile utilizzare una grande quantità di server virtuali gratuiti. Se ne avete a disposizione uno che supporti Php e un database MySQL potete seguire questa guida e raggiungere il risultato mostrato. Come prima cosa dobbiamo scaricare il pacchetto contenente i 3 file necessari (index.php che riceve i dati dalla Ethernet, light.php che rappresenta graficamente e style.css che contiene lo stile della pagina).

 

Creazione del database

E' necessario creare una tabella che conterrà tutti i dati ricevuti dal nostro device, e li indicizzi secondo una variabile incrementale detta id e una data, contenente giono mese anno e ora compresa di secondi. Grazie a queste due variabili potremo organizzare i dati e ordinarli, ma soprattutto rappresentarli graficamente. Per creare questa tabella è necessario aprire il gestionale che fornisce il servizio di hosting, oppure è possibile farlo manualmente tramite php. I seguenti sono i campi che dovrete creare:

  1. Il primo campo è id, un intero di massimo 6 numeri con paramentro extra AUTO_INCREMENT, cioè auto incrementale.
  2. date variabile di tipo timestamp settato su CURRENT_TIMESTAMP
  3. light è un intero di 5 numeri
  4. temp è un intero di 5 numeri

 

Ricezione dei dati via Php

Per comunicare i dati da Arduino al Server sfruttiamo il metodo GET come abbiamo ampiamente visto nei Primi passi lato client con Ethernet Shield Wiznet. Per ricevere il messaggio mandato dalla Ethernet utiliziamo index.php e la funzione 

$light = $_GET["light"];
$temp = $_GET["temp"];

per salvare nella varibile light il valore inviato dalla Ethernet. Acquisiti i dati, con poche righe il Php, vengono salvati su MySQL i dati ottenuti:

mysql_connect("ip server mysql",$username,$password) or die( "Unable to select database");
@mysql_select_db($database) or die( "Unable to select database");
$query = sprintf('INSERT INTO nome cartella database (light, temp) VALUES (%d, %d)', $light, $temp);
mysql_query($query); // salva le variabili comunicate tramite GET da Arduino
if (mysql_error() != '') echo("Errore: " . mysql_error());
mysql_close();

Come potete vedere dopo tanto lavoro su Arduino queste poche righe non spaventano piu' tanto ;). La query è composta da un comando piuttosto semplice:

Inserisci nella cartella db scelta nei campi temp e light le variabili acquisite.

 

Rappresentazione dei dati con Javascript

Prima di pensare al grafico, dobbiamo leggere il database MySQL:

$p = $_GET['param'];
if (!in_array($p, array('light', 'temp', 'batteryvoltage', 'panelvoltage'))) $p = 'light';
$db = mysqli_connect("11.111.111.111", $username, $password, $database) or die("Unable to select database");
  $res = $db->query("SELECT date, $p FROM solarlogger ORDER BY date ASC");

Anche in questo caso il codice è molto semplice. Ci connettiamo al db, e selezioniamo la data e il campo richiesto dalla nostra tabella e ordiniamo i risultati per data ascendente. Queste operazioni ci permettono di poter fruire dei dati in modo organizzato, con un while vengono ciclati e rappresentati tutti come un singolo punto di una curva con Gogole Charts.

L'ho scelto perchè è sicuramente il sistema piu' documentato e completo per rappresentare grafici online. Ho scelto il grafico di tipo Line per rappresentare la variabile che rappresenta la luce ambientale nel tempo. 

Quello che vediamo ora è di certo la parte piu' interessante del tutorial, cioè come generare Javascript dinamicamente con Php. Per farlo utiliziamo json_encode($data); che ci permette di tradurre un array php in un array javascript in modo veramente pulito. L'array data contiene la data sistemata secondo lo standard italiano. 

  $data = array();
  while($row = $res->fetch_assoc()) {
      list($date, $time) = explode(" ", $row['date']);
      $date = join('/', array_reverse(explode('-', $date)));
      $data[] = array($date . ' ' . $time, transform($p, $row[$p]));

Per capire meglio come funziona questa script vi consiglio di dare un occhio al codice sorgente della pagina che viene generata.

 

Personalizzazione dello stile della pagina con CSS3

CSS o Cascading Style Sheet è un linguaggio di programmazione parallelo a HTML utilizzato per definire la formattazione e lo stile delle pagine web. Essendo il mio lavoro ho aggiunto alcune piccole cose per dare un'estetica accettabile al progetto, cosa che spesso manca nei progetti DIY che ho visto sul forum italiano e internazionale. Nel file charts.php viene incluso il file style.css:

html, body { margin: 0; padding: 0; }

body {
    background: #333;
    color: #444;
    font-family: Tahoma, Arial, Sans-Serif;
    font-size: .8em;
    line-height: 1.3em;
}

#chart_cont { width: 950px; height: 611px; background-color: #EBEBEB; box-shadow: 0px 0px 10px #222; margin: auto;  }
#chart_div { width: 930px; box-shadow:0px 0px 1px #333; height: 500px; margin-left: 10px; }
#header { height: 25px; margin: auto; width: 900px; margin-bottom: 20px; padding    -top: 15px;  }
#header a { text-decoration: none; color: #135CAE; margin:5px; box-shadow: 0px 0px 1px black; padding: 7px; background-color: white; font-size: 16px;}
#header a:hover {color: red; }
.claim { height: 30px; background-color: white; margin:40px 10px 10px 10px; box-shadow: 0px 0px 1px #333; }
#menu {margin: 25px    auto; float: left;}

Come potete vedere nel file charts.php ci sono alcuni contenitori chiamati div che sono definiti con una classe (class) o con un id. Questi sono il nome che permette di attribuire un dato stile a un dato contenitore. Per esempio, come potete vedere nel codice piu' in alto, al contenitore principale chart_cont viene definita un'ombra scura di 10px con il comando box-shadow.

 

Purtroppo non mi è possibile spiegare ogni singola riga di questi 3 file perchè sarebbe decisamente troppo lungo, pero' ho cercato di essere il piu' chiaro possibile e documentare con i commenti dove poteva essere utile.

 

Gioblu Robotics © 2010 - 2012 · Sitemap · privacy

gioscarab@gmail.com · Via Savona 123 20146 Milano MI · PI 06977550968 · Codice fiscale MTLGNN86S09F205F

Gioblu BOTServer è online dal 10 Aprile 2010 - 319.232 Visite - 1.027.175 Pagine visualizzate - 182.309 Visitatori unici - 536 utenti attivi