When hacking and beer can come together into one single moment, you know you’re having a good day!
The Story:
And I’ve been having quite a few good days lately! You see, many years ago I tried my hand at making some homemade root beer the natural way (with yeast)… Aboslute FAIL! It was many years ago so I don’t know what went wrong but I’ve gotten over the disappointment and decided to try again.
Making root beer is actually very similar to making beer. I’ve been trying my hand at root beer simply to learn the basics, plus I’m sure my nieces and nephews will enjoy it! Once I can make a good batch or two of root beer I am moving up to actual brews! Mmmmm… Can’t wait to brew my own IPA!
My current batch of root beer isn’t carbonating as fast as I remember it doing years back… if at all! I’m pretty bummed about it but this time instead of getting discouraged about it I’ve decided to take one of the arts I’m gifted at (hacking & programming) to improve this new art I’m trying to learn.
You see, there are many variables when it comes to making a good homebrew. Temperature is one of the important ones (all the way from the water to the belly). In order for the yeast to properly carbonate the beverage it needs to sit at just the right temperature with very little temperature fluctuations. Since I live in a house that turns 120 years old this year, I’ve found it very difficult to regulate the temperature well.
The Goal:
At this time I’m not 100% certain that temperature is my current problem, but from what I’ve read it’s one of the most common reasons that the yeast may not carbonate. This project’s main goal is to monitor the area temperature my brew is sitting in and be able to look at historical numbers on the batch. This will help me to make a consistent brew and determine if temperature is my issue. If not, I can look elsewhere.
I also want to be able to view this information remotely (via web browser or Android phone) in order to alert me if there are temperature changes that could put the batch in jeopardy. Using the sensor I can also determine the prime location in the house.
Hopefully, this will help someone out in the future. I’m also posting all the code for the Arduino and Python.
The Solution:
I have a Springfield Precision #91751 atomic clock whose purpose also doubles as a home weather station. Included with this was a wireless thermometer/humidity sensor to be placed outside. I’d like to tap into the RF Card on the atomic clock and decode the data being sent to the clock in order for it to be logged on my computer for further processing and analysis.
Here’s a quick video of the project:
The Process:
The Arduino Code:
The heart of the Arudino code is the pulseIn() function. It’s purpose is to monitor a pin and measure how long that pin stays HIGH. In this case we are monitoring pinData (Pin 3). The length of the pulse indicates a 1, 0, or data break. The function decodeTime() converts the pulse length into 1 or 0, or a data break.
When all is done, the program looks for the ID number (“10011001000000000000″) in the bit stream. Doing this helps alleviate the possibility of receiving data from a rouge transmitter.
In the bit stream the temperature directly follows the ID. It’s broadcast in Celcius. Right after temperature is the humidity. The ID, temperature, and humidty are sent four times per transmission.
The output of this program (when NOT in debug mode) is similar to the following:
Temp: 11011100 Humidity: 01000010 <END>
int pinLED = 13; // LED connected to digital pin 13
int pinTrigger = 2; // This pin goes HIGH when data is being sent. (ORANGE)
int pinData = 3; // This is the pin that the data is sent on (RED)
int pinDebug = 8; // Debug ouput when pin is HIGH.
int pinDebugLED = 12; // LED lit when debug mode is active.
boolean debug; // Debug out to serial port, else just temp and humidity.
void setup()
{
Serial.begin(9600);
pinMode(pinLED, OUTPUT);
pinMode(pinDebugLED, OUTPUT);
pinMode(pinTrigger, INPUT);
pinMode(pinData, INPUT);
pinMode(pinDebug, INPUT);
}
void loop()
{
if (digitalRead(pinTrigger) == HIGH){
captureData();
}
if (digitalRead(pinDebug) == HIGH){
digitalWrite(pinDebugLED, HIGH);
debug = true;
} else {
digitalWrite(pinDebugLED, LOW);
debug = false;
}
}
int decodeTime(int time){
//This is passed a time in µs (microseconds) and determines if it is a long or short pulse.
if (time > 0 && time < 5000) {
if (time < 3000) {
return 0;
} else {
return 1;
}
} else {
return -1; //Time was 0 or greater than above... Not a 1 or 0.
}
}
void captureData(){
unsigned int x=0;
unsigned int i=0;
int rawData[1000];
//boolean data;
if (debug){Serial.println("Capturing...");}
digitalWrite(pinLED, HIGH); // sets the LED on
do {
rawData[i] = pulseIn(pinData, HIGH);
i=i+1;
} while ((digitalRead(pinTrigger) == HIGH) && (i<1000) );
if (debug){Serial.println("End Capture.");}
digitalWrite(pinLED, LOW); // sets the LED off
if (debug){Serial.println("Number of pulses:");}
if (debug){Serial.println(i);}
//Decode
if (debug){Serial.println("Decoding...");}
String Data = "";
for (x=0; x < i; x++){
switch (decodeTime(rawData[x])){
case 0:
digitalWrite(pinLED, LOW);
Data = Data + "0";
break;
case 1:
digitalWrite(pinLED, HIGH);
Data = Data + "1";
break;
default:
Data = Data + "\n";
break;
}
}
digitalWrite(pinLED, LOW);
if (debug){Serial.println(Data);}
//Find ID start:
int IDStart = Data.indexOf("10011001000000000000", 10);
if(debug){Serial.println("ID Starts at the " + (String) IDStart + " pulse."); }
if (IDStart < 0) {
if (debug){Serial.println("ERROR: Invalid ID");}
return;
}
String temp = Data.substring(IDStart + 20, IDStart + 28);
String humid = Data.substring(IDStart + 29, IDStart + 37);
if (debug){Serial.println("");}
Serial.println("Temp:");
Serial.println(temp);
Serial.println("Humidity:");
Serial.println(humid);
Serial.print("\n");
delay(2000);
}
The Python Code:
This Python code may need to be modified slightly in order to run under Windows. If you wish to run this under Windows I believe all you would need to modify is the /dev/ttyUSB0 line to match your COM port on Windows.
This code listens to /dev/ttyUSB0 and decodes the data from the Arudino. It’s in charge of converting the binary to decimal, converting Celsius to Fahrenheit, and outputting a CSV. Eventually, I’ll update this code to make the data accessible from the web so I can monitor from my Android phone.
#! /usr/bin/env python
# Atomic Clock Thermometer
# Author: Gregory Strike
# Tested on Python 2.6.6
# Using pySerial 2.3-1
import serial
from time import *
#Yeah, it's hard coded.
s = serial.Serial('/dev/ttyUSB0', 9600, timeout=0)
filename = "temphumid.csv"
data = ""
while True:
waiting = s.inWaiting()
if waiting > 0:
data = data + s.read(waiting)
if data.find("") <> -1:
tempStart = data.find("Temp:") + 7
binTemp = data[tempStart:tempStart+8]
humidStart = data.find("Humidity:") + 11
binHumid = data[humidStart:humidStart+8]
temp = long(binTemp, 2)
strTemp = str(temp)
temperature = float(strTemp[:2] + "." + strTemp[-1])
temperature = (1.8 * temperature) + 32
temperature = round(temperature, 1)
humidity = long(binHumid, 2) / 2
#print strftime("%Y-%m-%d %H:%M:%S")
#print "Temperature:"
#print temperature
#print "Humidity:"
#print humidity
#print data
file = open(filename, "a");
line = strftime("%Y-%m-%d %H:%M:%S") + ", " + str(temperature) + ", " + str(humidity) + "\n"
file.write(line)
file.close()
print line
data = ""
That’s it folks. I’ll be keeping this code updated as I make changes but please feel free to use it as you see fit. Thanks to the guys (error404 & GaspingSpark) in the Hack A Day Forums for some much needed direction. The forums are definitely a great resource especially when people contribute!









Pingback: Weather station turned data logger - Hack a Day
Pingback: Fermentation – The Golden Step in any Craft Brew | Gregory Strike