Arduino per domotica, collegato in rete come client/server

Con questo articolo parto a spiegarvi come utilizzare arduino e altri strumenti per autocostruirsi un impianto di domotica e relativo antifurto.

Con questo parte di progetto utilizzo arduino per inviare via UDP lo stato degli I/O e anche di ricevere pacchetti UDP per controllare 4 relay.
Tutto il progetto completo è formato da diversi blocchi come questo che comunicano con un server (raspberry pi) che in python controlla il tutto e agisce di conseguenza. Sul Rasberry è installato anche Asterisk che interfacciato con il mio programma python è in grado di ricevere telefonate per attivare l’antifurto o disattivarlo e decidere chi chiamare, tutto tramite voce i segnali DTMF.

Comunque senza perderci troppo con il primo pezzo, cioe’ arduino che invia e riceve pacchetti.

I messaggi che manda sono nel formato “NUMERO SCHEDA” + “NUMERO SENSORE” + “STATO”

ad esempio la scheda 5 arduino con il sensore 6 e lo stato 00001 = 050600001

In questo modo posso utilizzare quanti arduino voglio, di sensori in teoria fino a 99, teniamo conto che arduino si può facilmente espandere con I/O su i2c.
Per il valore utilizzo 5 cifre perchè oltre al segnale on/off posso trasmettere temperature, livello di Co2 e tutto quello può servirvi.

Come porte UDP ho utilizzato 5055 per la trasmissione e 5056 per la ricezione, poi potete comunque modificarle con altre se vi torna comodo.

Nel mio caso ho utilizzato:

  • un arduino nano
  • un ENC28J60 Ethernet Shield V1.0 per scheda di rete
  • un piccola espansione per fare dei collegamenti decenti
  • Scheda a 4 relay

 

baseenc28j60-shield-variations
relay
ArduinoNanoFront_3_sm

 

 

 

 

 

 

serve la libreria per gestire lo shield Ethernet, quindi scaricate la libreria qui: https://github.com/ntruchsess/arduino_uip

Installate la libreria in Arduino IDE e qui sotto c’e’ il programma ad hoc che utilizzo su una scheda, più’ sotto vi spiego i vari blocchi:

/*
 * pin 10 -11 -12 -13 occupati da ethernet
 * pin 2 -3 -4 -5 -6 -7 -8 -9 digitali
 * da A0 ad A7 analogici
 */

#include <UIPEthernet.h>

EthernetUDP udpserver;
EthernetUDP udp;

int success;
char IRF;
int counter; //lo utilizzo per il conteggio del client per mandare i messaggi al server


void setup() {
 
 pinMode(2, OUTPUT); //rele
 pinMode(3, OUTPUT); //rele
 pinMode(4, OUTPUT); //rele
 pinMode(5, OUTPUT); //rele
 pinMode(6, INPUT); // finestra cortile filo rosso
 pinMode(7, INPUT); // finestra vicino lavandino filo nero
 pinMode(8, INPUT); // porta cucina filo bianco
 pinMode(9, INPUT); // sensore lampada 500w portico
 
 
 Serial.begin(9600); //imposto la porta seriale per debug
 uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; //imposto mac address
 Ethernet.begin(mac,IPAddress(10,0,0,253)); //imposto ip
 success = udpserver.begin(5056); // apro la porta udp
 }

void loop() {
 
 //controllo nuovi udp-packet:
 int size = udpserver.parsePacket();
 if (size > 0) {
 do
 {
 char* msg = (char*)malloc(size+1);
 int len = udpserver.read(msg,size+1);
 msg[len]=0;
 Serial.print("received: ");
 Serial.println(msg);
 if (String(msg[0])=="1") {
 digitalWrite(2, HIGH);
 } else {
 digitalWrite(2, LOW);
 }

 if (String(msg[1])=="1") {
 digitalWrite(3, HIGH);
 } else {
 digitalWrite(3, LOW);
 }

 if (String(msg[2])=="1") {
 digitalWrite(4, HIGH);
 } else {
 digitalWrite(4, LOW);
 }

 if (String(msg[3])=="1") {
 digitalWrite(5, HIGH);
 } else {
 digitalWrite(5, LOW);
 }

 free(msg);
 }
 while ((size = udpserver.available())>0);
 //finish reading this packet:
 udpserver.flush();
 
 // restituisco la lettura delle uscite
 for (int i=20; i < 24; i++){
 success = udpserver.beginPacket(IPAddress(10,0,0,10),5056);
 String Messaggio = "050" + String(i) + "0000" + String(digitalRead(i-18));
 success = udpserver.print(Messaggio);
 success = udpserver.endPacket();
 delay(100);
 } 
 udpserver.stop();
 //restart with new connection to receive packets from other clients
 Serial.print("restart connection: ");
 Serial.println (udpserver.begin(5056) ? "success" : "failed");
 }

// qui parto con le letture dei sensori
 if (counter > 1200) {
 
 
 for (int i=6; i < 10; i++){
 success = udp.beginPacket(IPAddress(10,0,0,1),5055);
 String Messaggio = "050" + String(i-5) + "0000" + String(!digitalRead(i));
 success = udp.print(Messaggio);
 success = udp.endPacket();
 delay(100);
 } 
 
 for (int i=0; i < 2; i++){
 if (analogRead(i) > 300) { //leggo lo stato degli irf
 IRF='1';
 } else {
 IRF='0';
 }
 success = udp.beginPacket(IPAddress(10,0,0,1),5055);
 String Messaggio = "050" + String(i+5) + "0000" + IRF;
 success = udp.print(Messaggio);
 success = udp.endPacket();
 delay(100);
 } 

 counter=0;
 } else {
 counter = counter + 1;
 }

}

Lo shield per la scheda di rete utilizza i pin di Arduino 10 -11 -12 -13
Quindi questi non li possiamo utilizzare per la nostra domotica.

 uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; //imposto mac address
 Ethernet.begin(mac,IPAddress(10,0,0,253)); //imposto ip
 success = udpserver.begin(5056); // apro la porta udp

Dobbiamo impostare il mac address per la scheda di rete (utilizzare dei numeri esadecimali a caso), poi impostiamo un IP statico nel range della vostra rete; nella mia rete utilizzo 10.0.0.0/24 quindi ho preso un IP libero a caso  10.0.0.253.. Alla fine imposto la porta di ascolto 5056 per ricevere dati da server (utilizzare certe porte come uscite).

Nel ciclo di loop è tutto abbastanza semplice, leggo i valori degli input e li invio uno a uno via UDP al mio server.
Per la parte della gestione uscite in Arduino rimane in ascolto sulla porta 5056 e riceve una stringa di 4 caratteri che attivano o disattivano i relay (1 attiva 0 disattiva).
Quindi 0001 attiva il primo relay.

Questa è la prima parte del progetto, spero vi possa essere di spunto per i vostri progetti.

Nel prossimo articolo posterò un progetto quasi uguale per Arduino dove invece lo utilizzo solo per leggere ingressi e non ho uscite, quindi manca la parte server.