MeshWeather


Stazioni Meteo Distribuite per il monitoraggio dei campi

Alessandro Pagiaro e Mario Salinas

Hardware

Abbiamo fatto ciò che non dovevamo fare...
... scegliere prima l'hardware e poi capire come usarlo

  • ESP-01, tanti, tantissimi...
  • Arduino e relativi sensori

Circuito per gestire gli ESP-01

usageMode

Software

(La parte divertente)

Cosa abbiamo fatto...

Protocolli di comunicazione

3 modalità di comunicazione

  • Seriale - Arduino, ESP-01

    Collegamento seriale puro, dove vengono mandati dei pacchetti JSON contenente i dati raccolti.

  • Wifi - ESP-01, ESP-01

    Rete Mesh ad hoc simulata tramite una serie di connessioni punto-punto.

  • Wifi/Seriale - ESP-01, Server

    Collegamento seriale (o alternativamente Wifi) che raccoglie tutti i pacchetti della rete e li manda al server che li elaborerà

Protocollo della rete mesh


Nodo Station / Nodo Server

La rete è completamente composta da ESP-01.
A seconda del loro ruolo, tuttavia, possiamo distinguerli in 3 categorie:

  • Station. Il compito dei nodi di questo tipo è quello di leggere i dati dai sensori, creare un pacchetto di tipo DATA e inviarlo al server.
  • GenericNode. I nodi intermedi si occupano esclusivamente di inoltrare i pacchetti dati verso il server e le discoveryReq a tutti vicini.
  • espServer. Il/i server lanciano periodicamente una discoveryReq e inviano sulla porta seriale tutti i nuovi pacchetti dati.

Protocollo della rete mesh


Discovery

Inviata dal server ai suoi vicini e propagata in broadcast fra i nodi, viene usata per costuire l'albero di copertura della rete così da evitare il formarsi di cicli.
{ 
	"from" : uint32_t idServer, 
	"updat_number" : int currentUpdateNumber, 
	"sender_id" : uint32_t prevHopId, 
	"type" :  0 
}
Alternativamente si potrebbe usare l'RSS.

Protocollo della rete mesh


Fowarding/Data

Ogni volta che un nodo riceve un pacchetto lo inoltro al nodo successivo. Se non esiste lo mando in broadcast.

Non è stata volontariamente gestita la pardita di pacchetti poichè i dati raccolti differiscono poco dai precedenti e quindi non è necessario un campionamento eccessivo. Inoltre una nuova richiesta di interesse del sink provvederà, qualora sia necessario, a ricostruire la rotta con una frequenza adeguata alla situazione (parametro della rete).

Protocollo della rete mesh


Strutture dati

  • int lastPId[30];
    uint32_t lastCId[30];
    Dizionario attraverso il quale si evita la diffusione di pacchetti duplicati all'interno della rete.
  • int update, lastSyncTime
    Gestite dal server e usate nella fase di discovery per comunicare ai nodi l’aggiornamento delle rotte e l’avvio di una nuova fase di sincronizzazione.

Protocollo della rete mesh


Discovery nel server

Implementata da discoveryTree(), crea e invia un pacchetto per reinizzializzare l’albero di copertura della rete e risincronizzare i nodi
void discoveryTree(){ 
  char msg[256];
  sprintf(msg, "{\"from\": %d, \"update_number\": %d, \"sender_id\": %d,
  \"type\": 0}", mesh.getChipId(), ++update, mesh.getChipId());
  /*Prevent overflow*/
  if(update == INT_MAX)
    update = 0;
  String p(msg);
  mesh.sendBroadcast(p);
  lastSyncTime = mesh.getNodeTime();
  return; 
}

Protocollo della rete mesh


Discovery nei nodi

Si aggiorna la rotta con la più recente.
void receivedCallback( uint32_t from, String &msg_str ){
  JsonObject& msg = jsonBuffer.parseObject(msg_str);
  int type = msg["type"];
  switch(type){  
    case(DISCOVERY_REQ):{
        if(msg["update_number"] > update){
          update = msg["update_number"];
          nextHopId = msg["sender_id"];
          propagateDiscovery(msg);
          lastSyncTime = mesh.getNodeTime();
        }
    }break;
    [...]
  }
}

Protocollo della rete mesh


Gestione pacchetto dati nel server

Il server ESP-01 spedisce tutti i pacchetti che riceve sul seriale, delegando al computer (decisamente con più capacità di calcolo), di organizzare il tutto e scartare i pacchetti duplicati.
void receivedCallback( uint32_t from, String &msg_str ){
  JsonObject& message = jsonBuffer.parseObject(msg_str);
  int type = message["type"];
  if(type!=DISCOVERY_REQ)
    printJson(message);
}

La nostra demo

Cioè un modello semplificato

La stazione Arduino viene simulata direttamente su un ESP-01.

void loop(){
	[...]
	char msg[100];
	sprintf(msg, "{\"temp\": %f}", getTemp());
	mesh.sendBroadcast(msg);
}

Tale semplificazione è giustificabile dal fatto che nel caso in cui si hanno due sensori di raccolta dati, questi possono essere raccolti direttamente con un ESP-01 senza necessità di un microcontrollore esterno.

Abbiamo 3 ESP-01, quello connesso al server ignora i pacchetti che gli arrivano dal primo

void receivedCallback( uint32_t from, String &msg_str ){
  if(from == 2008034 /*ID dell'ESP-01 che genera i dati*/)
    return;
    [...]
    }

Aspettate un attimo... e il duty cycle?

Non ha una funzione per far spegnere la radio. O meglio...
void deepSleep(int milliseconds){}
spegne si la radio, ma poi riparte la funzione di setup, è praticamente un RESET!!!!!

I dati raccolti non vengono analizzati ma semplicemente salvati su un server (ThingSpeak)

Let's start!