

Il box per i collegamenti

Il connettore a 9 pin

Le sonde con XLR
In questa pagina descrivo come implementare un raspi nel bagno.
Hardware:
1. Raspberry PI2
2. TouchScreen 7"
3. Sonda Temperatura Umidità AM2302 (versione "wired" della DHT22)
4. Sonda Temperatura esterna 18B20
5. Sonda Temperatura acqua doccia 18B20
6. Flussimetro 5volt
7. Sensore PIR
Software:
Adafruit software per la lettura della sonda temperatura umidità.
Il solito codice python per il web-scraping e per il main il cui risultato si vede in foto.
Come si vede dalla foto della schermata, ho sul display l'ora ed il giorno attuali, la temperatura del bagno, l'umidità del bagno, la temperatura esterna, la temperatura della doccia (calda, fredda e mixata) e dati relativi il consumo di acqua della doccia.
Sotto si vedono le previsioni del tempo per le prossime ore e un pulsante di chiusura del programma (essendo impostato pygame.NOFRAME).
Lo scopo di questo aggeggio è quello di avere delle informazioni relative l’acqua della doccia e informazioni esterne che possono essere utili durante questi momenti.
TEMPERATURE
Le temperature lette sono quelle dell’acqua in doccia, con un sensore per ogni acqua: la fredda dell’acquedotto, la cada della caldaia e quella mixata che ci cade in testa. In particolare quest’ultima è utile per sapere quando si può entrare in box (chi non ha il ricircolo e il bagno è lontano dalla caldaia sa che deve aspettare un po’ prima di avere l’acqua alla temperatura desiderata). Il colore del valore indicato varia dal blu per l’acqua fredda, al verde per quella considerata accettabile, al rosso quando troppo calda.
FLUSSO DELL’ACQUA
Ho inserito un flussimetro non tanto per una reale utilità ma solo per un mio esercizio volto a comprendere quanti litri di acqua si consumano per le docce.
Il flussimetro è quello classico che si trova ovunque. Purtroppo però è disponibile per il raspi & c. solo a 5 volt (5-18), ciò significa che non è compatibile con i microcontrollers tipo raspberry che hanno la GPIO a 3 volt. Per questo motivo si deve utilizzare un partitore di tensione. Un partitore di tensione (esiste anche quello per la corrente) non è altro che un circuito con resistenze in serie che sfrutta la legge empirica di Ohm. Il voltaggio in uscita da questo circuito è direttamente proporzionale al voltaggio in entrata moltiplicato per la resistenza da cui si preleva la tensione fratto la somma delle due resistenze in serie.

Nel disegno sopra si può vedere una simulazione (grazie a Tinkercad di Autodesk!) utilizzando le resistenze necessarie a portare i 5 v a circa 3.3 v, cioè una da 4.7kohm e una (utilizzata per prelevare la tensione desiderata) da 10kohm.
Il filo arancione è quello che andrà al pin della GPIO e che darà l’IN alla chiusura del contatto sul flussimetro.
Per la taratura (modifica del valore di conversione degli impulsi in litri) si può procedere in questo modo: si legge il contatore di casa, si apre solo la doccia per un periodo a scelta, si legge nuovamente il contatore. Se i dati non coincidono si aggiusta il parametro di conversione. Se si vuole fare prima si stampa a video il counter degli impulsi e, se si deve aggiustare il risultato, si prendono i litri letti dal contatore e si dividono per gli impulsi.
Attenzione però che nel mio script il conteggio dei litri avviene solo se la temperatura è maggiore di 20 gradi, modificare questo parametro o fare la prova con l’acqua già calda.
Qui di seguito tutto il circuito del mio raspi.

Il flussimetro viene gestito da uno script.py che è sempre in esecuzione, i dati registrati vengono poi prelevati da un altro script che mostrerà i valori delle misure sullo screen. Lo script del flussimetro scrive anche i dati su un file di testo che serve a riprendere i valori memorizzati del mese in caso di reboot.
Un crontab fa il riavvio del raspi ad ogni primo giorno del mese e nello script del flussimetro c’è un controllo al riavvio dello stesso: se il giorno del riavvio è il primo del mese azzera tutti i valori del flussimetro.
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import time, sys, datetime
import read_dallas_module
import glob
GPIO.setmode(GPIO.BCM)
pin = 17
GPIO.setup(pin, GPIO.IN)
litreconv = 0.004883
interval = 10
counter = 0
now=datetime.datetime.now()
if datetime.datetime.now().day == 1:
start = now.strftime('%d %b %Y')
with open("/home/pi/Bath/flowmeter.txt", "w") as f:
seq=(str(start)+'\n','0\n', '0\n', '0\n', '0\n')
litres_tot = 0
minutes = 0
litres_last_shower = 0
shower_counter=0
cumulative = 0
f.writelines(seq)
else:
with open('/home/pi/Bath/flowmeter.txt', 'r') as f:
content=f.readlines()
'''initializes all variables reading values stored
in file.txt, last_shower is initialized to 0'''
litres_tot= round(float(content[1]), 1)
minutes = int(content[2])
shower_counter = int(content[3])
cumulative = int(litres_tot/litreconv)
litres_last_shower = 0
def reading(pin):
global counter, cumulative
counter += 1
cumulative += 1
GPIO.add_event_detect(pin, GPIO.RISING, callback=reading, bouncetime = 20)
ts = 1
pause=True
Nel ciclo principale prima leggo la temperatura con un modulo importato. Poi inizio a leggere i dati del flussimetro in blocchi di 60 secondi allo scopo di avere un conteggio anche dei minti di doccia.
while True:
'''read temp shower for the following condition'''
temp_shower=read_dallas_module.D18B20("temp_shower")
temp_shower=temp_shower.read_temp()
Quest'ultimo codice serve a verificare di essere alla fine della doccia e, trascorsi 3 minuti (per quelli che usano spengere la doccia per insaponarsi i capelli) senza essere stata riaperta l'acqua, procede con le memorizzazioni finali: nr di docce e litri ultima doccia.
'''check if temp_shower is over 20 deg and flow is running'''
if temp_shower >20 and GPIO.event_detected(pin) and counter>250:
'''keeps running'''
pause= False
ts = time.time()
'''loop for storing data during a fixed interval
the interval is needed for calculate time of shower'''
while pause == False:
tn = time.time()+60
'''litres last shower are set to 0 for each shower'''
litres_last_shower = 0
while time.time() <= tn:
print(GPIO.input(pin), end='') #only for debugging
pause=True
'''this condition is for clearing the status of
flow meter that would replicate the reading
(nothing to do with bouncing!!!)'''
not GPIO.event_detected(pin)
minutes+=1
litres_tot = round(cumulative * litreconv, 1)
time.sleep(0.2)
with open('/home/pi/Bath/flowmeter.txt', 'r+') as f:
content[1]=str(litres_tot)+'\n'
content[2]=str(minutes)+'\n'
f.writelines(content)
pause=False
elif temp_shower >2 and not GPIO.event_detected(pin) and time.time()>(ts+180):
if pause is False:
litres_last_shower = round((counter) * litreconv, 1)
shower_counter+=1
time.sleep(1)
with open('/home/pi/Bath/flowmeter.txt', 'r+') as f:
content[3]=str(shower_counter)+'\n'
content[4]=str(litres_last_shower)+'\n'
f.writelines(content)
pause = True
counter = 0
litres_last_shower = 0
GPIO.cleanup()
sys.exit()
Di seguito come ho preso le informazioni per le previsioni del tempo.
import urllib2
import time
from bs4 import BeautifulSoup
import sys
hdr = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
'Accept-Encoding': 'none',
'Accept-Language': 'en-US,en;q=0.8',
'Connection': 'keep-alive'}
url = "http://www."miosito"/"paginadimiosito""
req = urllib2.Request(url, headers=hdr)
page = urllib2.urlopen(req)
soup = BeautifulSoup(urllib2.urlopen(req).read(), "lxml")
def h3_with_"ParolaChiave"(tag):
return tag.name == 'h3' and tag.text.startswith("ParolaChiave")
f=soup.find_all(h3_with_"ParolaChiave")[0]
h=f.findNextSibling()
reload(sys)
sys.setdefaultencoding("latin-1")
file = open("/home/pi/"FilediArchiviazione".txt","w")
file.write(h.string)
file.close()
Il codice sopra riportato sfrutta il noto BeautifulSoup, nella versione 4. Sono poche righe perchè in realtà non è particolarmente complesso il suo utilizzo, tuttavia ho riscontrato un pò di difficoltà nella terminologia giusta.
Infatti le istruzioni possono essere diverse anche per una virgola e differiscono a secondo del contesto in cui sono
scritte.
Attenzione al "parser" che installate, nel mio caso lxml, che deve essere utilizzata la solita istruzione apt-get install python-lxml e non pip
perchè così per me è stato l'unico metodo funzionante.
La funzione "def h3_with_"ParolaChiave"(tag):" serve a cercare su tutto il sito una parola chiave per identificare il blocco di testo con le previsioni.
Una volta trovata, prende la prima dell'elenco (se ci sono più parole chiave e se la prima è quella che interessa).
L'istruzione seguente è quella che memorizza il testo successivo alla parola chiave. Per visualizzare correttamente le parole accentate della lingua italiana
ho inserito la successiva istruzione con la corretta codifica.
h=f.findNextSibling()
A questo punto lo script apre il file di testo dove memorizzare le previsioni e vi scrive quanto rilevato.
Un launcher di avvio di questo programma di web scraping, memorizzato nel cronotab, ripeterà ad intervalli regolari la lettura delle previsioni del tempo. Nel mio caso è solo qualche volta in 24 ore.
Nel programma principale il loop andrà a leggere il testo di questo file e lo riporterà a video.
Nella foto si vedono poche parole di previsioni ma in realtà le parole scorrono al fine di permettere la visualizzazione
di testo anche più lungo. All'inizio avevo creato un'istruzione per visualizzare un vero e proprio scorrimmento orizzontale. Tuttavia una volta
messo in azione nel programma principale, completo di lettura delle sonde, avevo dei blocchi tra un refresh e l'altro. Così, anche per
pigrizia, ho deciso di fare uno scorrimento a blocchi di 700 caratteri circa. Magari tra un pò di tempo proverò a rivedere il codice e cercare
una soluzione per avere lo scorrimento orizzontale continuo.
Infine, a proposito del sensore PIR, questo serve solo a svegliare lo schermo dallo screensaver. Infatti, pur non essendoci per ora la possibilità di
mettere il monitor del raspberry in stand-by, per evitare sprechi di corrente, ho utilizzato lo screensaver per risparmiare un pò di corrente, rendendo
lo schermo nero. Con il sensore ho la possibilità di riattivare lo schermo al momento dell'entrata di una persona nel locale.
TAF!