Version 2.0 // Python temperature logging script Arduino + Raspberry Pi

temp_jig

Above is a temperature probe jig, it captures and logs the temperature from inside of the fermentor.

beer_sample_plot2

Plotting the data using a web API:

The plot above was generated using sample data and the service – https://plot.ly ( once you capture the data, you can upload your data_file.dat there and with a few clicks, make the graph ) – until you learn how to manually write the plot code in python.

Plotting the data using python code:

In the python code for the log – if you use this line to capture the data, then you can manually run the python code and it should generate a plot if you installed python right with all the necessary modules – this is considered machine readable the way that time.time is written to the file.  If you use the DATE/TIME instead, then I haven’t figured this out yep, so we use the web API (above) and upload the data and generate the graph like that.

logFile.write('{:10.0f}\t{:3.2f}\n'.format(time.time(),temperature))

a quick python plot example below:

plot

sample code to generate a plot from the sample data.

from matplotlib import pyplot as plt
from matplotlib import style
import numpy as np

# select the style
style.use('ggplot')

# unpack values into array when using numpy // python uses lists
x,y = np.loadtxt('test3.dat', unpack=True, delimiter='\t')

plt.plot(x,y)

# configure the labels
plt.title('temperature plot')
plt.ylabel('Y Axis')
plt.xlabel('X Axis')

plt.show()

 

Dynamic Temperature Python script…

Version 2.0 // logging of temperature code with appended date.  This version checks to see if the previous recorded sample is the same, if it is, it is skipped and not recorded.  This is useful to have when you are wanting to monitor and record temperatures over a long time, like months or a year and not waste data space on repeating values.

This code can be pretty much used with any temperature sensor, we use it with the Dallas DS18S20.

Let me briefly explain what the code is doing ( from top to bottom ), but I strongly recommend that you take some basic classes on Python, we are still learning it too :- ) that is the only way to take full advantage of it and learn a new skill – Python is a good thing to have on your resume these days too :- )

Special thanks go to “Ofnuts” (the person who helped up with the syntax to get this done from the python help forum)!

  1. we are importing some modules
  2. we are setting up some variables like LOGFILE_FORMAT & TIMESTAMP
  3. def – means defining a function, so we are defining a function called: logTemperature() – it does the logging of the temperature with an appending timestamp to a text file
  4. setup the serial connection from the Arduino over the USB cable
  5. last_temp_reading = – 273 (we are setting up a unrealistic condition for comparison temperature)
  6. the rest of the code checks for a clean string coming from the Arduino and converting it into a float so that an inequality check can be done
  7. a lot of the extra Printing was also done to test, you can take those out if you are not going to be looking at the screen and running the command in the background using nohup.
  8. If you know Python remove and add whatever you need and share with us if you end up doing something cool
import serial, datetime
from datetime import datetime
import time

LOGFILE_FORMAT = '%Y-%m-%d.dat' # could also contain a path: '/home/brewery/temperatures/%Y-%m-%d.dat'
TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S' # better make them human readable

LOGFILE_FORMAT_FILE_NAME = '/home/pi/python/datalog_onefile_test2_dynamic.dat'

def logTemperature(temperature):
    if not temperature:
        return; # no need to go further
    now=datetime.now() # get it only once to insure consistency
    logFilename=now.strftime(LOGFILE_FORMAT_FILE_NAME)
    loggedTimestamp=now.strftime(TIMESTAMP_FORMAT)
    logFile=open(logFilename,'a')
    logFile.write('{:s}\t{:3.2f}\n'.format(loggedTimestamp,temperature))
# if you want the decimal part of the time to be dropped use below line instead
# un-comment it and replace the .write line above
    # logFile.write('{:10.0f}\t{:3.2f}\n'.format(time.time(),temperature))
    logFile.close()

#define for the USB serial connection between the Raspberry Pi/Arduino Uno
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
ser.close()
ser.open()

last_temp_reading = -273

while True:
    temp = ser.readline().strip() # get something clean from the start
    if temp:   # a non-empty string is "True", an empty string (or None...) is "False"
        temperature = float(temp)
        print "printing variable", temperature
        print "printing temperature variable", last_temp_reading

# dynamic sampling, ignoring repeating temperature samples
        if last_temp_reading != temperature: # assumes you can't get a reading of -273, so first execution will always see this as true.
            print "temp is different, recording it!", temperature
            logTemperature(temperature)
            last_temp_reading = temperature
        else:
            print "temp is the same, ignoring it!!!", last_temp_reading

 

 

Posted in Arduino-RaspberryPi-Make-Beer | 1 Comment

Apricot Belgian Blonde 10 Gallon Recipe // All Grain

20160305_150844

brew-day: 12/26/2015 // OG – 1.072 // Update on temp. chart of fermentation later along with FG, we are hoping for 8%.  This recipe originally called for 3lb of sugar, we used 1.5lb.  If you want 9%, add that extra sugar.

For yeast using a 2000ml starter, French Saison #3711 prepared 28 hours ahead of time.  The best thing to do with starters if you really want to be exact about it, is to test the wort until it reaches an OG of approx. 1.040.  This will prepare and propagate the yeast for the main fermentation without tiring its self out before the main fight.  The best way to do that is with a refractometer (make sure to buy one with the SG wort scale for brix %).

sugar + yeast = alcohol, Co2 and heat.

Fermentation is an exothermic process. The internal temperature of the fermentor can be as much as 10F above ambient conditions on the outside, just due to yeast activity.

450x450x7462b.jpg.pagespeed.ic.zJ98iUC8K6

70 minute boil.

Malt:

  • 24 lbs of American 2-row (use local grain from your state/region if you can, support your local farmers)
  • 1.2 lb aromatic malt
  • 1.5lb cane sugar – [ in Belgian beers sugar is added to lighten the body of the beer without affecting the taste, it will also increase the ABV as it should fully convert.  Warning: Belgian beers are not Budweiser. drink them responsibly and slow… ]

Hops:

  • 10 minute into the boil (70 mins total), add 2 ounce of Magnum Hops – for Bitter
  • at end of boil, add 2 ounce of Styrian Hops – for Aroma

We always add Irish Moss at 15 minute to end of boil

Yeast:

We used a French Saison #3711 // but there are other choices not limited to: Abbey Ale or Wyeast 3787 (Trappist High Gravity) yeast (we recommend you make a starter atleast 24 hours bore brew day).

Fermentation:

Add 2 days into the fermentation the Apricot Puree, 5-6 lbs.  Fruit doesn’t transfer well in boil, otherwise skip if you don’t want the Apricots.

Posted in Belgian Beer Recipes | Comments Off on Apricot Belgian Blonde 10 Gallon Recipe // All Grain

Arduino + Raspberry Pi to measure fermentation temperature

This is the original Version #1 // it will get you going – please see Version #2 for the dynamic sensor processing and more on plotting the data using an API and code.

temp_jig

temperature logging sensor jig above in fermentor…

IMAG0398

Above on the left (Raspberry Pi), middle (breadboard), right (Arduino UNO) – this web site runs on the Pi and you are reading this article right now from it :- )

Home Brewing is more than just the act of beer brewing at home to many people // it is a hobby filled with lots of creativity, ideas and passion.  One of our goals was to capture accurate temperature measurements of the fermentation – once you capture the data you can do things with it.

We decided to use a digital 3 wire temperature sensor also referred to as a 1-wire system, because the data is sent over 1 wire, the other two are the volt and ground cable.

We used a DS18S20 Dallas 1-Wire digital thermometer, this sensor is digital and fairly accurate and the program can delivery the data in C or F or whatever you can program for, and it can send the signal over longer distances than an analog thermister.  Also you can have multiple digital readers on the same wire, since each one is identified with a digital ID and you can separate the sensors within the programming code.

http://pdfserv.maximintegrated.com/en/ds/DS18S20.pdf

STEP #1

Setup the Arduino + Raspberry driver software // Google this and do it on your own…

So in our setup we used an Arduino UNO connected via the USB cable to a Raspberry Pi B, and the Pi also powers the Arduino, get a better 2.0+ Amp power supply for the Pi, ours is 2.5 Amp. You also have to install drivers that allow the two to communicate over the USB cable (serial) connection of the cable.

STEP #1.1

You need to connect the sensor correctly to a 4.7K ohm pull-up resistor, we used a breadboard to help us with the connections, but you can prototype it better.  The breadboard will connect to the Arduino, below a simple way to show the connections of the cables.  The C code is setup to receive the input on pin 2.

DS18S20-hookup

STEP #2

Arduino

Get a program working in C (language) on the Arduino loaded correctly through the IDE, to read the temperature from the sensor – you will have to learn how to do this part and be overall familiar with the basics of how to use the Arduino.    If you never done this before, (go learn that and then come back to do this step), we are sharing the code that we use below, it compiles fine, you might have to install some dependencies, like the OneWire and Time libraries (learn that too).

#include <OneWire.h>
#include <Time.h>

int DS18S20_Pin = 2; //DS18S20 Signal pin on digital 2

//Temperature chip i/o
OneWire ds(DS18S20_Pin); // on digital pin 2

void setup(void) {
Serial.begin(9600);
}

void loop(void) {
float temperature = getTemp();
Serial.println(temperature);

delay(5000); //just here to slow down the output so it is easier to read

}
float getTemp(){
//returns the temperature from one DS18S20 in DEG Celsius

byte data[12];
byte addr[8];

if ( !ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
return -1000;
}

if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return -1000;
}

if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Device is not recognized");
return -1000;
}

ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end

byte present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for (int i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}

ds.reset_search();

byte MSB = data[1];
byte LSB = data[0];

float tempRead = ((MSB << 8) | LSB); //using two's compliment
float TemperatureSum = tempRead / 16;

TemperatureSum = (TemperatureSum * 9.0)/ 5.0 + 32.0; // Convert to F

return TemperatureSum;

}

 

 

STEP #3

Use a Python script on the Rasberrpy Pi to read the signal data being sent by the Arduino, see examples of what we actually use right now below.  This script not only reads the data from the Arduino over the (serial USB) cable but also logs the data to a (tab delimited) text file while appending date/time stamp for each point reading, it does this every 5 seconds.  5 seconds could be an overkill for your project, maybe you want it every 30 seconds, it all depends what you are after and the resolution of the data capture that you need.

import serial, datetime
from datetime import datetime

LOGFILE_FORMAT = '%Y-%m-%d.dat' # could also contain a path: '/home/brewery/temperatures/%Y-%$
TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S' # better make them human readable

LOGFILE_FORMAT_FILE_NAME = '/home/pi/python/datalog_onefile.dat'

def logTemperature(temperature):
    if not temperature:
        return; # no need to go further
    now=datetime.now() # get it only once to insure consistency
    logFilename=now.strftime(LOGFILE_FORMAT_FILE_NAME)
    loggedTimestamp=now.strftime(TIMESTAMP_FORMAT)
    logFile=open(logFilename,'a')
    logFile.write(loggedTimestamp+'\t'+temperature)
    logFile.close()

#define for the USB serial connection between the Raspberry Pi/Arduino Uno
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
ser.close()
ser.open()

while True:
    temperature = ser.readline()
    print temperature
    logTemperature(temperature)

Version #2 of this code is available – http://kodiakbrewing.com/wordpress/?p=4172 // it ignores a temp sample if it incoming the same as the one just recorded, saving space if you are recording remotely over long time.

STEP #4

Do a test and record some data for a few days or a few weeks in the background using (nohup), you will have to learn Linux as well.  Run the script basically for a few days or weeks and then learn how to graph the data captured in whatever you see fit best way.  Once you have the data in a flat-file, you can transfer it over network and open the data with many different programs to create a temperature/date-time graph.  You can also use Python to create the graphs as well, etc…

We used a free program (Plot2) on a Mac to open the flat text file to read the data and it would actually automatically plot a graph.  Keep in mind that if you record a test sample of say 2 weeks (of stable temperature that don’t vary much), you will see mostly a flat line, but during fermentation you will see a spike of a few days and then a slow decline as the fermentation finishes off – but as tests go for (code and the sensor) – this is a good start.

So think about it, here you learn about the Arduino, and the Raspberry Pi and Linux, and text files to capture the data and C/Python programming languages, and how to graph the data, this is just scratching the surface.   You can take this much further, from displaying the temperature live on an LCD screen, to graphing it live on a LCD screen, to writing more program code and maybe even regulate a heater band over the fermentor to control the fermentation temperate after the yeast finishes its job, to deal with off-flavors for example and many other things, not just temperature.

You also see the min() and max() ranges the yeast temperature was reached during the reaction time of the fermentation to see if you hit the manufacturers recommended temp ranges, just yet another example of the data’s value.

Bottom line is that you not only learn new things, but capture useful data that you can analyze on and take action with – to in the end improve and make great beer.

Updates will come later with additional data, all our future beers will come with a fermentation charts of the overall process of the yeast used.

Also check out the – https://wizbrewery.wordpress.com/  Waldy the Wiz, also makes a great project and he shares all of his hard work – his is a little bit more advanced than our example.

Screen Shot 2015-10-19 at 7.40.50 PM

Posted in Arduino-RaspberryPi-Make-Beer | Tagged , , , , , , , , , | Comments Off on Arduino + Raspberry Pi to measure fermentation temperature

Imperial Brown Stout 10/11% All Grain Recipe

Mashout, brew date: 9/20/2015 ( next to an IPA on the right, our previous brew )..

OG 1.086 // FG after 2 week fermentation 1.025 – 8% ( we didn’t hit our goal of 10% because of the yeast that we used for this test, but the beer came out super delicious regardless, so it was a success! ) // Next time we will use the WLP007 yeast and should be closer to our target!

IMAG0331

This is going to be something new for us, we had plenty of good Porters and Black Stouts, but a Brown Stout ?  🙂 exactly!

Notice the nice Brown foam..

IMAG0333

Video of the fermentation the morning after :- )

 

For our 10 gallon batch we used these grains and also used 1LB of Light DME, to add to the ABV% without affecting the color of the beer or taste too much.

  • 18 lbs of Marris Otter Malt
  • 9 lbs British Brown Malt
  • 4 lbs Amber Malt
  • 1.4 lbs Black Malt (Roasted)
  • 1LB Light DME

6 ounces of Columbus hops (used for bittering) added at the beginning of boil with a 90 minute boil.

Yeasts:

Our first choice was WLP007, but it was sold out // so we picked a British Ale #1098 and did a 3 liter starter.  There are many other yeasts you could probably try, depending on what you like.

 

Posted in BEER Recipes | Tagged , , | Comments Off on Imperial Brown Stout 10/11% All Grain Recipe

Semper fIPA – All Grain Recipe

IMG_3067

 

Above picture credit: Danny Ferguson

next we are going to try a recipe by a fellow brewer from the Brew Nerds community on Google+  credit goes to Danny Ferguson

The Semper fIPA was targeted 7% ABV & 70 IBU / our version might vary based on what type of hops we can get, we will post our version later when we brew in about a month.

5.5 gal fermenter volume:

81% 2-row pale
6% German Munich
6% American carapils (dextrin)
4% American crystal 40
3% orange blossom honey (or enough to hit target gravity)

hops:

2.0 oz Amarillo leaf FWH – ( First Wort Hops )
0.5 oz Chinook leaf 30 min
1.0 oz Columbus pellet 30 min
1.0 oz Sorachi Ace leaf 15 min
2.0 oz Citra leaf dry hop 5 days

WLP001 yeast

Posted in BEER Recipes | Comments Off on Semper fIPA – All Grain Recipe