Raspberry Pi sous vide water bath
Temperature control for a sous vide water bath is a popular application for hobbyist microcontroller kits, with lots of well documented projects out there. My favourite is the Sous Vader – if only for the attention to detail in the decal on the box.
I’ve been planning my own for a little while, and got some DS18B20 temperature probes a little while ago. The long Easter weekend break finally brought me some time to progress the project.
Danger – High Voltage
I have an old slow cooker that’s perfectly good for doing pot roast. It’s been falling to bits for some time, and I’ve patched it up with a Sugru sample I got at Monkigras. I had thoughts of hacking it directly (and perhaps even building in a Raspberry Pi), but common sense took hold and I decided on a route that didn’t involve directly manipulating mains electricity.
To turn the slow cooker on and off I got hold of a radio controlled mains socket from Maplin – they’re available without the controller (which I didn’t need) for £7.99.
I found a library to control the remote socket on github – Raspberry Strogonanoff (thanks Duncan McGregor, and a clever choice of project name). This uses a Sparkfun 434MHz RF Link Transmitter (which as suggested by Duncan I got from Protopic).
Getting Raspberry Strogonanoff working was the easier part of the whole set up. Having looked at the socket to establish that it was set to channel 4 button 1 I simply ran this line to turn it on:
sudo ./strogonanoff_sender.py --channel 4 --button 1 --gpio 0 on
and this to turn it off again:
sudo ./strogonanoff_sender.py --channel 4 --button 1 --gpio 0 off
A water bath is a good example of a control system. The water and pot collectively have quite a high specific heat capacity, and there’s quite a bit of latency between turning off power and the rise in temperature stopping. The standard way of dealing with this is to use a PID Controller (see this explanation for a BBQ application for something more straightforward than the Wikipedia article). The Sous Vader seems to have worked with just a PI controller (effectively D=0), so I tried that first. There is a python implementation of a PID controller, which I didn’t spend the time to integrate.
Tuning the control loop
This is the tricky and time consuming part. In theory there should be a nice library out there that figures out correct settings for P, I and D based on observed data, but in practice it seems that most people resort to manual tuning.
I started out with things on a breadboard using my usual home made Pi Cobbler, but as I want to use this in the kitchen I’ve created a more permanent setup using a Ciseco Slice of Pi, which at £3.90 is a very inexpensive small project board. I used one of the header strips in the Slice of Pi kit as a place to plug in the 434MHz transceiver and the temperature probes (so it would be easy to use parts in other projects). It was then simply a case of soldering some connecting wires to the appropriate power (5v for the transceiver and 3.3v for the DS18B20), GPIO (0 for the transceiver and 7 for the DS18B20) and GND:
The system pictured above has an Edimax WiFi dongle so that I can control and monitor the whole thing when it’s in the kitchen.
Update 14 Apr 2013 – the code (slightly improved over what’s below) is now available on GitHub along with (hopefully comprehensive) installation instructions.
It’s not especially pretty, but seems to be doing the job:
import os from subprocess import Popen, PIPE, call from optparse import OptionParser from time import sleep def tempdata(): # Replace 28-000003ae0350 with the address of your DS18B20 pipe = Popen(["cat","/sys/bus/w1/devices/w1_bus_master1/28-000003ea0350/w1_slave"], stdout=PIPE) result = pipe.communicate() result_list = result.split("=") temp_mC = int(result_list[-1]) # temp in milliCelcius return temp_mC def setup_1wire(): os.system("sudo modprobe w1-gpio && sudo modprobe w1-therm") def turn_on(): os.system("sudo ./strogonanoff_sender.py --channel 4 --button 1 --gpio 0 on") def turn_off(): os.system("sudo ./strogonanoff_sender.py --channel 4 --button 1 --gpio 0 off") #Get command line options parser = OptionParser() parser.add_option("-t", "--target", type = int, default = 55) parser.add_option("-p", "--prop", type = int, default = 8) parser.add_option("-i", "--integral", type = int, default = 2) (options, args) = parser.parse_args() target = options.target * 1000 print ('Target temp is %d' % (options.target)) P = options.prop I = options.integral # Initialise some variables for the control loop interror = 0 pwr_cnt=1 pwr_tot=0 # Setup 1Wire for DS18B20 setup_1wire() # Turn on for initial ramp up state="on" turn_on() temperature=tempdata() print("Initial temperature ramp up") while (target - temperature > 3000): sleep(15) temperature=tempdata() print(temperature) print("Entering control loop") while True: temperature=tempdata() print(temperature) error = target - temperature interror = interror + error power = ((P * error) + ((I * interror)/100))/100 print power if (power > 0): pwr_tot = pwr_tot + power pwr_ave = pwr_tot / pwr_cnt pwr_cnt = pwr_cnt + 1 print pwr_ave # Long duration pulse width modulation for x in range (1, 100): if (power > x): if (state=="off"): state="on" print("On") turn_on() else: if (state=="on"): state="off" print("Off") turn_off() sleep(1)
I’ve not had the chance to use the water bath for cooking yet, but I’m very much looking forward to trying out a few steaks and maybe some Sunday roasts. I’ll report back on the results.
Filed under: code, making, Raspberry Pi | 24 Comments
Tags: 434MHz, control system, DS18B20, mains, PI, PID, python, Raspberry Pi, remote control, RPi, Sous vide, water bath