I was looking for some time for a good reason to buy a Raspberry Pi. Unfortunately I already have a nice nettop box that is doing its job very well as a media player with XBMC (soon Kodi) plus a few services (irc bot, file sharing, …) Ok, it is not as silent and more power greedy than I’d wish, but I can’t just throw it away…
But I finally found the good reason I was looking for!
I want to log the temperature of a house several times a day during several weeks. The house has power but no internet access. Ideally, it would be able to log the temperature inside and outside the house. I’ve looked for a ready to use tool that could do the job at a low cost, but haven’t found anything really convincing.
This is the kind of task the Raspberry Pi can do very easily, with the help of a DS18B20 sensor.
So I bought:
I already had:
Total cost: less than 40€.
Here is how it looks:
Not a peace of art, but it should do the job!
I’ve soldered the pull up resistor on the IDE cable between the pin 1 and 7, and the pin 1, 2 and 3 of the DS18B20 on the pin 9, 7 and 1 of the GPIO respectively.
The temperatures are read through the
sysfs interface, that requires to load
two extra modules in the kernel. To do that, I’ve added these two lines in the
A python script run by cron every ten minutes reads the temperature from the sensors and writes the output to a file:
#!/usr/bin/env python import glob, os from datetime import datetime out = open("temp.csv", "a") date = str(datetime.now()) ds = glob.glob('/sys/bus/w1/devices/28-*/w1_slave') for d in ds: name = d.split("/")[-2] temp = str(float(open(d).read().split()[-1][2:])/1000) print >> out, ";".join([date, name, temp]) out.close()
The date is the same for all the sensors, to make easier to compare the temperatures. When doing fast acquisition or using many sensors, it may be a better idea to get the real date for each sensor, as each sensor take a second or so to read.
The crontab entry is:
*/10 * * * * /home/pi/temp.py
Here are a few lines from the generated
2014-12-21 16:20:01.575703;28-001450767aff;21.875 2014-12-21 16:30:02.006573;28-001450767aff;21.625 2014-12-21 16:40:02.116337;28-001450767aff;22.125
There is a single sensor for now – I’m still waiting for the waterproof sensor. And here is a chart with the data on a few hours:
The data is in CSV format, so it can be easily imported everywhere. I’ve used R:
data <- read.table("temp.csv", sep=";", col.names=c("date", "sensor", "temperature")) data$date <- as.POSIXct(as.character(data$date)) plot(temperature ~ date, data)
Without a screen, keyboard, or any kind of connection, it is not possible to shutdown the Raspberry Pi properly. Fortunately it has many input on the GPIO that can be used just for that. I’ve soldered a switch between the pin 39 (GPIO21) and the pin 40 (ground).
A python script launched by
/etc/rc.local just waits for the input to change, and
then initiates the clean system shutdown.
#!/usr/bin/env python import RPi.GPIO as GPIO import os GPIO.setmode(GPIO.BCM) GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.wait_for_edge(21, GPIO.BOTH) os.system("logger 'power button pressed'") os.system("halt")
Note that it wasn’t possible to use the pin number with the RPi.GPIO module installed by default on my raspbian. It failed with the error:
ValueError: The channel sent is invalid on a Raspberry Pi
I had to run
setmode(BCM) instead of
avoid that problem, and use the GPIO number instead of the pin number:
The switch, once pushed, connects the GPIO21 to the ground, so the GPIO21
has to be configured with a pull up resistor. When reading the value with
input(21), the value returned is
1 when the switch is not pressed and
when it is pressed. This may seem a bit counter intuitive, but only describe
the current state on the GPIO21:
1 for the 3.3V from the pull up resistor,
0 for the 0V from the ground.
Instead of reading the value from time to time and triggering the shutdown when
the value is
0, the script just use
wait_for_edge(21, BOTH), that detects when the
value change on the pin and exits when it happens.
A message is sent to
syslog with the
logger command to keep a track that the
button was pressed.
The line in the file
/etc/rc.local is just:
& is mandatory to let the process run in the background.
I already knew the Raspberry A+ has no network interface. This is fine for this application, because the house has no internet connection.
This is not convenient for the setup though, where everything must be done with the screen and the keyboard, or transfered to the SD card before booting the Raspberry Pi.
Another problem I overlooked is the lack of battery for the clock. This mean the Raspberry Pi can’t keep its clock running when it is not powered. The Raspbian deals with that by keeping the date unchanged since the last time it went down. With the network, the date and time are updated with NTP. Without network, the only way to update the date is to use a command like:
sudo date -s "december 21 2014 17:29"
Obviously, the only (easy) way to run that is with a screen and a keyboard, and I won’t have any when I’ll plug the Raspberry Pi in that house.
Again, a network interface would have helped, as I could have used my laptop to set the date through SSH.
I could buy a USB WIFI adapter, but the total cost would then be quite close to the price of the Raspberry B+, and WIFI is a lot more painful to configure than a simple ethernet connection.
I guess I’ll just have to set the approximate date at which it will boot before unplugging it.
A power failure will also shift the time recorded with the temperature. I’m not sure how important it can be, but to be sure to know when a power failure occur, I’ve added a command that renames the temperature file when the Raspberry reboots:
mv temp.csv temp.csv.`date +%Y-%m-%dT%H.%M.%S`
This is run by cron with the special string
So a Raspberry A+ is fine for the application itself, but the network interface would have helped quite a lot to configure everything and experiment with the temperature logging. I think I’ll buy a B+ for my next project!
Now I wait for the weatherproof sensor to arrive. In the mean time, I let the logger accumulate some real temperatures that I can use to try to extract some interesting informations.