MyLegalPlants | IoT Project
MyLegalPlants è un progetto, alla sua seconda versione, di Internet delle Cose (IoT) per il controllo dello stato dell’ambiente di coltivazione di piante o per applicazioni in agricoltura in generale (Agritech).
La Tecnologia
Il sistema utilizza tecnologie Raspberry PI 3, Arduino, Php e MySQL, Web App e Telegram.
L’ambiente è monitorato da Sensori che ne rilevano le caratteristiche fisiche, come umidità del terreno, temperatura, illuminazione, ed i loro valori vengono acquisiti da Arduino per una lettura periodica. Tali valori vengono memorizzati da Raspberry in modo centralizzato su DataBase MySQL installato sul Server Web.
La visualizzazione di tali valori viene effettuata tramite WebApp oppure possono essere richiesti tramite messaggio Telegram.
Le condizioni ambientali possono essere modificate da un Sistema di Irrigazione, Illuminazione o Riscaldamento controllato da raspberry e Arduino e comandato da WebApp o con messaggistica Telegram.
Si è optato per l’utilizzo di Raspberry in associazione ad Arduino, invece di Arduino MKR1000, per la sua migliore capacità e stabilità di connessione HTTP con il server e per la sua apertura ad implementazioni di nuove future funzionalità.
Il sistema è espandibile nella tipologia di caratteristiche controllate e adattabile a qualunque controllo IoT.
Hardware
L’hardware realizzato prevede l’interfacciamento ed il condizionamento dei segnali forniti dai sensori (Temperatura, Umidità, Intensità luminosa), e l’azionamento ed il controllo degli attuatori (Riscaldatore, Irrigatore, Lampada) per la modifica delle condizioni ambientali.
I sensori sono il DS18B20 per rilevare la temperatura dell’ambiente, un igrometro Wire TE215 per la misura dell’umidità del terreno e una fotoresistenza per la lettura dell’intensità luminosa presente.
Gli attuatori consistono in una Lampada ad Infrarossi per il riscaldamento, in una Pompa DC per il flusso dell’acqua per l’irrigazione e una lampada Led per l’illuminazione.
Sulla scheda alloggia Arduino UNO che ha il compito di acquisire i dati dai sensori e controllare gli attuatori, destinati al controllo del sistema (WebApp, Messaggi Telegram).
Il Web Server
Sito internet (www.mylegalplants.it) e Database MySQL sul quale vengono memorizzati i valori di sensori ed attuatori in modo centralizzato tra i due Arduino MKR1000, sono installati su Web Server Linux.
I microcontrollori, connessi a Internet tramite scheda WiFi, utilizzano files php per effettuare le query al database attraverso le quali leggere o scrivere i valori dei sensori e attivare gli attuatori.
Tali files utilizzano per la connessione al DB un file db_config.inc.php come include all’interno dei files php, contenente le variabili:
$hostname = “host server”;
$username = “db user”;
$password = “password”;
$db = “db name”;
La Web App
Per il controllo del sistema è stata prevista una WebApp che visualizza, attraverso indicatori Gauge realizzati in Javascript, il valore delle grandezze fisiche monitorate.
La App incorpora anche i pulsanti per la attivazione degli attuatori, graficamente modificati attraverso CSS.
Compito della WebApp è la visualizzazione e/o la scrittura dei valori dei sensori e lo stato degli attuatori sul Database.
La struttura logica dell’App prevede interrogazioni al DB cicliche (ogni 3 sec) attraverso HttpRequest JS utilizzando i files php. Al risultato delle interrogazioni vengono dinamicamente aggiornati i valori visualizzati dagli indicatori e le immagini dei pulsanti se lo stato dell’attuatore è stato modificato esternamente per altre vie (come Telegram Bots).
Microcontrollore Arduino
Programma Arduino
Il compito di Arduino è quello di leggere i valori di Temperatura, Umidità del terreno e Illuminazione attraverso i sensori e di comunicarlo a Raspberry attraverso la UART, e da questo ricevere lo stato aggiornato degli attuatori (Riscaldatore, Irrigatore e Lampada) per attivarli o meno.
#include
#include
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature Tsensor(&oneWire); //DS18B20
// vars sensori T, H, L
int acq_T = 0;
int acq_H = 0;
int acq_L = 0;
int t_value = 0;
int h_value = 0;
int l_value = 0;
// pins Acquisizione Analogicam
const int pinH = A1;
const int pinL = A2;
// pins Attuatori
const int pinAttuatore_T = 8; //led Verde -> Uscita RISCALDATORE
const int pinAttuatore_H = 9; //led Giallo -> Uscita IRRIGATORE
const int pinAttuatore_L = 10; //led Rosso -> Uscita ILLUMINAZIONE
int incoming;
char rxSeriale[5];
int counter = 0;
const int pinLED = 13;
unsigned long inizioIrrigazione = 0; // in millisecondi
const unsigned long tempoIrrigazione = 10L * 1000L; // ritardo durata irrigazione, in millisecondi
void setup() {
// output
pinMode(pinAttuatore_T, OUTPUT);
pinMode(pinAttuatore_H, OUTPUT);
pinMode(pinAttuatore_L, OUTPUT);
pinMode(pinLED, OUTPUT);
digitalWrite(pinLED, LOW);
// Start up the library T sensor
Tsensor.begin();
}
void loop() {
// lettura e condizionamento Sensori
Tsensor.requestTemperatures(); // Send the command to get temperatures
t_value = Tsensor.getTempCByIndex(0);
acq_H = analogRead(pinH); // H
h_value = map(acq_H,250,1023,100,0); // converto il valore di acq_H (0-1023) in %H sapendo che in H2o acq_h=180 -> 100%H
acq_L = analogRead(pinL); // L
l_value = map(acq_L,0,740,0,470); // converto il valore di acq_L (0-1023) in LUX sapendo che acq_l=740 -> 470 lux
//gestione comunicazione seriale
if(counter==0) Serial.begin(9600);
//invio seriale valori Sensori
invioSeriale(int(t_value),int(h_value),int(l_value));
//lettura della risposta seriale di Raspberry per Attuatori
if (Serial.available() > 0) {
while(counter<=5){
incoming = Serial.read();
rxSeriale[counter]=incoming;
Serial.println(rxSeriale[counter]);
counter++;
if(rxSeriale[0]=='1') digitalWrite(pinAttuatore_T, HIGH); //controllo Riscaldatore
if(rxSeriale[0]=='0') digitalWrite(pinAttuatore_T, LOW);
if(rxSeriale[2]=='1') digitalWrite(pinAttuatore_H, HIGH); //controllo Irrigazione
if(rxSeriale[2]=='0') digitalWrite(pinAttuatore_H, LOW);
if(rxSeriale[4]=='1') digitalWrite(pinAttuatore_L, HIGH); //controllo Illuminazione
if(rxSeriale[4]=='0') digitalWrite(pinAttuatore_L, LOW);
}
counter=0;
//Serial.println("Fine comunicazione");
Serial.end();
}
//ritardo di esecuzione
delay(3000);
}
void invioSeriale(int T, int H, int L){
Serial.print("!");
Serial.print(T);
Serial.print("|");
Serial.print(H);
Serial.print("|");
Serial.print(L);
Serial.println("/");
}
Telegram Bots
Il progetto prevede l’utilizzo anche della messaggistica Telegram per la gestione della pianta.
Questo è possibile grazie ai Bots messi a disposizione da Telegram LLC, che possono essere utilizzati per passare parametri alle applicazioni che li utilizzano.
Una volta creato il BOT, e ottenuto il Token univoco, attraverso una specifica libreria per Python (Telepot) è possibile interagire con esso attraverso messaggi, che vengono inviati attraverso il proprio account Telegram.
Programma gestione Telegram Bots e DB:
Il programma Python su Raspberry utilizza anche la messaggistica Telegram, rispondendo, a richiesta, sul valore dei valori acquisiti dai sensori e modificando sul server lo stato degli attuatori di controllo delle condizioni ambientali, se riceve messaggi di modifica.
I messaggi accettati sono:
– “Sensori” -> Risponde con il valore di tutti i sensori
– “T” -> Risponde con il valore della Temperatura
– “H” -> Risponde con il valore dell’Umidità del terreno
– “L” -> Risponde con il valore della Intensità luminosa
– “Accendi Riscaldatore” -> Attiva Riscaldatore
– “Spegni Riscaldatore” -> Disattiva Riscaldatore
– “Accendi Irrigazione” -> Attiva Pompa irrigazione
– “Spegni Irrigazione” -> Disattiva Pompa irrigazione
– “Accendi Illuminazione” -> Attiva Lampada di illuminazione
– “Spegni Illuminazione” -> Disattiva Lampada di illuminazione
Raspberry PI 3B
Programma Python
Raspberry ha il compito di inviare e ricevere dati dei Sensori da Arduino attraverso la comunicazione seriale e di gestire la messaggistica Telegram.
#!/usr/bin/env python
import time
import serial
import requests
import telepot
import datetime
from sys import exit
array_valori=[]
valori=[]
counter=0
ctrl=0
url=''
tempo_ultima_connessione=0
intervallo_connessioni=5 #sec tra una httprequest e l'altra
#Gestione Telegram Bots
id_a = [160285307]
def handle(msg):
chat_id = msg['chat']['id']
command = msg['text']
sender = msg['from']['id']
if sender in id_a:
if command == 'Sensori':
bot.sendMessage(chat_id, 'T='+valori[0]+'; H='+valori[1]+'; L='+valori[2])
elif command == 'T':
bot.sendMessage(chat_id, 'T='+valori[0])
elif command == 'H':
bot.sendMessage(chat_id, 'H='+valori[1])
elif command == 'L':
bot.sendMessage(chat_id, 'L='+valori[2])
elif command == 'Accendi riscaldatore':
requests.get('http://mylegalplants.it/web_app/attiva_T.php?T=1')
bot.sendMessage(chat_id, 'Riscaldatore acceso')
elif command == 'Spegni riscaldatore':
requests.get('http://mylegalplants.it/web_app/attiva_T.php?T=0')
bot.sendMessage(chat_id, 'Riscaldatore spento')
elif command == 'Accendi irrigazione':
requests.get('http://mylegalplants.it/web_app/attiva_H.php?H=1')
bot.sendMessage(chat_id, 'Irrigazione accesa')
elif command == 'Spegni irrigazione':
requests.get('http://mylegalplants.it/web_app/attiva_H.php?H=0')
bot.sendMessage(chat_id, 'Irrigazione spenta')
elif command == 'Accendi illuminazione':
requests.get('http://mylegalplants.it/web_app/attiva_L.php?L=1')
bot.sendMessage(chat_id, 'Illuminazione accesa')
elif command == 'Spegni illuminazione':
requests.get('http://mylegalplants.it/web_app/attiva_L.php?L=0')
bot.sendMessage(chat_id, 'Illuminazione spenta')
else:
bot.sendMessage(chat_id, 'Non sei autorizzate a darmi ordini!')
#bot.sendMessage(chat_id, sender)
bot = telepot.Bot('279377079:AAF4npjDymYPES4Dqkr7wBUR9D4AFwCYUFg') #TelegramBotToken MyLegalPlantsBot
bot.message_loop(handle)
print 'Sono in ascolto per Telegram..'
#Gestione invio/ricezione valori Sensori/Attuatori
arduino = serial.Serial(
port='/dev/ttyACM0',
baudrate = 9600,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
timeout = 1
)
try:
while True:
while arduino.in_waiting: #aspetto che ci sia comunicazione da parte di Arduino, che detta i tempi
RxData = arduino.read()
if RxData=='!':
ctrl=1 #inizio valori inviati
del array_valori[:] #cancello tutti gli elementi dell'array
if RxData=='/': ctrl=0 #fine valori inviati
if ctrl==1 and RxData!='!': array_valori.append(RxData)
if ctrl==0:
#print array_valori[:]
string_valori=''.join(array_valori) #stringa ottenuta dall'array_valori
valori=string_valori.split('|') #array dei valori di T, H e L
#controllo HTTPRequest server
tempo_attuale=time.time()
if (tempo_attuale-tempo_ultima_connessione)>intervallo_connessioni:
tempo_ultima_connessione=tempo_attuale
if tempo_ultima_connessione!=0 and len(valori)>0:
r = requests.get('http://mylegalplants.it/web_app/inserisci_valori.php?'+'T='+valori[0]+'&H='+valori[1]+'&L='+valori[2])
r_string=r.text
print valori[0],'-',valori[1],'-',valori[2],'|',r_string[0],'-',r_string[2],'-',r_string[4]
r_bytes=r_string.encode() #conversione string->bytes
arduino.write(r_bytes)
if r_string[2]=='1': #temporizzo irrigazione
print 'temporizzo irrigazione'
time.sleep(10)
requests.get('http://mylegalplants.it/web_app/attiva_H.php?H=0')
r_string_new=r_string.replace('1','0',1)
r_bytes_new=r_string_new.encode() #conversione string->bytes
arduino.write(r_bytes_new)
# per uscita con interrupt da tastiera dal programma (control+C)
except KeyboardInterrupt:
exit()