Temperaturen meten met de RPi

Doel 

Temperaturen meten en vastleggen in bestanden met de RPi

Benodigdheden 
Tutorial 

Temperaturen meten met de RPi is vrij eenvoudig. Het is ook leuk om te zien hoe de temperatuur verloopt in je huis of om te kijken hoe koud het nu eigenlijk 's nachts wordt in de slaapkamer. Je kunt ook kijken hoe dit afhangt van de buitentemperatuur en zien hoe snel je huis opwarmt op een zonnige dag. Uiteindelijk moet je ook temperaturen kunnen meten als je zelf een slimme thermostaat wil maken.

De sensoren aansluiten

Zorg dat je RPi uitstaat (en de voedingsstekker er niet in zit) bij het aansluiten van dingen op de GPIO, de pinnen gaan direct de cpu in en kortsluiting schijnt makkelijk te kunnen gebeuren.
De twee sensoren die ik heb gebruikt sluit je aan op 5V, aarde (ground), en GPIO4 voor het uitlezen (zie " De Raspberry Pi GPIO pinnen"), ik gebruik daar een breadboard en wat "dupont wires" voor (je sluit dus allebei de sensoren op precies dezelfde pinnen aan). Ik heb van mensen gehoord dat ik een weerstand tussen de data poort van de sensor en GPIO4 zou moeten zetten (een pull-up resistor, 4.7 kOhm bijvoorbeeld) maar bij de versie die ik heb zit die weerstand al ingebouwd, ten minste, in de sensor voor binnen. Bij de sensor voor buiten zie ik het niet staan bij de specs dus misschien is het handig dat nog even zelf er tussen te zetten. Als alles is aangesloten kun je je RPi aanzetten.

De sensoren uitlezen

Om de sensoren aan te kunnen spreken heeft de linux kernel de volgende twee modules nodig: w1-therm en w1-gpio. Je kunt deze nu handmatig laden door te typen:
sudo modprobe w1-therm && sudo modprobe w1-gpio
Maar je kunt ze ook elke keer na een reboot weer automatisch laden door de modules toe te voegen aan het bestand /etc/modules:
sudo nano /etc/modules Voeg onderaan de file toe:
w1-therm
w1-gpio
Na het laden van de modules staan er in de map /sys/bus/w1/devices/ 1 of 2 (of meer), mappen met nummers als (in mijn geval) 28-000005838064 en 28-0014159e1dff. Elke map staat voor 1 sensor. Let op, als je in deze map geen nummer vindt moet je misschien in /boot/config.txt de volgende text helemaal onderaan toevoegen. Voor was dit ineens nodig toen ik een verse installatie deed:
sudo nano /boot/config.txt
dtoverlay=w1-gpio,gpiopin=4
Nogmaals, dit lijkt niet bij iedereen nodig te zijn.

Bij jou hebben de sensors waarschijnlijk een ander nummer, je vindt jouw nummers met dit commando:
ls /sys/bus/w1/devices/
In de map (of, in beide mappen) vind je een bestand genaamd w1_slave, als je dit bestand "cat" krijg je de rauwe output van de sensor te zien, let op dit commando werkt alleen bij mij, bij jou heeft de map waarschijnlijk een andere naam:
cat /sys/bus/w1/devices/28-0014159e1dff/w1_slave
Je krijgt de volgende output te zien:

98 01 55 00 7f ff 0c 10 24 : crc=24 YES
98 01 55 00 7f ff 0c 10 24 t=25500
Bij mij was het op het moment dat ik dit commando uitvoerde dus 25.5 graden (het was hoog zomer). Deze output is niet zo mooi dus we gaan een Python script maken wat deze rauwe output in een mooier formaat weer kan geven. Overigens, als je wat wilt zien gebeuren kun je bijvoorbeeld op de sensor blazen en hem nogmaals uitlezen met cat.

De sensor uitlezen met een Python script

1 sensor

Eerst gaan we 1 sensor uitlezen, als je er 2 hebt aangesloten, scroll dan door naar "2 sensors".

Open een editor, het maakt niet veel uit op welke plaats maar doe maar in je home map waar je schrijf rechten hebt:
cd
(cd brengt je altijd naar je home map)
nano temp.py
Plak de onderstaande tekst in het bestand:

import glob
import time
import os
import datetime
## initialize the device -> Ik zet hier een # voor want dit heb je niet nodig, de modules hebben we al geladen.
#os.system("sudo modprobe w1-gpio")
#os.system("sudo modprobe w1-therm")
print "DS18B20 - op de RaspBerry Pi"
## find the device
devicedir = glob.glob("/sys/bus/w1/devices/*")
device = devicedir[0]+"/w1_slave"
## open up the file
f = open (device, 'r')
sensor = f.readlines()
f.close()
## parse the results from the file
crc=sensor[0].split()[-1]
temp=float(sensor[1].split()[-1].strip('t='))
temp_C=(temp/1000.000)
now = datetime.datetime.now()
dtime = datetime.time(now.hour, now.minute, now.second)
 ## output
if ('YES' in crc):
    print dtime,"\t",temp_C
else:
    print dtime,"\tCRC check failed."
    ## wait 5 seconds and repeat
Sla het bestand op en sluit nano (ctrl-x, Y, enter).
Geef het commando:
python temp.py
om het script te draaien, je ziet een nette lijst met temperatuur waarden opgebouwd worden. Hieronder herhalen we het truukje met 2 sensoren en daar weer onder gaan we deze waarden naar een file schrijven.

2 sensoren

Om 2 sensoren uit te lezen doe je het volgende:
Open een editor, het maakt niet veel uit op welke plaats maar doe maar weer in je home map waar je schrijf rechten hebt:
cd
(cd brengt je altijd naar je home map als je daar nog niet was)
nano temp2.py
Plak de onderstaande tekst in het bestand:
# -*- coding: utf-8 -*-
import glob
import time
import os
import datetime
## print "DS18B20 op de Raspberry Pi"
## find the device
devicedir = glob.glob("/sys/bus/w1/devices/*")
device = devicedir[0]+"/w1_slave"
device2 = devicedir[1]+"/w1_slave"
while True:
   ## open up the file
   f = open (device, 'r')
   sensor = f.readlines()
   f.close()
   ## parse the results from the file
   crc=sensor[0].split()[-1]
   temp=float(sensor[1].split()[-1].strip('t='))
   temp_C=(temp/1000.000)
   now = datetime.datetime.now()
   dtime = datetime.time(now.hour, now.minute, now.second)
   ## Rij toevoegen voor de tweede tempsensor
   f = open (device2, 'r')
   sensor = f.readlines()
   f.close()
   ## parse the results from the file
   crc=sensor[0].split()[-1]
   temp=float(sensor[1].split()[-1].strip('t='))
   temp_C2=(temp/1000.000)
   ## output
   if ('YES' in crc):
    print dtime,"\t",temp_C,temp_C2
   else:
       print dtime,"\tCRC check failed."
       ## wait 5 seconds and repeat
       time.sleep(5)
Sla het bestand op en sluit nano (ctrl-x, Y, enter).
Geef het commando:
python temp2.py
om het script te draaien. Je ziet wederom een mooi lijst opgebouwd worden.

Dit is leuk maar natuurlijk niet handig, uiteindelijk willen we graag grafieken plotten van het temperatuur verloop, daarvoor moeten we de waarden wegschrijven naar een file.

Temperatuurwaarden naar een file schrijven

Om de waarden op te slaan in een file gebruiken we het unix tooltje watch. We passen eerst het script aan zodat er geen "while loop" meer in zit en het maar 1 keer een output uitleest leesbaar maakt, het loop-en laten we straks aan watch over.

Open de editor:
nano tempwatch.py
Plak de onderstaande tekst in het bestand:

# -*- coding: utf-8 -*-
import glob
import time
import os
import datetime
## print "DS18B20 op de Raspberry Pi"
## find the device
devicedir = glob.glob("/sys/bus/w1/devices/28-*")
device = devicedir[0]+"/w1_slave"
device2 = devicedir[1]+"/w1_slave"
## open up the file
f = open (device, 'r')
sensor = f.readlines()
f.close()
## parse the results from the file
crc=sensor[0].split()[-1]
temp=float(sensor[1].split()[-1].strip('t='))
temp_C=(temp/1000.000)
now = datetime.datetime.now()
dtime = datetime.time(now.hour, now.minute, now.second)
## Rij toevoegen voor de tweede tempsensor
f = open (device2, 'r')
sensor = f.readlines()
f.close()
## parse the results from the file
crc=sensor[0].split()[-1]
temp=float(sensor[1].split()[-1].strip('t='))
temp_C2=(temp/1000.000)
## output
if ('YES' in crc):
        print dtime,"\t",temp_C,temp_C2
else:
        print dtime,"\tCRC check failed."
        ## wait 5 seconds and repeat
        time.sleep(5)
Sla het bestand op en sluit nano (ctrl-x, Y, enter).
Als we het script nu zouden draaien met:
python tempwatch.py
Dan zouden de sensoren 1 keer uitgelezen worden, waarna het script stopt. Met de unix tool "watch" kunnen we het script met een gespecificeerde regelmaat laten draaien en de output steeds onderaan de file toevoegen. Gebruik het volgende command om de temperatuur elke 2 seconden aan de file "tempoutput" toe te voegen:
watch -n 2 'python 2temp2.py >> tempoutput'
Als je de "2" in "60" zou veranderen zou de temperatuur elke minuut worden bijgeschreven. Heel leuk maar als je dit via ssh doet is het natuurlijk vervelend om een sessie open te moeten hebben. Gelukkig hebben we hier weer een mooi tooltje voor.

tmux

Tmux is een tool welke je in staat stelt een ssh sessie te verlaten terwijl de sessie wel gewoon doorloopt. Je kunt de sessie weer oppikken op een ander tijdstip, op een ander apparaat vanaf een ander ip-adres. Wij gaan tmux gebruiken om ons temperatuursensor-script door te laten draaien als we uitloggen.

Update eerste je repositories en installeer tmux:
sudo apt-get update
sudo apt-get install tmux
Nu kun je door simpelweg het commando
tmux
te geven een soort sessie in een ssh sessie starten. Deze sessie kun je afsluiten met de volgende toets combinatie:
ctrl-b, d
(dus ctrl en b samen indrukken, loslaten en d indrukken.)
Dit beëindigd de sessie. Je kunt nu uit ssh loggen, later weer inloggen en door te typen
tmux attach
open je de sessie weer. Wanneer je in de tmux sessie ons commando watch -n 2 'python 2temp2.py >> tempoutput geeft en de sessie uitlogt, zal dit script tot je het beëindigd waarden blijven toevoegen aan de file "tempoutput".

De methodes die ik hier beschrijf kunnen zeker efficiënter en eleganter maar ze geven een goed idee van wat mogelijk is en wat er precies gebeurd onder de motorkap. Als je betere of leukere oplossingen hebt, laat ze me dan weten middels de comments. Wat je bijvoorbeeld kan doen is deze hele tutorial uitvoeren in een map die beschikbaar is voor Nginx (de webserver die we eerder installeerden: Een webserver met PHP) zodat je in je browser de file "tempoutput" kunnen openen om hem zo direct Excel in te kopiëren bijvoorbeeld (let op dat je dan steeds sudo moet gebruiken omdat je geen schijfrechten hebt in de standaard map /usr/share/nginx/www/). Met Python kun je ook direct Excel bestanden maken en deze mailen. Je kunt ook zelf spelen met het exec commando in PHP om zo de gemeten waarden (of gegenereerde grafieken?) gelijk mooi in een website weer te geven. De mogelijkheden zijn zoals altijd weer eindeloos.