Differenze tra le versioni di "Termostato"

Da raspibo.
Jump to navigation Jump to search
 
(38 versioni intermedie di 3 utenti non mostrate)
Riga 1: Riga 1:
 
Le applicazioni dei termostati sono svariate, in questo caso partiamo con la realizzazione di un termostato per il controllo della caldaia di casa che può comunque essere ampliato con sensori o attuatori aggiuntivi ad esempio per il controllo del condizionatore.
 
Le applicazioni dei termostati sono svariate, in questo caso partiamo con la realizzazione di un termostato per il controllo della caldaia di casa che può comunque essere ampliato con sensori o attuatori aggiuntivi ad esempio per il controllo del condizionatore.
  
Per rendere il termostato più flessibile la gestione è modulare perciò i dati vengono salvati su [http://redis.io/]redis per la sua velocità, e la possibilità di sincronizzazione master/slave.
+
Per rendere il termostato più flessibile la gestione è modulare perciò i dati vengono salvati su [http://redis.io/ redis] per la sua velocità, e la possibilità di sincronizzazione master/slave.
  
Per rendere più facile la gestione viene utilizzata una interfaccia web implementata sul server web [http://nginx.org/]nginx con [http://www.php.net]php e librerie [http://humblesoftware.com/flotr2/]Flotr2 per la rappresentazione grafica dei dati.
+
Per rendere più facile la gestione viene utilizzata una interfaccia web implementata sul server web [http://nginx.org/ nginx] con [http://www.php.net php] e librerie [http://humblesoftware.com/flotr2/ Flotr2] per la rappresentazione grafica dei dati.
  
 
== Schema di massima ==
 
== Schema di massima ==
 +
 +
[[File:Termostato schema.jpg|400px]]
  
 
== Sensori utilizzati ==
 
== Sensori utilizzati ==
  
Per la misura della temperatura si possono uitlizzare i sensori DALLAS vedi voce [[Raspberry Pi-Lettura Temperatura]] per la semplicità d'uso, la possibilità di collegamento su un bus digitale in modo da usare pochi pin del GPIO.
+
Per la misura della temperatura si possono uitlizzare i sensori DALLAS vedi voce [[Raspberry Pi-Lettura Temperatura]] per la semplicità d'uso e la possibilità di collegamento su un bus digitale in modo da usare pochi pin del GPIO.
  
 
Questi sensori utilizzano un pin del gpio, possono essere collegati su bus lineare o a stella la lunghezza massima del collegamento arriva a 200 metri.
 
Questi sensori utilizzano un pin del gpio, possono essere collegati su bus lineare o a stella la lunghezza massima del collegamento arriva a 200 metri.
Riga 19: Riga 21:
 
Innanzitutto modificare il file /etc/modules inserendo i moduli per la gestioe del bus 1 wire:
 
Innanzitutto modificare il file /etc/modules inserendo i moduli per la gestioe del bus 1 wire:
  
 +
<source lang=bash>
 
  echo 'wire' >> /etc/modules
 
  echo 'wire' >> /etc/modules
 
  echo 'w1_gpio' >> /etc/modules
 
  echo 'w1_gpio' >> /etc/modules
 
  echo 'w1_therm' >> /etc/modules
 
  echo 'w1_therm' >> /etc/modules
 +
</source>
  
 
Riavviare il Raspberry ed installare i sensori.
 
Riavviare il Raspberry ed installare i sensori.
Riga 27: Riga 31:
 
Al riavvio nella dir /sys/bus/w1/devices/ si trovano i files relativi ai sensori:
 
Al riavvio nella dir /sys/bus/w1/devices/ si trovano i files relativi ai sensori:
  
 +
<pre style="color:green;overflow:auto">
 
  root@raspberrypi:~/termostato# ls -l /sys/bus/w1/devices/
 
  root@raspberrypi:~/termostato# ls -l /sys/bus/w1/devices/
 
  totale 0
 
  totale 0
Riga 34: Riga 39:
 
  lrwxrwxrwx 1 root root 0 mar 21 21:33 28-000004052c94 -> ../../../devices/w1_bus_master1/28-000004052c94/
 
  lrwxrwxrwx 1 root root 0 mar 21 21:33 28-000004052c94 -> ../../../devices/w1_bus_master1/28-000004052c94/
 
  lrwxrwxrwx 1 root root 0 mar 21 21:38 w1_bus_master1 -> ../../../devices/w1_bus_master1/
 
  lrwxrwxrwx 1 root root 0 mar 21 21:38 w1_bus_master1 -> ../../../devices/w1_bus_master1/
 +
</pre>
 +
 +
Se anche dopo aver verificato i collegamenti questo non funziona, modificare il file /boot/config.txt aggiungendo la seguente istruzione e riavviare (vedi riferimenti in fondo).
 +
 +
dtoverlay=w1-gpio,gpiopin=4
  
 
Si può procedere all'installazione vera e propria del software:
 
Si può procedere all'installazione vera e propria del software:
Riga 39: Riga 49:
 
il server redis per la memorizzazione dei dati
 
il server redis per la memorizzazione dei dati
  
 +
<pre style="color:blue;overflow:auto">
 
  sudo apt-get install redis-server bc  
 
  sudo apt-get install redis-server bc  
 +
</pre>
  
il comando elink per la lettura della temperatura esterna da inernet
+
il comando elink per la lettura della temperatura esterna da internet
  
 +
<pre style="color:blue;overflow:auto">
 
  sudo apt-get install elinks
 
  sudo apt-get install elinks
 +
</pre>
  
 
il software per la gestione via web
 
il software per la gestione via web
  
  sudo apt-get install nginx php5-fpm php5-cli php5-curl php5-cgi php-pear php5-gd
+
<pre style="color:blue;overflow:auto">
 +
  sudo apt-get install nginx php5-fpm php5-cli php5-curl php5-cgi php-pear php5-gd php5-dev
 +
</pre>
  
 
== Lettura sensori e salvataggio su redis ==
 
== Lettura sensori e salvataggio su redis ==
Riga 53: Riga 69:
 
Per la lettura si utilizza uno script in bash (/root/termostato/04_leggi_temperatura.sh):
 
Per la lettura si utilizza uno script in bash (/root/termostato/04_leggi_temperatura.sh):
  
 +
<source lang=bash>
 
  #!/bin/bash
 
  #!/bin/bash
 
  sensori[0]='28-000004052c94'
 
  sensori[0]='28-000004052c94'
Riga 91: Riga 108:
 
   fi
 
   fi
 
  fi
 
  fi
 +
</source>
  
 
Per la memorizzazione su Redis si lancia uno script che richiama il precedente per ogni sensore e lo associa alla zona da monitorare inoltre memorizza la data corrente(/root/termostato/05_memorizza_temp.sh):
 
Per la memorizzazione su Redis si lancia uno script che richiama il precedente per ogni sensore e lo associa alla zona da monitorare inoltre memorizza la data corrente(/root/termostato/05_memorizza_temp.sh):
  
 +
<source lang=bash>
 
  #!/bin/bash
 
  #!/bin/bash
 
  sensore[0]='28-000004052c94'
 
  sensore[0]='28-000004052c94'
Riga 114: Riga 133:
 
  /usr/bin/redis-cli rpush lettura "`date "+%Y-%m-%d %H:%M:%S"`"
 
  /usr/bin/redis-cli rpush lettura "`date "+%Y-%m-%d %H:%M:%S"`"
 
  /usr/bin/redis-cli rpush timestamp "`date "+%s"`"
 
  /usr/bin/redis-cli rpush timestamp "`date "+%s"`"
 +
</source>
  
Per la lettura della temperatura esterna nel mio caso ho fatto riferimento alla centralina meteo più vicina e leggo i dati via web(/root/termostato/06_display_letture.sh):
+
Per la lettura della temperatura esterna nel mio caso ho fatto riferimento alla centralina meteo più vicina e leggo i dati via web (/root/termostato/06_display_letture.sh):
  
 +
<source lang=bash>
 
  #!/bin/bash
 
  #!/bin/bash
 
  temp=`/usr/bin/elinks -dump "http://www.wunderground.com/weatherstation/WXDailyHistory.asp?ID=IITALIAB2&format=1"|awk -F "," '{print $2}'| grep '[0-9]\.[0-9]'| tail -1`
 
  temp=`/usr/bin/elinks -dump "http://www.wunderground.com/weatherstation/WXDailyHistory.asp?ID=IITALIAB2&format=1"|awk -F "," '{print $2}'| grep '[0-9]\.[0-9]'| tail -1`
 
  /usr/bin/redis-cli rpush temp_esterna $temp
 
  /usr/bin/redis-cli rpush temp_esterna $temp
 +
</source>
  
 
Una volta lanciati gli script precedenti si può verficare se vengono memorizzati correttamente su Redis:
 
Una volta lanciati gli script precedenti si può verficare se vengono memorizzati correttamente su Redis:
  
 +
<source lang=bash>
 
  #!/bin/bash
 
  #!/bin/bash
 
  echo "Visualizzazione elementi lista in redis"
 
  echo "Visualizzazione elementi lista in redis"
Riga 132: Riga 155:
 
  echo "Display valori lista temperatura esterna"
 
  echo "Display valori lista temperatura esterna"
 
  redis-cli lrange temp_esterna -10 -1
 
  redis-cli lrange temp_esterna -10 -1
 
+
</source>
 
 
  
 
== Configurazione ==
 
== Configurazione ==
  
Per il setup dei valori su redis si può utilizzare questo script che crea le variabili in cui memorizzare la programmazione settimanale creando due fasce orarie G=giorno e N=notte oguna con temperatura minima e massima.
+
Per il setup dei valori su redis si può utilizzare questo script che crea le variabili in cui memorizzare la programmazione settimanale creando due fasce orarie G=giorno e N=notte ognuna con temperatura minima e massima.
Vengono create anche le variabili per lo stato del rele ed altre variabili di appoggio per gli script successivi:
+
Vengono create anche le variabili per lo stato del rele` ed altre variabili di appoggio per gli script successivi:
  
 +
<source lang=bash>
 
  #!/bin/bash
 
  #!/bin/bash
 
  for x in `seq 0 6`
 
  for x in `seq 0 6`
Riga 184: Riga 207:
 
  redis-cli lrange min 0 -1  
 
  redis-cli lrange min 0 -1  
 
  redis-cli lrange max 0 -1
 
  redis-cli lrange max 0 -1
 +
</source>
  
 +
== Script di gestione del termostato ==
 +
 +
Lo script legge i dati da redis e decide in base all'ora di sistema la fascia di temperature da usare per il confronto con l'ultima lettura.
 +
La tolleranza sulla temperatura impostata di più o meno 0.25 grado, viene memorizzata su Redis anche una stringa che contiene tutti i dati utilizzati per le decisione presa.
 +
 +
=== /root/termostato/termostato.sh ===
 +
 +
<source lang=bash>
 +
#!/bin/bash
 +
ora=`date "+%H"`
 +
camera=`redis-cli lrange camera -1 -1`
 +
cucina=`redis-cli lrange cucina -1 -1`
 +
rele=`redis-cli lrange rele -1 -1`
 +
t_min_notte=`redis-cli get t_min_notte`
 +
t_max_notte=`redis-cli get t_max_notte`
 +
t_min_giorno=`redis-cli get t_min_giorno`
 +
t_max_giorno=`redis-cli get t_max_giorno`
 +
data_ora=`date "+%H:%M:%S"`
 +
giorni[1]="lun"
 +
giorni[2]="mar"
 +
giorni[3]="mer"
 +
giorni[4]="gio"
 +
giorni[5]="ven"
 +
giorni[6]="sab"
 +
giorni[7]="dom"
 +
gg_sett=`date "+%u"`
 +
n_giorno=${giorni[$gg_sett]}
 +
#ricavo la temperatura per l'ora corrente
 +
temp_att=`redis-cli lindex ${n_giorno} ${ora}`
 +
#case "$temp_att" in
 +
#N) echo "Programma attuale: notte"
 +
#controllo="${data_ora} Temp camera= ${camera}    - Invariato - notte  - min ${t_min_notte}/max ${t_max_notte} - Temperature: ${camera}/${cucina}"
 +
case "$temp_att" in
 +
N) echo "Programma attuale: notte"
 +
min=${t_min_notte}
 +
max=${t_max_notte}
 +
if (( `echo "$camera<${t_min_notte}" | bc -l` ))
 +
then
 +
rele=1
 +
controllo="${data_ora} Temp camera= ${camera} < ${t_min_notte} - notte - min ${t_min_notte}/max ${t_max_notte} - Temperature: ${camera}/${cucina}"
 +
fi
 +
if (( `echo "$camera>${t_max_notte}" | bc -l` ))
 +
then
 +
rele=0
 +
controllo="${data_ora} Temp camera= ${camera} > ${t_max_notte} - notte - min ${t_min_notte}/max ${t_max_notte} - Temperature: ${camera}/${cucina}"
 +
fi
 +
  ;;
 +
G) echo "Programma attuale: giorno"
 +
min=${t_min_giorno}
 +
max=${t_max_giorno}
 +
if (( `echo "$cucina<${t_min_giorno}" | bc -l` ))
 +
then
 +
rele=1
 +
controllo="${data_ora} Temp cucina= ${cucina} < ${t_min_giorno} - giorno - min ${t_min_giorno}/max ${t_max_giorno} - Temperature: ${camera}/${cucina}"
 +
fi
 +
if (( `echo "$cucina>${t_max_giorno}" | bc -l` ))
 +
then
 +
rele=0
 +
controllo="${data_ora} Temp cucina= ${cucina} > ${t_max_giorno} - giorno - min ${t_min_giorno}/max ${t_max_giorno} - Temperature: ${camera}/${cucina}"
 +
fi
 +
  ;;
 +
S) echo "Programma attuale: spento"
 +
min=0
 +
max=0
 +
controllo="${data_ora} Temp camera= ${camera},Temp cucina= ${cucina} - termo spento"
 +
rele=0
 +
  ;;
 +
esac
 +
/usr/bin/redis-cli rpush rele $rele > /dev/null
 +
#echo "d4=$rele" | /usr/bin/telnet localhost 2000
 +
if [ ! -d /sys/class/gpio/gpio25 ]
 +
then
 +
  echo "25" > /sys/class/gpio/export
 +
  echo "out" > /sys/class/gpio/gpio25/direction
 +
fi
 +
if [ $rele -eq 1 ]
 +
then
 +
echo "0" > /sys/class/gpio/gpio25/value
 +
else
 +
echo "1" > /sys/class/gpio/gpio25/value
 +
fi
 +
/usr/bin/redis-cli rpush controllo "$controllo"  > /dev/null
 +
/usr/bin/redis-cli rpush min "$min" > /dev/null
 +
/usr/bin/redis-cli rpush max "$max" > /dev/null
 +
#echo "camera=${camera} cucina=${cucina}"
 +
echo "Rele: $rele"
 +
echo "Controllo: $controllo"
 +
</source>
 +
 +
 +
Lo script che regola la temperatura è in bash e va schedulato con la giusta frequenza in crontab in modo che la caldaia non si accenda e spenga in continuazione ad esempio ogni 10 minuti.
 +
 +
crontab -e
 +
 +
ed aggiungere la seguenti righe
 +
 +
<source lang=bash>
 +
* * * * * /root/termostato/05_memorizza_temp.sh; /root/termostato/06_display_letture.sh > /dev/null
 +
*/10 * * * * /root/termostato/termostato.sh > /dev/null
 +
</source>
 +
 +
=== redis_2_csv.sh ===
 +
 +
Questo script è utile per il debug, viene anche utilizzato dalla pagina che visualizza il grafico per analizzare meglio il comportamento del termostato.
 +
 +
<source lang=bash>
 +
#!/bin/bash
 +
if [ $# == 2 ]
 +
then
 +
start=$1
 +
stop=$2
 +
else
 +
start=-72
 +
stop=-1
 +
fi
 +
redis-cli lrange uptime $start $stop > /tmp/uptime
 +
redis-cli lrange lettura $start $stop > /tmp/lettura
 +
redis-cli lrange timestamp $start $stop > /tmp/timestamp
 +
redis-cli lrange min $start $stop > /tmp/min
 +
redis-cli lrange max $start $stop > /tmp/max
 +
redis-cli lrange lettura $start $stop > /tmp/lettura
 +
redis-cli lrange temp_esterna $start $stop > /tmp/temp_esterna
 +
if [ $TERM == 'dumb' ]
 +
then
 +
redis-cli lrange temp_1 $start $stop > /tmp/temp_1
 +
redis-cli lrange temp_2 $start $stop > /tmp/temp_2
 +
redis-cli lrange temp_3 $start $stop > /tmp/temp_3
 +
else
 +
redis-cli lrange temp_1 $start $stop | sed 's:^:\o033\[31m:g' | sed 's/$/\o033\[0m/g' > /tmp/temp_1
 +
redis-cli lrange temp_2 $start $stop | sed 's:^:\o033\[32m:g' | sed 's/$/\o033\[0m/g' > /tmp/temp_2
 +
redis-cli lrange temp_3 $start $stop | sed 's:^:\o033\[34m:g' | sed 's/$/\o033\[0m/g' > /tmp/temp_3
 +
fi
 +
redis-cli lrange rele $start $stop > /tmp/rele
 +
redis-cli lrange controllo $start $stop > /tmp/controllo
 +
#88256  2013-01-05 09:20:01  1357374001  8.0  21.25  21.75  20.875  21.312  24.125  1  Invariato - giorno - min 21.25/max 21.75
 +
if [ $TERM == 'dumb' ]
 +
then
 +
echo -e "uptime    data      ora      T est T min  T max  camera camerina cucina rel decisione del termostato"
 +
echo -e "                                                    28-000004052dbd 40506c2 4056005"
 +
else
 +
echo -e "uptime    data      ora      T est T min  T max  \e[1;31mcamera\e[0m \e[1;32mcamerina\e[0m \e[1;34mcucina\e[0m rel decisione del termostato"
 +
echo -e "                                                    28-00000\e[1;31m4052dbd\e[0m \e[1;32m40506c2\e[0m \e[1;34m4056005\e[0m"
 +
fi
 +
tabella=`paste -d\| /tmp/uptime /tmp/lettura /tmp/temp_esterna /tmp/min /tmp/max /tmp/temp_1 /tmp/temp_2 /tmp/temp_3 /tmp/rele /tmp/controllo | column -t -s"|"`
 +
 +
if [ $TERM == 'dumb' ]
 +
then
 +
echo "$tabella" | tac
 +
else
 +
echo "$tabella"
 +
fi
 +
rm /tmp/uptime /tmp/lettura /tmp/temp_esterna /tmp/min /tmp/max /tmp/temp_1 /tmp/temp_2 /tmp/temp_3 /tmp/rele /tmp/controllo
 +
if [ $TERM == 'dumb' ]
 +
then
 +
echo -e "uptime    data      ora      T est T min  T max  camera camerina cucina rel decisione del termostato"
 +
fi
 +
</source>
 
== Configurazione del software installato ==
 
== Configurazione del software installato ==
  
Riga 191: Riga 372:
 
/etc/nginx/sites-enabled/default
 
/etc/nginx/sites-enabled/default
  
aggiungere index.php nela riga 25:
+
aggiungere index.php nella riga 33:
  
  index index.php index.html index.htm;
+
<pre style="color:green;overflow:auto">
 +
  index index.php index.html index.htm index.nginx-debian.html;
 +
</pre>
  
aggiungere/verificare la gestione delle pagine php a partire dalla riga 40:
+
Nel file di configurazione è già prevista la gestione di files php, infatti ci sono alcune righe commentate, noi però andiamo ad aggiungere la gestione delle pagine php con le seguenti instruzioni sempre all'interno del blocco server racchiuso tra parentesi graffe:
  
 +
<pre style="color:green;overflow:auto">
 
         location ~ \.php$ {
 
         location ~ \.php$ {
 +
                try_files $uri =404;
 
                 fastcgi_split_path_info ^(.+\.php)(/.+)$;
 
                 fastcgi_split_path_info ^(.+\.php)(/.+)$;
 
                 # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
 
                 # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
Riga 204: Riga 389:
 
                 fastcgi_pass unix:/var/run/php5-fpm.sock;
 
                 fastcgi_pass unix:/var/run/php5-fpm.sock;
 
                 fastcgi_index index.php;
 
                 fastcgi_index index.php;
                 include fastcgi_params;
+
                 include fastcgi.conf;
 
         }
 
         }
  
Installare phpredis facendo riferimento alle istruzioni sulla pagina dei sorgenti: https://github.com/nicolasff/phpredis
+
</pre>
 +
 
 +
Restartare ngnix per fargli leggere le modifiche
 +
 
 +
<pre style="color:green;overflow:auto">
 +
/etc/init.d/nginx restart
 +
</pre>
 +
 
 +
<pre style="color:green;overflow:auto">
 +
vi /etc/php5/fpm/php.ini
 +
</pre>
 +
 
 +
Settare a zero il parametro cgi.fix_pathinfo=0 per la gestione del path per gli script cgi come indicato nella parte commentata che abbiamo aggiunto al file /etc/nginx/sites-enabled/default
 +
 
 +
<pre style="color:green;overflow:auto">
 +
cgi.fix_pathinfo=0
 +
</pre>
 +
Installare phpredis facendo riferimento alle istruzioni sulla pagina dei sorgenti: https://github.com/nicolasff/phpredis
 +
 
 +
Modificare del php.ini inserendo 
 +
 
 +
extension=redis.so.
 +
 
 +
(a seconda della versione di raspbian la libreria potrebbe gia' essere caricata, eventualmente controllare ad esempio su phpinfo o sui log, non dovrebbe comunque causare problemi un doppio caricamento)
  
Una volta terminata l'installazione modificare il file php.ini copiando la riga dell'extension di redis dal file /etc/php5/cgi/php.ini e mettendola anche nel file /etc/php5/fpm/php.ini.
+
Installare redis da pecl
  
  extension=/usr/lib/php5/20100525+lfs/redis.so
+
  sudo pecl install redis
  
Restartare php5-fpm e nginx per applicare le modifiche.
+
Riavviare php5-fpm e nginx per applicare le modifiche.
  
 
A questo punto il server web dovrebbe essere funzionante.
 
A questo punto il server web dovrebbe essere funzionante.
Riga 219: Riga 427:
 
== Interfaccia web ==
 
== Interfaccia web ==
  
Per la visualizzazione grafica si usa la libreria [http://humblesoftware.com/flotr2/documentation]Flotr2, seguire le istruzioni sul sito per l'installazione.
+
A questo punto si tratta di creare qualche pagina php per la visualizzazione e modifica dei dati.
 +
 
 +
cd /tmp
 +
git clone https://github.com/dcast78/Termostato/
 +
 
 +
ora spostiamo le pagine web sotto /var/www e cambiamo il proprietario dei files
 +
 +
mv /tmp/Termostato/www/* /var/www/html/
 +
chown -R www-data:www-data /var/www/html/
 +
 
 +
Per la visualizzazione grafica si usa la libreria [http://humblesoftware.com/flotr2/documentation Flotr2].
 +
 
 +
Quindi basta clonare l'archivio git
  
a questo punto si tratta di creare qualche pagina php per la visualizzazione e modifica dei dati.
+
cd /var/www/html
 +
git clone https://github.com/HumbleSoftware/Flotr2
 +
 
 +
== Riferimenti ==
 +
 
 +
* Come indicato sopra l'archivio dei files si trova su [https://github.com/dcast78/Termostato github]
 +
* Modifica del file /boot/config.txt [http://www.raspberrypi-spy.co.uk/2013/03/raspberry-pi-1-wire-digital-thermometer-sensor/] se 1wire non funziona.
  
 
== Screen shoot ==
 
== Screen shoot ==
 +
[[File:Termostato imposta temp.png|615px|thumb|center|Imposta temperature]]
 +
[[File:Termostato prog settimana.png|615px|thumb|center|Imposta programma settimanale]]
 +
[[File:Termostato grafico.png|615px|thumb|center|Visualizzazzione grafica]]
 +
 +
 +
[[Category:Progetti]]

Versione attuale delle 13:40, 4 gen 2016

Le applicazioni dei termostati sono svariate, in questo caso partiamo con la realizzazione di un termostato per il controllo della caldaia di casa che può comunque essere ampliato con sensori o attuatori aggiuntivi ad esempio per il controllo del condizionatore.

Per rendere il termostato più flessibile la gestione è modulare perciò i dati vengono salvati su redis per la sua velocità, e la possibilità di sincronizzazione master/slave.

Per rendere più facile la gestione viene utilizzata una interfaccia web implementata sul server web nginx con php e librerie Flotr2 per la rappresentazione grafica dei dati.

Schema di massima

Termostato schema.jpg

Sensori utilizzati

Per la misura della temperatura si possono uitlizzare i sensori DALLAS vedi voce Raspberry Pi-Lettura Temperatura per la semplicità d'uso e la possibilità di collegamento su un bus digitale in modo da usare pochi pin del GPIO.

Questi sensori utilizzano un pin del gpio, possono essere collegati su bus lineare o a stella la lunghezza massima del collegamento arriva a 200 metri.

Possono essere utilizzati anche altri sensori grazie alla modularità del sistema basta infatti che i dati vengano inseriti in redis.

Installazione del software

Innanzitutto modificare il file /etc/modules inserendo i moduli per la gestioe del bus 1 wire:

 echo 'wire' >> /etc/modules
 echo 'w1_gpio' >> /etc/modules
 echo 'w1_therm' >> /etc/modules

Riavviare il Raspberry ed installare i sensori.

Al riavvio nella dir /sys/bus/w1/devices/ si trovano i files relativi ai sensori:

 root@raspberrypi:~/termostato# ls -l /sys/bus/w1/devices/
 totale 0
 drwxr-xr-x 2 root root 0 mar 21 21:33 ./
 drwxr-xr-x 4 root root 0 mar 21 21:33 ../
 lrwxrwxrwx 1 root root 0 mar 21 21:33 28-0000040520d3 -> ../../../devices/w1_bus_master1/28-0000040520d3/
 lrwxrwxrwx 1 root root 0 mar 21 21:33 28-000004052c94 -> ../../../devices/w1_bus_master1/28-000004052c94/
 lrwxrwxrwx 1 root root 0 mar 21 21:38 w1_bus_master1 -> ../../../devices/w1_bus_master1/

Se anche dopo aver verificato i collegamenti questo non funziona, modificare il file /boot/config.txt aggiungendo la seguente istruzione e riavviare (vedi riferimenti in fondo).

dtoverlay=w1-gpio,gpiopin=4

Si può procedere all'installazione vera e propria del software:

il server redis per la memorizzazione dei dati

 sudo apt-get install redis-server bc 

il comando elink per la lettura della temperatura esterna da internet

 sudo apt-get install elinks

il software per la gestione via web

 sudo apt-get install nginx php5-fpm php5-cli php5-curl php5-cgi php-pear php5-gd php5-dev

Lettura sensori e salvataggio su redis

Per la lettura si utilizza uno script in bash (/root/termostato/04_leggi_temperatura.sh):

 #!/bin/bash
 sensori[0]='28-000004052c94'
 sensori[1]='28-0000040520d3'
 #controllo che lo script venga lanciato con 1 parametro
 if [ $# != 1 ]
  then
  echo -n "Lancia lo script: $0 [all"
  for i in "${sensori[@]}"
  do
    echo -n "|$i"
  done
  echo ']'
 else 
  if [ $1 == "all" ] # Se lanciato con il parametro all visualizza la lettura di tutti i sensori
  then
   for i in "${sensori[@]}"
   do
     $0 $i 
   done
  else
  sensore=$1
 
  for x in 1 2 3 4
  do
   lettura=`paste -s /sys/bus/w1/devices/${sensore}/w1_slave | grep YES` # esegue la lettura verificando il CRC
  # echo $?
  # echo lettura
   if [ $? == 0 ]
    then temp=$lettura; break
    else temp='ERR' ; break
   fi
  done
 
  temperatura=`echo $temp | paste -s | awk -F "=" '{print $3/1000}'`
 
  echo $temperatura
  fi
 fi

Per la memorizzazione su Redis si lancia uno script che richiama il precedente per ogni sensore e lo associa alla zona da monitorare inoltre memorizza la data corrente(/root/termostato/05_memorizza_temp.sh):

 #!/bin/bash
 sensore[0]='28-000004052c94'
 sensore[1]='28-0000040520d3'
 d_sensore[0]='cucina'
 d_sensore[1]='camera'
 x=0
 for i in "${sensore[@]}"
 do
  temp=`/root/termostato/04_leggi_temperatura.sh $i`
  if [ "$temp" != "-0.062" ]
   then
   if [ "$temp" != "85" ]
    then
     /usr/bin/redis-cli rpush ${d_sensore[${y}]} $temp
   fi
  fi
 y=`expr $y + 1` 
 done
 /usr/bin/redis-cli rpush lettura "`date "+%Y-%m-%d %H:%M:%S"`"
 /usr/bin/redis-cli rpush timestamp "`date "+%s"`"

Per la lettura della temperatura esterna nel mio caso ho fatto riferimento alla centralina meteo più vicina e leggo i dati via web (/root/termostato/06_display_letture.sh):

 #!/bin/bash
 temp=`/usr/bin/elinks -dump "http://www.wunderground.com/weatherstation/WXDailyHistory.asp?ID=IITALIAB2&format=1"|awk -F "," '{print $2}'| grep '[0-9]\.[0-9]'| tail -1`
 /usr/bin/redis-cli rpush temp_esterna $temp

Una volta lanciati gli script precedenti si può verficare se vengono memorizzati correttamente su Redis:

 #!/bin/bash
 echo "Visualizzazione elementi lista in redis"
 redis-cli keys "*"
 echo "Display valori lista primo sensore: cucina"
 redis-cli lrange cucina -10 -1
 echo "Display valori lista primo sensore: camera"
 redis-cli lrange camera -10 -1
 echo "Display valori lista temperatura esterna"
 redis-cli lrange temp_esterna -10 -1

Configurazione

Per il setup dei valori su redis si può utilizzare questo script che crea le variabili in cui memorizzare la programmazione settimanale creando due fasce orarie G=giorno e N=notte ognuna con temperatura minima e massima. Vengono create anche le variabili per lo stato del rele` ed altre variabili di appoggio per gli script successivi:

 #!/bin/bash
 for x in `seq 0 6`
 do
  redis-cli rpush lun N
  redis-cli rpush mar N
  redis-cli rpush mer N
  redis-cli rpush gio N
  redis-cli rpush ven N
  redis-cli rpush sab N
  redis-cli rpush dom N
 done
 for x in `seq 7 23`
 do
  redis-cli rpush lun G
  redis-cli rpush mar G
  redis-cli rpush mer G
  redis-cli rpush gio G
  redis-cli rpush ven G
  redis-cli rpush sab G
  redis-cli rpush dom G
 done
 redis-cli lrange lun 0 23
 redis-cli lrange mar 0 23
 redis-cli lrange mer 0 23
 redis-cli lrange gio 0 23
 redis-cli lrange ven 0 23
 redis-cli lrange sab 0 23
 redis-cli lrange dom 0 23
 redis-cli set t_min_giorno 21
 redis-cli set t_max_giorno 21.5
 redis-cli set t_min_notte 21
 redis-cli set t_max_notte 21.5
 redis-cli get t_min_giorno 
 redis-cli get t_max_giorno 
 redis-cli get t_min_notte
 redis-cli get t_max_notte 
 redis-cli lpush rele 0 
 redis-cli lrange rele 0 -1 
 redis-cli lpush timestamp 0 
 redis-cli lrange timestamp 0 -1 
 redis-cli rpush min 0
 redis-cli rpush max 0
 redis-cli lrange min 0 -1 
 redis-cli lrange max 0 -1

Script di gestione del termostato

Lo script legge i dati da redis e decide in base all'ora di sistema la fascia di temperature da usare per il confronto con l'ultima lettura. La tolleranza sulla temperatura impostata di più o meno 0.25 grado, viene memorizzata su Redis anche una stringa che contiene tutti i dati utilizzati per le decisione presa.

/root/termostato/termostato.sh

 #!/bin/bash
 ora=`date "+%H"`
 camera=`redis-cli lrange camera -1 -1` 
 cucina=`redis-cli lrange cucina -1 -1` 
 rele=`redis-cli lrange rele -1 -1`
 t_min_notte=`redis-cli get t_min_notte`
 t_max_notte=`redis-cli get t_max_notte`
 t_min_giorno=`redis-cli get t_min_giorno`
 t_max_giorno=`redis-cli get t_max_giorno`
 data_ora=`date "+%H:%M:%S"`
 giorni[1]="lun"
 giorni[2]="mar"
 giorni[3]="mer"
 giorni[4]="gio"
 giorni[5]="ven"
 giorni[6]="sab"
 giorni[7]="dom"
 gg_sett=`date "+%u"`
 n_giorno=${giorni[$gg_sett]}
 #ricavo la temperatura per l'ora corrente
 temp_att=`redis-cli lindex ${n_giorno} ${ora}` 
 #case "$temp_att" in
 #N) echo "Programma attuale: notte"
 #controllo="${data_ora} Temp camera= ${camera}     - Invariato - notte  - min ${t_min_notte}/max ${t_max_notte} - Temperature: ${camera}/${cucina}"
 case "$temp_att" in
 N) echo "Programma attuale: notte"
 min=${t_min_notte}
 max=${t_max_notte}
 if (( `echo "$camera<${t_min_notte}" | bc -l` )) 
 then
 rele=1
 controllo="${data_ora} Temp camera= ${camera} < ${t_min_notte} - notte - min ${t_min_notte}/max ${t_max_notte} - Temperature: ${camera}/${cucina}"
 fi
 if (( `echo "$camera>${t_max_notte}" | bc -l` )) 
 then
 rele=0
 controllo="${data_ora} Temp camera= ${camera} > ${t_max_notte} - notte - min ${t_min_notte}/max ${t_max_notte} - Temperature: ${camera}/${cucina}"
 fi
  ;;
 G) echo "Programma attuale: giorno"
 min=${t_min_giorno}
 max=${t_max_giorno}
 if (( `echo "$cucina<${t_min_giorno}" | bc -l` )) 
 then
 rele=1
 controllo="${data_ora} Temp cucina= ${cucina} < ${t_min_giorno} - giorno - min ${t_min_giorno}/max ${t_max_giorno} - Temperature: ${camera}/${cucina}"
 fi
 if (( `echo "$cucina>${t_max_giorno}" | bc -l` )) 
 then
 rele=0
 controllo="${data_ora} Temp cucina= ${cucina} > ${t_max_giorno} - giorno - min ${t_min_giorno}/max ${t_max_giorno} - Temperature: ${camera}/${cucina}"
 fi
   ;;
 S) echo "Programma attuale: spento"
 min=0
 max=0
 controllo="${data_ora} Temp camera= ${camera},Temp cucina= ${cucina} - termo spento"
 rele=0
   ;;
 esac
 /usr/bin/redis-cli rpush rele $rele > /dev/null
 #echo "d4=$rele" | /usr/bin/telnet localhost 2000
 if [ ! -d /sys/class/gpio/gpio25 ] 
 then
   echo "25" > /sys/class/gpio/export
   echo "out" > /sys/class/gpio/gpio25/direction
 fi
 if [ $rele -eq 1 ] 
 then 
 echo "0" > /sys/class/gpio/gpio25/value
 else
 echo "1" > /sys/class/gpio/gpio25/value
 fi
 /usr/bin/redis-cli rpush controllo "$controllo"  > /dev/null
 /usr/bin/redis-cli rpush min "$min" > /dev/null
 /usr/bin/redis-cli rpush max "$max" > /dev/null
 #echo "camera=${camera} cucina=${cucina}"
 echo "Rele: $rele"
 echo "Controllo: $controllo"


Lo script che regola la temperatura è in bash e va schedulato con la giusta frequenza in crontab in modo che la caldaia non si accenda e spenga in continuazione ad esempio ogni 10 minuti.

crontab -e

ed aggiungere la seguenti righe

* * * * * /root/termostato/05_memorizza_temp.sh; /root/termostato/06_display_letture.sh > /dev/null
*/10 * * * * /root/termostato/termostato.sh > /dev/null

redis_2_csv.sh

Questo script è utile per il debug, viene anche utilizzato dalla pagina che visualizza il grafico per analizzare meglio il comportamento del termostato.

#!/bin/bash
if [ $# == 2 ] 
then
 start=$1
 stop=$2
else 
 start=-72
 stop=-1
fi
redis-cli lrange uptime $start $stop > /tmp/uptime 
redis-cli lrange lettura $start $stop > /tmp/lettura
redis-cli lrange timestamp $start $stop > /tmp/timestamp 
redis-cli lrange min $start $stop > /tmp/min
redis-cli lrange max $start $stop > /tmp/max
redis-cli lrange lettura $start $stop > /tmp/lettura
redis-cli lrange temp_esterna $start $stop > /tmp/temp_esterna
if [ $TERM == 'dumb' ]
 then
 redis-cli lrange temp_1 $start $stop > /tmp/temp_1 
 redis-cli lrange temp_2 $start $stop > /tmp/temp_2 
 redis-cli lrange temp_3 $start $stop > /tmp/temp_3 
else
 redis-cli lrange temp_1 $start $stop | sed 's:^:\o033\[31m:g' | sed 's/$/\o033\[0m/g' > /tmp/temp_1 
 redis-cli lrange temp_2 $start $stop | sed 's:^:\o033\[32m:g' | sed 's/$/\o033\[0m/g' > /tmp/temp_2 
 redis-cli lrange temp_3 $start $stop | sed 's:^:\o033\[34m:g' | sed 's/$/\o033\[0m/g' > /tmp/temp_3 
fi
redis-cli lrange rele $start $stop > /tmp/rele 
redis-cli lrange controllo $start $stop > /tmp/controllo 
#88256  2013-01-05 09:20:01  1357374001  8.0  21.25  21.75  20.875  21.312  24.125  1  Invariato - giorno - min 21.25/max 21.75
if [ $TERM == 'dumb' ]
 then
echo -e "uptime    data      ora      T est T min  T max   camera camerina cucina rel decisione del termostato"
echo -e "                                                    28-000004052dbd 40506c2 4056005"
else
echo -e "uptime    data      ora      T est T min  T max   \e[1;31mcamera\e[0m \e[1;32mcamerina\e[0m \e[1;34mcucina\e[0m rel decisione del termostato"
echo -e "                                                    28-00000\e[1;31m4052dbd\e[0m \e[1;32m40506c2\e[0m \e[1;34m4056005\e[0m"
fi
tabella=`paste -d\| /tmp/uptime /tmp/lettura /tmp/temp_esterna /tmp/min /tmp/max /tmp/temp_1 /tmp/temp_2 /tmp/temp_3 /tmp/rele /tmp/controllo | column -t -s"|"`

if [ $TERM == 'dumb' ]
 then
echo "$tabella" | tac
else 
echo "$tabella" 
fi
rm /tmp/uptime /tmp/lettura /tmp/temp_esterna /tmp/min /tmp/max /tmp/temp_1 /tmp/temp_2 /tmp/temp_3 /tmp/rele /tmp/controllo
if [ $TERM == 'dumb' ]
 then
echo -e "uptime    data      ora      T est T min  T max   camera camerina cucina rel decisione del termostato"
fi

Configurazione del software installato

Va configurato il server web nginx editando il file:

/etc/nginx/sites-enabled/default

aggiungere index.php nella riga 33:

 index index.php index.html index.htm index.nginx-debian.html;

Nel file di configurazione è già prevista la gestione di files php, infatti ci sono alcune righe commentate, noi però andiamo ad aggiungere la gestione delle pagine php con le seguenti instruzioni sempre all'interno del blocco server racchiuso tra parentesi graffe:

        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
                # With php5-cgi alone:
                # With php5-fpm:
                fastcgi_pass unix:/var/run/php5-fpm.sock;
                fastcgi_index index.php;
                include fastcgi.conf;
        }

Restartare ngnix per fargli leggere le modifiche

 /etc/init.d/nginx restart
 vi /etc/php5/fpm/php.ini

Settare a zero il parametro cgi.fix_pathinfo=0 per la gestione del path per gli script cgi come indicato nella parte commentata che abbiamo aggiunto al file /etc/nginx/sites-enabled/default

 cgi.fix_pathinfo=0

Installare phpredis facendo riferimento alle istruzioni sulla pagina dei sorgenti: https://github.com/nicolasff/phpredis

Modificare del php.ini inserendo

extension=redis.so.

(a seconda della versione di raspbian la libreria potrebbe gia' essere caricata, eventualmente controllare ad esempio su phpinfo o sui log, non dovrebbe comunque causare problemi un doppio caricamento)

Installare redis da pecl

sudo pecl install redis

Riavviare php5-fpm e nginx per applicare le modifiche.

A questo punto il server web dovrebbe essere funzionante.

Interfaccia web

A questo punto si tratta di creare qualche pagina php per la visualizzazione e modifica dei dati.

cd /tmp
git clone https://github.com/dcast78/Termostato/

ora spostiamo le pagine web sotto /var/www e cambiamo il proprietario dei files

mv /tmp/Termostato/www/* /var/www/html/
chown -R www-data:www-data /var/www/html/

Per la visualizzazione grafica si usa la libreria Flotr2.

Quindi basta clonare l'archivio git

cd /var/www/html
git clone https://github.com/HumbleSoftware/Flotr2

Riferimenti

  • Come indicato sopra l'archivio dei files si trova su github
  • Modifica del file /boot/config.txt [1] se 1wire non funziona.

Screen shoot

Imposta temperature
Imposta programma settimanale
Visualizzazzione grafica