Monday, January 20, 2014

Raspberry Pi Temperature data recorder - Part I: Hardware

The Raspberry Pi seems ideal for all kinds of "physical computing" applications, as it is small, cheap, low-powered and yet more powerful and feature rich than a traditional micro-controller.

One way to showcase such applications in an educational context could be to control science experiments which require long term measurements and data collection.

One of the easiest measurement sensors to connect to a Raspberry Pi is the DS18B20 digital thermometer,. It can be read out via a multi-device 1-wire bus that is directly supported by a driver in the Linux kernel. Several sensors can be connected in parallel to the same data-wire and read out individually over the bus interface by their hard-coded IDs. All we need to connect one or more DS18B20 sensors to a Raspberry Pi, is to connect the VCC pin to 3.3V, GND to GND and data to GPIO4 on the Raspberry Pi GPIO header as well as connect a 4.7k Ohm resistor between the VCC and data lines of the sensor. The sensor is available among others as a basic board mounted package as well as a water-proof assembly with a ca. 1m long isolated cable.

The whole setup can be assembled without any soldering, using some prototyping tools from Adafruit Industries, a great supplier of electronics parts for hacking, making and education, based in NYC but who also ships world-wide.

In addition to the Raspberry Pi with CF card, micro-usb cellphone charger and EW-7811Um USB wifi adapter (see configuration here), the shopping list for this project includes:
This great tutorial explains in much detail how to connect both types of DS18B20 sensors using the breadboard & breakout connector. The ribbon cable on fits one-way into the breakout connector due to the notch on one side, but should be mounted to the Raspberry Pi with the cable pointing away as in the picture above and with the different colored wire towards the edge where the CF card slot and micro-USB power connectors are.

For the experiment, we want to connect at least 3 temperature sensors to simultaneously monitor:
  • inside/room temperature (board mounted sensor)
  • outside temperature
  • heater temperature
Using the data collected for inside & outside temperature and a lot of simplifying assumptions, we could for example estimate the amount of thermal flow out of the room and thus how much heating energy the room has used during the measurement period. Or try to reverse-engineer the control function of the heater thermostat by looking at the relationship of outside, inside and heater feed temperature.

Our house is a roughly 120 year old apartment building with a radiator based central heating system. There are exposed riser pipes which distribute the hot water from the boiler in the basement to the radiators and the apartments above us. This is the place where we can connect the heater temperature sensor, as it will show the feed temperature, regardless of whether the radiator in the room is turned on or off. Tin-foil can make a great heat-conducting sleeve to connect the sensor to the tube. The outside sensor is simply stuck outside the window with the cable pinched by the window frame in less than professional manner...

Once we have carefully assembled all the parts, powered up the Raspbery Pi and made sure that none of the sensors are starting to overhead from wrong polarity, we can test if the driver is working properly:
pi@my-pi ~ $ sudo modprobe w1-gpio
pi@my-pi ~ $ sudo modprobe w1-therm
pi@my-pi ~ $ cd /sys/bus/w1/devices
pi@my-pi /sys/bus/w1/devices $ ls
28-000005303678  28-000005604c61  28-000005610c53  w1_bus_master1
pi@my-pi /sys/bus/w1/devices $ cat 28-*/w1_slave
79 01 4b 46 7f ff 07 10 0a : crc=0a YES
79 01 4b 46 7f ff 07 10 0a t=23562
83 00 4b 46 7f ff 0d 10 5b : crc=5b YES
83 00 4b 46 7f ff 0d 10 5b t=8187
5c 02 4b 46 7f ff 04 10 e6 : crc=e6 YES
5c 02 4b 46 7f ff 04 10 e6 t=37750


In order to make sure that the drivers for the GPIO 1wire interface and the DS18B20 protocol are loaded at boot-time going forward, we need to add them to /etc/modules:
sudo echo w1-gpio >> /etc/modules
sudo echo w1-therm >> /etc/modules

Then we create the following simple driver class in temp_sensor.py that is going to be used to read and record the sensor data in the second part of this tutorial:
#!/usr/bin/python

import re

class TempSensor():
    """
    Read data from DS18B20 Temperature sensor via 1-wire interface.
    """
    _DRIVER = "/sys/bus/w1/devices/%s/w1_slave"
    _TEMP_PATTERN = re.compile("t=(\d+)")

    def __init__(self, sensor_id):
        self._id = sensor_id

    def _read_data(self):
        data_file = open(self._DRIVER % (self._id, ), "r")
        try:
            return data_file.read()
        finally:
            data_file.close()

    def get_temperature(self):
        data = self._read_data()
        # data should contain 2 lines of text like this:
        # 86 01 4b 46 7f ff 0a 10 5e : crc=5e YES
        # 86 01 4b 46 7f ff 0a 10 5e t=24375
        #
        # Temperature reading is value of t= in milli-degrees C
        m = self._TEMP_PATTERN.search(data)
        if not m:
            raise IOError("Invalid data for sensor " + self._id)
        return float(m.group(1)) / 1000.0

if __name__ == '__main__':
    import sys
    for sensor_id in sys.argv[1:]:
        sensor = TempSensor(sensor_id)
        print sensor.get_temperature()

In order to test the driver, we can also execute it directly:
pi@my-pi $ ./python/temp_sensor.py 28-000005303678 28-000005604c61 28-000005610c53
23.562
7.812
39.562
Here we can also identify which ID corresponds to which sensor in our setup. Since it is winter right now, we can assume that 23.5C is the inside temperature, 7.8C the outside and 39.5C is the temperature of the heating pipe. If testing first on a workbench, we can also touch one of the sensors and see which one of the sensor readings is going up towards 37C as a consequence.

Right now, we can simultaneously measure the current temperature in each of the 3 zones, but in the next part, we are going to record time-series based measurements into a database for graphing and further analysis.

Part II: Data Collection ->