Arduino Sous Vide Machine: Part 1

Note: For an updated version with simpler code and important information about hardware issues see this new post: Arduino Sous Vide, Version 2

Heavily inspired by an old blog post by the brilliant Seattle Food Geek, I set out to build an arduino powered sous vide / thermal immersion circulator machine.  Instead of a PID controller, it uses an arduino with a relay + waterproof thermistor. A little less sexy, but just as effective with the added bonus of being modular with reusable parts.


  1. Sterilite® Ultra Latch 17 L container $4
    • Made of polyproplyene, softens at ~155°C according to the Merck index, melts at 165°C; perfect for our application of temps < 100°C.
    • Avoid long term exposure to UV light as paranoid precaution against degradation
    • You can simply use a big pot instead of the plastic container. I Outlet boxhave an enamelled cast iron pot that is excellent for maintaining a steady temperature.
  2. Arduino (I’m using UNO rev3) $35
  3. Waterproof temperature sensor / thermistor (DS18b20 ) $2.03

    • This thermistor is waterproof but not rated for full immersion
    • I sealed mine in a small bit of plastic with the vacuum sealer. problem solved
    • See previous post for how to calibrate
  4. Immersion heater (2x) $13
  5. 3 prong power cable free if sacrificed, otherwise $6+
  6. 5V 1 channel relay  $1.36
    • This relay is really cheap and was starting to fall apart on me; I substituted it with another one I had laying around. YMMV
  7. Aquarium water pump 80GPH $6.88
  8. Ziploc V150 vacuum sealer system $30 (on clearance at Target)
  9. GFCI outlet $12.30
  10. Outlet faceplate $1 (optional)
  11. Outlet box $0.50 (link is to pack of 100, cheaper to buy in store)
  12. Wire coat hanger / safety wire
  13. Large binder clips (2x) $0.50
  14. Male to female (3x) and male to male jumper wires (the more the merrier) $2.00
  15. A 4.7 k Ω resistor for thermistor $0.05

Grand Total:  $114.62 if you buy everything. You can add an extra heater or two if desired. I found that two alone work pretty well. My units have been calculated to heat at about 0.01 C per second, taking an hour to get up to an average cooking temp of 65C from room temperature water.

norpro temperature graph

Step 1: Building the relay

The first step is building a functioning relay. The beauty of this sous vide machine is that it is comprised of parts that can be cannibalized and put to other uses when you’re not sous vide cooking. The relay is especially cool as it allows you to control high voltage devices from the measly 5V microcontroller of the arduino. The options from here are limited only by your creativity and/or depravity. (Lots of options of pairing it with motion!)

I followed a Sparkfun tutorial on how to build a Controllable Power Outlet. Quite frankly, there is no need to rehash something that is described better there. Check it out.

Here’s a diagram for the relay listed  in the parts list. You can figure it all out from this picture alone.

relay wiring

Step 2: Testing Relay

Controlling a relay with pyfirmata

Controlling the relay is incredibly easy with pyfirmata. It’s as simple as turning a pin on and off to open and close the relay. If you know how to switch a LED on, you can control a relay.

Here’s some example code to function test it.

import pyfirmata

port = '/dev/ttyACM0'

board = pyfirmata.Arduino(port)

it = pyfirmata.util.Iterator(board)

pin4 = board.get_pin('d:4:o')

while True:
	ui = raw_input("Enter 'on' or 'off': ")
	if ui == 'on':
	elif ui == 'off':

Plug your relay into the arduino, plug your arduino into a PC and test it out by plugging in your relay controlled power outlet and lamp into the outlet.

That’s all there is to it. It’s only a small leap from here to put some devices online that you can control remotely. (Check out X10 for anything beyond a few devices).


Building a feedback loop with a thermistor and using thermostat-like hysteresis curves for controlling the immersion heaters.

Thermistor + pyfirmata

Want to know how to use a thermistor with your arduino via pyfirmata? Look no further…

I’ve been playing with thermistors as part of a home monitoring system I’ve been building and for an upcoming sous vide project. Thermistors are cheap and can be highly accurate for a pretty wide range of temperatures. I’m using an epoxy coated and waterproofed thermistor for my sous vide project.

The Setup

You need:

  • an arduino
  • a thermistor
  • a resistor that matches your thermistor (ie: 10k ohm resistor with 10 k ohm thermistor)
  • a breadboard with jumper wires

pyfirmata thermistor

The Code

Code available for download

### JS Kouri 2/1/2014, no rights reserved
### In this example, I am using a 4.7 kΩ resistor 
### (Digi-Key Part Number NTCLE400E3472H)
### Values for Steinhart-Hart equation calculated 
### at from datasheet info

import pyfirmata
from math import log
from time import sleep

n = 0							#first port number to try ie: ttyACM0
PORT = '/dev/ttyACM' + str(n)    			# device location, yours may very. if unable to connect, try /dev/USB or check dmesg
connected = False 

def connection():
  global board
  board = pyfirmata.Arduino(PORT)
  print 'Port found, connecting...'
  it = pyfirmata.util.Iterator(board) # start iterator thread

while connected == False:
    print 'Trying' + PORT
    connected = True
    print "Connection established"
    n = n+1
    PORT = '/dev/ttyACM' + str(n)

pin0 = board.get_pin('a:0:i')				# edit to reflect your setup
print 'Waiting on reading...'
while is None:				# ignore input until pin is active

while True:

  analog_value =
  #print analog_value 					# optional debug info

  analog_value = analog_value * 5			# we multiply by 5 (volts) to get the true voltage read at pin (ie: we get 3 v instead of 0.6. pyfirmata reports analog values in the range of 0 to 1. 
  analog_value = 4700.0 * ((5.0/analog_value) -1.0) 	# solve for resistance at thermistor. change 4700 to match your resistor used.

  #print str(analog_value) + ' this is calculated resistance in ohms at thermistor' # optional debug info

  temp = (1 / (0.001308463361 + 0.0002344771590 * log(analog_value) + 0.0000001041772095 * log(analog_value)**3)) # substitute your thermistor's unique values for A, B, C. 

  print str(temp) + ' kelvin'

  t_celsius = temp - 273.15
  print str(temp) + ' degrees celsius'

  t_fahrenheit = 9/5.0*temp + 32
  print str(t_fahrenheit) + ' degrees fahrenheit\n\n'  

  sleep(30) 						# wait 30 seconds between polling pin

The Explanation

The code features a few important aspects that understanding will be helpful.

Converting Pyfirmata Analog Values to Voltage

Pyfirmata reports analog values as a float of 0 to 1. We need to determine what the voltage is at the analog pin. We’re using 5 VDC so we multiply it by 5.  This will provide Va for the next portion.

The Voltage Divider

A neat little explanation of why we use voltage divider circuits with thermistors and other sensors can be found here. No need to rehash it.

In order to obtain the resistance of the thermistor, we need to calculate it based off the voltage readings from the analog pin. (Which we just adjusted). We use an equation derived from Ohm’s Law that lets us calculate the resistance in a voltage divider.

RT = R  [1 / (V / VA – 1) ]

Where RT = thermistor resistance in ohms, R = resistor resistance, V = input voltage, VA = voltage reading from analog pin (Read more at Wikipedia Voltage Divider)

 Armed with the resistance at the thermistor, we can finally calculate the temperature.

Steinhart-Hart Equation

There are  a couple ways of calculating this, I chose the Steinhart-Hart equation, but you can also use the simpler β equation. (See Wikipedia)

Where R = thermistor resistance. (Written as RT in last section)

It is very important to have your datasheet in order to accurately calculate the values needed for this equation. If you don’t have the datasheet, you can determine your own values by obtaining resistance in ohms at three known temperatures.

my thermistor’s data sheet and the values I used in the calculator


Once you get your  resistance values for three known temperatures from your datasheet or experimental data, plug them into a Steinhart-Hart calculator and build your equation.

Replace my values in the code above with yours. Be sure to format the coefficients properly. The calculator I linked to above gives coefficients in scientific notation. Convert scientific notation to the long form decimal notation. (n-1 preceding decimal places for E to the n power)

Now run it and get your temperature!

 Sky’s The Limit

And there you have it. From here you can easily save your values in a text file or a database, build cool charts with matplotlib (if you don’t pull your hair out first trying to get it to work), or do something more dynamic like create feedback loops and control things based on temperature.

Relief for your eyes via Redshift and Twilight

I spend an inordinate amount of time staring at a screen throughout the day. Whether it’s against my will at work, or for fun at home. I hate bright lights and nothing is worse than looking at an application in a monitor with a white background or that is offensively bright. Enter Redshift and Twilight.

These programs have been designed to slowly fade the brightness of your screen to mimic the natural brightness outside. As the screen dims, it also becomes more red in color, which studies have shown to be less detrimental and disruptive to your body’s circadian rhythm and secretion of melatonin. Although my abnormal sleep schedule prevents me from speaking as to these applications’ sleep benefits, I can say that they have reduced my eye strain and incidence of headaches. It is much more pleasant to view my computer and smartphone screens at night or in a darkened environment. If you are bothered by bright screens and want an automatic fix that is a step above manually adjusting the brightness, give these apps a try. I no longer use a computer without installing these first if I can help it.

The setup for Twilight is simple and self explanatory, the setup for Redshift takes a little more work. Here’s how to configure it for your location and to get it to run at startup:

Obtain local GPS coordinates

Google "GPS coordinates of _your city_" or navigate to google maps and type in your address. Right click on map next to location, click "What's here", and get GPS coordinates from updated search bar above. ie: 36.111807,-115.16919


Create and test redshift command

$ redshift -l [your gps coordinates ie: 36.111807:-115.16919] -v


Add to cron

$ crontab -e


Execute redshift command after every reboot

@reboot [your redshift command from above]

If Redshift doesn’t work

FYI: If it is early in the day, your screen may not get much dimmer/redder

Check your GPS coordinates for proper formatting, should be:


Try running in different video modes by appending the following to your redshift command:

-m vidmode or -m randr

Otherwise, it’s off to the man page for you. Good luck

Where to download

Twilight app for Android

Redshift for Linux and Windows

Dropbox + Motion on the Raspberry Pi

Raspbian, the recommended default operating system of the Raspberry Pi, does not come with a native Dropbox package. The hacks I saw online were all pretty sloppy, with many showing how to bounce files from your raspberry pi to another device like a desktop PC that has dropbox installed, then using that PC to sync files. I wanted Dropbox synchronization for only a single folder, and for one purpose: to collect the photos my webcam takes when using the motion software.

(Motion is a pretty cool program that can give advanced motion sensing capabilities to a number of webcams, and live stream your webcam and/or automatically record video or take pictures when motion is detected. See:

I decided to use Dropbox’s Python API to create a script that could save my security footage. I had a number of uninvited painters scheduled to come to my apartment while I was away at work and needed something that would save to a remote location. The code that follows is tailored to the motion program. Since motion can automatically execute a program or script upon writing a file (ie: saving a photo or video triggered by motion), I decided to take advantage of this and upload each file individually as opposed to running an additional script that continually monitors the filesystem for changes.

(Will make that later… check back in a week or two). Update: more important things have cropped up like building a sous vide machine!

How to do it:


  • You have a dropbox account
  • You have python and motion installed
Step 1: Download droppi script files

Accessible here

Step 2: Install Dropbox SDK Python module & create new dropbox app

Install the module:

sudo pip install dropbox

Create new app:


Create App > Dropbox API app > Files & Datastores > Yes

Name your new app whatever you like.

Step 3: Copy down newly created app key and app secret

Paste your app key and app secret into the “keys” file downloaded in There should be one key per line with app key on the first line. ie:


Step 4: Run to allow dropbox API access so we can upload to dropbox


Follow the directions in the console, you will need to click the link to allow API access. You’ll also need to paste the code received into console. This will be the last key you will need to use the script. The rest of the keys and tokens are generated automatically for you and will be inserted into the “keys” file.

You can tell if it worked by checking your dropbox account. Do you see a new folder that bears the name of your app (may be located in a new “App” folder)? Is there a “test.txt” inside of it? If so, you’re all set for step 5.

Step 5: Configure Motion

Open the motion configuration file found at /etc/motion/motion.conf (always a good idea to make a copy). If you don’t have a configuration file, I used this sample one.

Disable video

I disabled video recording on mine because the dropbox account I’m using for motion is a new account with only about 2 gb of space in it. I disabled video recording by changing



ffmpeg_cap_new off

Set working directory

Choose the directory on your local machine where you would like to save your pictures and/or videos. /tmp is a good option if you don’t want long term storage. Make sure your directory is writeable by user motion.

target_dir /tmp

Add droppi upload

If you are saving images, modify the following the following (use absolute path for the file, ie: /home/pi/, and be sure to remove the semicolon at the front of the line)

on_picture_save python %f

If you are saving videos:

on_movie_end value

Step 6: Enjoy your dropbox enabled surveillance system!

Save the motion.conf file, start or restart the motion daemon

sudo service motion restart

Dance in front of your camera and check your dropbox!

Coming soon: Real time Dropbox folder syncing for Raspberry Pi

This motion dropbox script was a quick proof of concept hack and was made overnight because I needed it to keep an eye on these seedy painters that were coming into my apartment while I was out all day.

Hello painters!

 05-20140109084638-00 05-20140109084641-00(1) 05-20140109084503-00 05-20140109084259-00

What’s next

A python program that continually monitors a directory for changes should not be much more difficult to create. Stay tuned…

Overengineered Morse Code with the Arduino

As a first foray into python, arduino, and pyfirmata (after lighting a single LED), I wrote this small python script for converting text into morse code. I first ran it with a single LED on a breadboard, but it was much more fun to throw in a piezo buzzer and get the unmistakeable morse beeps.

See the code and schematics below. As someone with less than a month of on and off again python study, don’t expect anything too ‘pythonic’ and pretty. It works though!

Script requires the pyfirmata module. Be sure to adjust the pin number and port/device location of the arduino in the script.

### Arduino / Raspi Morse Code Generator
### Enter a word, and get morse code translation in console output & LED lights / beeps

import pyfirmata

morse = {'a':['.','-'],
	 ' ':' '}

port = '/dev/ttyACM0'
board = pyfirmata.Arduino(port)

pin = 7 

def program():

  delay = 0.15						# Length of time LED between inter elemental lighting
  delay_factor = 1					# Speed up or slow down entire program by set percentage Default: 1
  delay_intraletter = delay * delay_factor * 3		# Length of time between letters 
  delay_interword = delay * delay_factor * 7		# Length of time between words
  delay_dit = delay * delay_factor			# Length of illumination for dot/dit
  delay_dah = delay_intraletter	 

  user_list = [] 									# blank list
  user_input = raw_input("Enter your word to convert to morse code: ").lower()		# Take user input, convert to lowercase
  for x in user_input:
  print user_list
  print '\n Creating morse message now...'
  user_list = ''.join(user_list)
 # print 'DEBUG: joined user list'
 # print user_list
  for l in user_list:
    if l == '.':
      print 'TRANSMITTING: .'
    elif l == '-':
      print 'TRANSMITTING: -'
    elif l == ' ':
      print 'NEW WORD'	


The circuit is even simpler than the script. It amounts to nothing more than a piezo buzzer (unsure of the specs of mine), LED, and resistor in series.

Easy enough, right?
Easy enough, right?

So what had originally sprung up as an idea to play around with the pyfirmata syntax turned into a drive to learn morse code, which quickly faded into disinterest by the time I had finished transcoding the alphabet. I have since made an updated version that includes numbers and communicates between two computers on a network via the python SOCKS module. I was considering adding a reverse translator as well that translates user input (via pushbutton) morse into letters. I think I have a few other projects in mind that will be of more immediate practical use.

Download the latest source files for this project here

Morse key adopted from

Quick and Easy Wireless File Sharing With the Raspberry Pi in Linux

Fed up with the commandline and just want to drag and drop some files on to your network connected raspberry pi? Look no further than the oft-forgotten FISH protocol.

No, not that kind of fish

Fish is a simple and easy to use SSH file transfer protocol that can be used in Dolphin and Konqueror file managers/browsers. It allows you to share files between computers (including raspberry pi, woohoo) securely through SSH, all from the convenience of your GUI file manager.

To use it, simply open Dolphin or Konqueror, and type in the address bar:

fish://[raspberry pi username]@[local ip address]
ie: fish://pi@

Assuming you have all the basic dependencies like openssh, you should get a prompt that has you input the raspberry pi user password. Once entered, you’ll be on your way to easily swapping files without having to resort to running ftp servers, using scp, rsync or moving things manually to the SD card.


Obviously, this feature isn’t limited to just the raspberry pi. You can use it for transfers between other SSH accessible computers as well.

meandering adventures in the world of science and technology