Digital brew thermometer project:
While there are lots of great analog thermometers available, digital thermometer choices are much more limited.
I looked at all of the digital thermometers I could find and found that the ones I liked I couldn't afford and the ones I could afford I didn't like ( this happens to me so often I should translate it into Latin and use it for my family motto! perhaps: "Non Affordom Primo, Nil Desirus Crapola" )
What I want in a digital thermometer is pretty basic, accurate readings and an easy to read display.
A year or so ago I started playing around with Micro computers. There are several popular ones out there, 3 of the most popular are the "Raspberry Pi", the "Arduino" and the "Beaglebone/Beaglebone Black". All are fairly inexpensive and all have a large fan base and tons of documentation.
Looking at the cost of available thermometer hardware I determined that it should be possible to build a customizable digital thermometer with multiple inputs/probes using one of these micro computers for around $50.00 or less depending on how much of the hardware needed you already have. ( Note: you MUST have a spare laptop/desktop computer to make this project work, when not using the digital thermometer the computer can be used for other purposes. The laptop I'm using for my setup is an elderly Dell Inspiron 6000 with a Centrino processor running the Xubuntu Linux OS, I'm sure it's possible to run this from a Windows or Mac system if that's what you have, however I don't have the particulars on how to do it. )
The 2 key words in the previous statements are "customizable" and "multiple", by customizable I mean that, depending on your programming skill, you could write in extras such as temperature limits and alarms, tie ins to relays to control the heating elements, data logging to graphs and other uses I haven't even thought of yet. By multiple I mean the number of probes you can add are up to you, in my case I wanted to set up a 3 probe system for AG brewing to monitor HLT, MLT and BK temps from a central location.
As an added bonus, the display on my setup is VERY easy to read, each character is about an inch tall and I've set it up with red letters on a black background, this is easily changeble in the code if you'd like a different combination.
Of the micro computers listed I decided to go with the Arduino ( ar-dwee-no ) as it is generally considered the more robust platform.
Before you consider trying this project be aware that you need average or above computer skills and are comfortable installing software, installing hardware and are familiar with programming concepts. In particular you need to be familiar with the Linux operating system, if you don't fell comfortable with all of this then you might want to refer this to one of your more nerdy friends!
Also be aware that this project will take at least a couple of hours to complete. If you like playing around with computers and possibly learning new stuff then it'll be fun, otherwise you might want to give it a skip.
Hardware:
What's needed depends on how you want to use the setup but the basic equipment is...
A laptop/desktop computer running Linux as mentioned before.
The Arduino - SainSmart UNO R3 ATmega328P Development Board + USB Cable ( $16.80, free shipping w/ $35 total purchase. )
http://www.amazon.com/gp/product/B00E5WJSHK/?tag=skimlinks_replacement-20
Solderless BreadBoard, 400 tie-points, 4 power rails, 3.3 x 2.1 x 0.3 in ($5.95, free shipping w/ $35 total purchase )
http://www.amazon.com/gp/product/B005GYAIES/?tag=skimlinks_replacement-20
Vktech 5pcs DS18b20 Waterproof Temperature Sensors Temperature Transmitter ( $7.80 at Amazon with free shipping from China )
http://www.amazon.com/gp/product/B00CHEZ250/?tag=skimlinks_replacement-20
( This is a 5 pack, singles are like $4.00 each, might as well get 5 in case there are any duds. Order these first as it takes a few weeks to get them. Note: these particular probes are 39" long but there are longer probes available, for example the 9' long model is $16.79 for 5, I'm hoping the 39" ones will work on the brew stand I'm building. )
4.7K pull up resistor ( 1 ) ( these should be available at Radio Shack for like 50 cents, I bought a variety pack of resistors from Amazon for $9.99 that has 400 resistors in 16 different sizes that I will be using for other projects. The variety pack is overkill for this application but here's a link to the one I bought. )
http://www.amazon.com/gp/product/B00E9Z0OCG/?tag=skimlinks_replacement-20
You need 3 male/male breadboard jumper wires, I'm sure these are available at Radio Shack for probably 50 cents each, or multi-packs are available at Amazon, here's one with 100 jumpers...
Wosang Solderless Flexible Breadboard Jumper Wires M/M 100pcs ( $6.00, free shipping w/ $35 total purchase )
http://www.amazon.com/dp/B005TZJ0AM/?tag=skimlinks_replacement-20
Hardware setup:
On the breadboard connect the 4.7K pull-up resistor between data and power. To do this, bend the resistor leads into a "staple" shape that spans the breadboard points you wish to use ( in my setup I selected row 13 for data, row 15 for power and row 17 for ground, see photo, by skipping a row between each one I allow myself a little more working room ), clip the leads to approximately 1/4" long, insert the resistor into the mounting points.
I have been told that there are different wiring versions of the probes, such as...
Red: 5Vdc, Black: Ground, White: Data
Red: 5Vdc, Yellow: Ground, Green: Data
mine was...
Red: 5Vdc, Black: Ground, Yellow: Data
If you get yet another configuration you might have to experiment to determine which is which.
Connect M/M jumpers from the 5V connector on the Arduino to the breadboard point you've selected for power, data pin 2 on the Arduino to your breadboard data point and Arduino ground to your breadboard ground point .
Connect each probe's power, data and ground wire to the corresponding breadboard point. Note: You may have to trim away some insulation to expose enough wire to get a good insertion in the breadboard, I trimmed the insulation back on mine and then, using a soldering iron, applied a little solder to the exposed wires to thicken them up for a better fit.
It may be necessary to use zip ties to secure the wiring to prevent disconnects, another method would be to borrow the wife's hot glue gun and permanently attach the wires to the breadboard ( make sure everything works first ). On my setup I used some double sided tape to secure the wires. Also in my setup I've mounted everything into a small plastic box to protect from possible splashes on brew day.
Software setup:
One programming language commonly used in Linux is called "Python" and at the end of this write up I've provided the Python code I've written for this project. Note: if you want to change the code to add other features please feel free to do so, just be aware I am not a professional programmer ( and not much of an unprofessional one either ) so if you have questions about changing the code or adding to it please direct your questions to someone more knowledgeable about Python than myself ( "my Python Kung-fu is not the best" ).
I'm using version 2.7.6 of Python. Python is pre-installed in most versions of Linux, you will however need to add some modules to make this project work.
To display the output in easy to read GUI windows it's necessary to load the "TKinter" module, to do this open a Linux terminal window and enter...
sudo apt-get install python-tk
the "Pyserial" module is required to communicate with the serial port that the Arduino sends data to, instructions to download and install this module are here...
http://pyserial.sourceforge.net/pyserial.html
The Python code I'm providing will need to be modified to reflect which device your system uses for the serial port output, in my case it's "/dev/ttyACM0' but yours will most likely be different, when you install the Arduino IDE software on your system there is a step that determines the correct device for you to use.
To facilitate editing your Python code there is a IDE ( Integrated development environment ) you can use called IDLE which is pre-installed on most Linux systems, IDLE I believe is a universal IDE and may need to be set for Python. ( Note: IDLE is separate program from the Arduino IDE also needed. )
The programming language used by the Arduino is "C/C++" and again at the end of this write up I've provided the C code I've written for this project. Note: As before, if you want to change the code to add other features please feel free to do so, just be aware I am not a professional programmer so if you have questions about changing the code or adding to it please direct your questions to someone more knowledgeable about C/C++ than myself.
The Arduino code provided will also need to be modified, you'll need to specify the addresses of your probes. For example the address of one of my probes is...
DeviceAddress Probe01 = { 0x28, 0x14, 0xB3, 0x5C, 0x06, 0x00, 0x00, 0x83 };
The Hex code listed is the serial number of the probe. Each probe contains a DS18B20 transistor and each transistor has a unique serial number, directions on obtaining your serial numbers will follow.
To edit and install your Arduino code you must install the Arduino IDE available at...
http://arduino.cc/en/main/software
Links to installation directions are located on that same page.
Once you have the Arduino IDE installed there are 2 modules required for this project...
The "Dallas Temperature Control Library" at...
http://milesburton.com/Main_Page?title=Dallas_Temperature_Control_Library
and the "One wire library" at...
http://www.pjrc.com/teensy/td_libs_OneWire.html
After you've installed these libraries, from the Arduino IDE "file" drop down menu select the "/examples /Dallas Temperature /Tester" file and upload the file to the Arduino, on the right side of the IDE window is a small magnifying glass icon, click this icon to open the serial monitor window. De-select "autoscroll" in that window and scroll up to the top of the data. There you will find the serial number/addresses of your probes ( assuming they are hooked up correctly ).
Edit the Arduino code I've provided and enter your correct address information in place of mine, upload the code to the Arduino. Note: You can open the serial monitor window previously described to see the raw data coming from the probes but do not open the serial monitor window while the Python program is running as this will crash the Python program.
Once the code is loaded into the Arduino it immediately begins executing and starts filling the serial port read buffer with data, you should have the Python code ready to start at the same time as the Arduino in order to keep the the data being displayed in sync with the actual data coming from the probes.
The Arduino hold it's programming in memory and it immediately begins executing the code when power is applied either by turning on an external power supply connected to the Arduino ( not used in my example ) or by plugging the USB cable the Arduino is attached to into the host computer. To empty the serial port read buffer just unplug the Arduino USB cable.
Just to be clear, once the code is loaded on the Arduino and running correctly there is no need to reload the code onto the Arduino ever again or to ever launch the Arduino IDE program again.
To launch the Python program start IDLE and open the program code you previously edited and saved ( you did save it didn't you? then start the program from the run menu. You can also set the file up to run just by double clicking it, I haven't gotten around to doing that yet, I'm just happy it works!
In my code I've set it up for the Arduino to poll the probes once every 4 second at which time it writes a separate line of data for each probe ( i.e. 3 lines ), the Python code reads one line of code every second which means it takes slightly over 3 seconds to read those 3 lines of code. Depending on how much of a head start the Arduino has over the Python program the Python program will eventually catch up on the data already written to the serial port read buffer. It may be possible to send a purge command to the buffer when the Python program starts but I haven't spent a lot of time looking into this as it's not really a problem as long as the Python program is started in a timely fashion after the Arduino is powered up.
If you are an accomplished programmer you may wish to change the code to display all three probe data streams at once instead of cycling through them as I've set it up. I had tried writing 3 separate programs, one for each probe's data to be displayed in a separate window, but when I ran the 3 programs I would start getting garbage after just a couple of seconds. I believe that the garbage was being produced when all 3 programs were trying to access the serial port read buffer at the same time, causing collisions.
BTW, It took me a couple of weeks to get my setup working, mostly because I haven't written any code in over a decade. It took several days to get the mental cobwebs blown out
Cheers!
---------------- Python code ----------------
from Tkinter import *
import serial
root = Tk()
var = StringVar()
ser = serial.Serial('/dev/ttyACM0', 9600)
class App:
def __init__(self, master):
self.y='0'
self.t=ser.readline()
if 'P1' in self.t:
self.y='HLT = ' + self.t[3:8]
if 'P2' in self.t:
self.y='MLT = ' + self.t[3:8]
if 'P3' in self.t:
self.y='BrK = ' + self.t[3:8]
self.x=str(self.y)
self.x+=u'\N{DEGREE SIGN}''F'
self.w = Label(textvariable=var, height=3, width=14, bg="Black", fg="Red", font=('Verdana', 80, 'bold'))
var.set(self.x)
self.w.pack()
self.id = self.w.after(1000, self.timer)
def timer(self):
self.t=ser.readline()
if 'P1' in self.t:
self.y='HLT = ' + self.t[3:8]
if 'P2' in self.t:
self.y='MLT = ' + self.t[3:8]
if 'P3' in self.t:
self.y='BrK = ' + self.t[3:8]
self.x=str(self.y)
self.x+=u'\N{DEGREE SIGN}''F'
self.w.config(textvariable=var)
var.set(self.x)
self.id = self.w.after(1000, self.timer)
app = App(root)
root.mainloop()
---------------- Arduino code ----------------
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS_PIN 2
OneWire oneWire(ONE_WIRE_BUS_PIN);
DallasTemperature sensors(&oneWire);
DeviceAddress Probe01 = { 0x28, 0x14, 0xB3, 0x5C, 0x06, 0x00, 0x00, 0x83 };
DeviceAddress Probe02 = { 0x28, 0x46, 0xD4, 0x5B, 0x06, 0x00, 0x00, 0x05 };
DeviceAddress Probe03 = { 0x28, 0x65, 0x6E, 0x5C, 0x06, 0x00, 0x00, 0x9E };
void setup()
{
Serial.begin(9600);
sensors.begin();
sensors.setResolution(Probe01, 12);
sensors.setResolution(Probe02, 12);
sensors.setResolution(Probe03, 12);
}
void loop()
{
delay(4000);
sensors.requestTemperatures();
Serial.print("P1 ");
printTemperature(Probe01);
Serial.println();
Serial.print("P2 ");
printTemperature(Probe02);
Serial.println();
Serial.print("P3 ");
printTemperature(Probe03);
Serial.println();
}
void printTemperature(DeviceAddress deviceAddress)
{
float tempC = sensors.getTempC(deviceAddress);
if (tempC == -127.00)
{
Serial.print("Error getting temperature ");
}
else
{
Serial.print(DallasTemperature::toFahrenheit(tempC));
}
}
---------------------------------------------------------------------------
Last edited by a moderator: