Beeruino – is an #arduino based data logger and controller project that I dreamt up after my second pint of #homebrew. Here is an older video before the buttons were added for more flexible control.
What is it made of ?
Black project box (Radio Shack), donated to me by a fellow brew head
Originally using Arduino UNO R3 // Recently upgraded to the Mega 2560 R3 (more memory!)
Ethernet Sheild (gives Ethernet and SD card capability)
RTC (real-time-clock) using I2C bus (give accurate date/time)
dual 10 amp relay module (120 volt x 10 amp = 1200 watts)
dual A/C sockets, independent of each other (so different things can be controlled out of each socket)
4×20 LCD screen using the I2C bus
Arduino sketch C++ code
Power Cable to power the A/C sockets
Analog buttons to change the set goal temperature UP or DOWN on the control relay, and to RESET the DATA storage on the SD card
Beeruino now has control buttons and Version 2 of the code has been released. They allow you to control the target goal temperature without the need to change the value manually and no need to recompile the program using the computer, making it more independent and flexible as a tool.
Importing, Verifying, Analyzing and Plotting the Data:
I like to analyze the data using R (open-source) statistical software, that can do a lot more than just statistics, so don’t let that scare if you are not familiar or good with math/numbers.
Basically data in imported into R from the textfile.txt off the SD card, then I do some quick summary verification, I take a sample every 25 row and plot it in two different way using ggplot2. Temperature of internal/external split by day and also the whole plot in one not segmented or split.
These two plot show a simple test run on plain water in a 12.5 gallon fermentor.
Started with cold 44F well water, turned on Beeruino and set temperature goal to 65F, then later raised it to 70F and again for the duration of the test to 75F.
Here is a simple R script, this assumes you have some limited know-how in using R, if not do our self a favor and learn it.
Update: since this blog was written, the Project was transferred to a more professional looking project box and is now called the Beeruino, please search to see that blog – also code has been posted to Git.
empty cigar box (smaller plastic project boxes also are ideal, but cigar box was free)
Arduino UNO R3
Arduino UNO R3 compatible ethernet shield + SD card that plugs into the SD slot
two Dallas 1-wire temperature sensors (1 meter long, internal cable length was extended)
4×20 blue LCD Screen – works over I2C
an RTC (real-time-clock), also works over I2C
miscellaneous: wires, shrink wraps, hot glue, plastic wire ties and some light soldering
If you are one of those people – who is reading this and inside your head you are saying “why the hell should I do any of this shit, I just buy!!” – guess what, you are not a Maker and you will learn nothing from buying things that others have created. Once you learn, you have full control over your creation and any future ideas/goals, you are not tied to a product that someone else has created.
In this quick blog I wanted to share a quick story about how I converted an empty cigar box into a data logger. It uses the Arduino Uno and two Dallas 1-wire sensor to capture and record both the internal temperature inside the fermentor and the external temperature (outside the fermentor), so that we have a base to compare against. You should see a higher temperature inside, because when yeast ferments, that is considered an exothermic process – https://en.wikipedia.org/wiki/Exothermic_process
The primary goal was to create a small, portable system (small size and weight wise) and also for it to be independent, meaning be able to do everything on its own without external dependencies like the internet, or some network, at this stage we don’t want to send live data to the internet or log to a database // but those things can certainly be done and in the future can be nice to have.
To have this system somewhat nice, I have added a 4×20 blue LCD screen – it uses the I2C interface to make the hook up easy. Also an RTC (real-time-clock) was installed to work on the same I2C bus, this adds date+time.
In addition I have used 4-pin aviation plugs to make the sensors connection modular, so that they can be easily unplugged (cleaning or swapping) without messing with the internal electronics or wires…
Hot glue was used to stick things in place inside the cigar box, along with some limited soldering, and shrink-wrap, and wire ties to keep things organized and properly connected for solid connections.
The programming code is not super complex, and it being shared below:
It assumes that the external temp. sensor is being pulled from index(0) and internal from index(1). Having the temp sensors assigned to a static index will allow you to switch the aviation plugs and still have them assigned correctly and display from the right sensor without having to worry about which plug which should be.
A quick video and Arduino C++ code below…
The data is recorded on an SD card (inside the ethernet shield) which is plugged-in on top of the Arduino UNO R3.
Arduino dallas-1 wire code
LiquidCrystal_I2C lcd(0x27,20,4);// set the LCD address to 0x27 for a 16 chars and 2 line display
unsignedshortintcounter=0;// value range between 0 to 65,536 // we have no need to store negative value ranges
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
// Pass our oneWire reference to Dallas Temperature.
lcd.init();// initialize the lcd
// start serial port
// Start up the library
;// wait for serial port to connect. Needed for native USB port only
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
Serial.println("Card failed, or not present");
// don't do anything more:
// use this code if you want the file removed upon device reboot or reset ???
Serial.println("file1 doesn't exist.");
// lcd.print("kodiakbrewing.com ");
lcd.print("Log Counter: ");
lcd.print("log to: brewday2.txt");
lcd.print("Int. Temp: ");
lcd.print(sensors.getTempCByIndex(1)*1.8+32.0);// Convert to F
lcd.print("Ext. Temp: ");
lcd.print(sensors.getTempCByIndex(0)*1.8+32.0);// Convert to F
Serial.print("External Temperature is: ");
Serial.print(sensors.getTempCByIndex(0)*1.8+32.0);// Convert to F
adding flaked oats to mash: – add sweetness and body – read…
start of boil (using hop balls for whole hops so they don’t plug up the pipes):
transfer to fermentor:
next day fermenting:
Attempt #1 – OG 1.068 // FG 1.010 – final ABV 7.6% – yes a little higher then the 6.0% Diamond Knot..
Attempt #2 – OG 1.066 // FG 1.014 – final ABV 6.83%
Total water used 15.5 gallons for final 10 gallons of beer…
attempt #1 grains:
18 lb Pale Malt 2-row
4.5 lb Munich Malt 10 love
3.0 lb Crystal Malt 10 love – see below for attempt #2 changes
0.20 lb Chocolate Malt
0.20 lb Black Barley
1.0 lb flaked Barley
1/2 lb of brown sugar
attempt #2 grains:
18 lb Pale Malt 2-row
4.5 lb Munich Malt 10 love
1.5 lb Crystal Malt 15 love
1.5 lb Crystal Malt 60 love – we did this to give the beer more caramel flavor and beer body
0.40 lb Chocolate Malt – we double the dark grains to darken the color a bit
0.40 lb Black Barley
1.0 lb flaked Barley
1/2 lb of brown sugar – we didn’t use it this time, the sugar…
hops attempt #1:
2.0 oz Galena with some whole hops from last year’s harvest (Yakima & Cascade) at start of boil, added to the hop boil ball, see video.
2.0 oz Willamette last 15 minute of boil.
hops attempt #2:
2.0 oz of home grown Cascade Hops, 2015 harvest (beginning of boil)
1.0 oz of Cascade pallet + 1.0 oz Willamette pallet (last 15 minutes)
attempt #1 – Wyeast #1056 yeast was used, took 2 weeks to ferment out, this yeast consistently bubbled over the 2 week period…
attempt #2 – British Ale Wyeast #1098 // 2 liter starter // 1.040 gravity – majority of the active fermentation will be over in about 4 days, but let it go out full 2 weeks – because it’s still happening, just slower, also we like to allow extra time for all the floaters in the fermentor to settle. On that note, per one of our brew nerds – once fermentation is over, trapped dissolved co2 gas slowly escapes the beer, so it will give you a false sense of a fermenation – only way is to measure.
Above is a temperature probe jig, it captures and logs the temperature from inside of the fermentor.
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.
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)!
we are importing some modules
we are setting up some variables like LOGFILE_FORMAT & TIMESTAMP
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
setup the serial connection from the Arduino over the USB cable
last_temp_reading = – 273 (we are setting up a unrealistic condition for comparison temperature)
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
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.
If you know Python remove and add whatever you need and share with us if you end up doing something cool
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
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 %).
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.
70 minute boil.
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… ]
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
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).
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.
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.
temperature logging sensor jig above in fermentor…
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.
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.
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.
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).
intDS18S20_Pin=2;//DS18S20 Signal pin on digital 2
//Temperature chip i/o
OneWire ds(DS18S20_Pin);// on digital pin 2
delay(5000);//just here to slow down the output so it is easier to read
//returns the temperature from one DS18S20 in DEG Celsius
//no more sensors on chain, reset search
Serial.println("CRC is not valid!");
Serial.print("Device is not recognized");
ds.write(0x44,1);// start conversion, with parasite power on at the end
TemperatureSum=(TemperatureSum*9.0)/5.0+32.0;// Convert to F
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.
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
#define for the USB serial connection between the Raspberry Pi/Arduino Uno
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.
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.
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!
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..
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.
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.
You can now buy these from us – this is our way or raising cash to fund our operation/blog, since we can’t sell you beer.
HOPS ARE POISONOUS TO DOGS – if you add hops to the Mash, you can’t use the grain to make dog biscuits.
Tip – Most brewers will be too busy brewing the beer so collect a bunch of spent grain after the mash is over, (drain it of the wort) if you don’t want it to be too wet and stick it into the fridge for later, it should be good for a solid week or more. This way you can make the biscuits a few days later after your brew day when you are not so busy or too tired.
After a few tries using recipes from a Google I decided to make my recipe and combine my experience of bread baking, I list two recipes..
One of the things that I noticed from the Google recipes is that most of them used only 2 cups of spent-grain, that’s little grain. We all know we have “a lot!” more than 2 cups left after a brew.
Recipe #1 (the more messy recipe that takes more time, see Recipe #2 below if you want a quicker less messy solution)
4 cups of spent grain (no hops were used) – hops are poisonous to dogs
1 cup of – flour (you can combine either of flour types or just use one type)
1 cup of whole flour
2 cups of (beef or chicken) broth for flavor – heat it up in the microwave so that it is luke warm and add the yeast to it
1 egg (use the whole egg, calcium from shell is good if possible)
1/2 packet bread yeast (add to the broth, see above)
In a mixer: grain + flour + broth + egg.. mix it well, you can easily control how sticky it will be by adding chicken broth slowly or less of it, Add 1/2 packet of bread yeast with the broth (pre-heated), roll into a ball and let it sit under a towel for at least an 1 hour to raise..
Roll it out and use cookie cutters to take shape of your biscuits..
Preheat to 350F // bake for 30 ~ 45 minutes… Since you added yeast, these cookies will be nice and poofy.
After baking, lower temp to 200 ~ 220F and bake them for a few hours (2) to dry them out so that mold don’t take hold later (this largely depends on how thick your cookies are), thicker need longer drying time… We also use grocery paper bags for a week+ to remove any residual moisture, works well.
If your mix is sticky, just keep on adding flour until it’s not, use lots of flour on your work area so that the cookies won’t stick… If things seem too sticky, don’t give up, add more flour – no matter how crazy it looks! Also you have an option of using less broth, since that is what made them sticky.
I ended up with 3 sheets of cookies, use foil if you run out of cookie sheets :- ) pre-spray with cooking oil.. If you make your cookies thin, they don’t require as much extra drying time or next to none, don’t assume anything // check and look to make sure you are not overheating and burning them!
This recipe does not use bread yeast, is simpler and faster to prepare/make and it should not be sticky at all, also you do everything in the mixing bowl, so there is little to clean up later. If you are short on time go with this one and dogs love peanut butter cookies as well!
Once you have your mix spread out on the cookie sheet, I usually cut it into strips. If you want to spend the extra time using fancy cookie shapes, go for it. Dogs don’t care :- )
4 cups of spent grain (ours was pretty dry and stored in the fridge for 2 days after brew day)
1.5 cups of flour (pick type, whole or all purpose), if you grain is more wet, you might need 2 cups, add more if so
1 cup of peanut butter
mix this all up, pre-heat your oven to 350 F and stick it in there for 30 minutes, then reduce heat to 220F and leave it in there for 2 hours. Again, spray your pan so they won’t stick.
Below are our photos (is lighter than in the picture), should be – amber color, you should see through the glass to the other side.
Today we are sharing a recipe of another fellow brewer from the Brew Nerds Community on Google+ ( thanks for permission to share your recipe Bryan Carr!! )
Here is his recipe:
≈ 9.8-10.0 %
15# Maris Otter
1.5# Crystal 60
0.5# Crystal 120
2 oz Roasted Barley
2 oz Chocolate
0.5 oz Fuggle @ 90
0.5 oz Fuggle @ 60
1 oz Northdown @ 15
Yeast: WLP028 White Labs Edinburgh, 1L starter with 3 vials… call it overkill.
Mashed at 146 F for 60 minutes, then brought it up to 156 F for 30 minutes. Mashed Out at 170 F and collected roughly 9 gallons of wort for the boil. It had a 90 minute (rigorous) boil, and final volume of 5.5ish gallons.
Fermented at 70 F in primary for 1 month, then dropped it down to 58 F degrees in secondary for 2 months. Bottle conditioned for 6 weeks.
For our 10 gallon recipe (based on grains/hops/yeast) that we have access to we picked:
30 lbs of Golden Promise, at $1.30 a pound
3 lbs Crystal 60 Lov., at $1.85 a pound
1 lbs Crystal 120 Lov., at $1.85 a pound
4 ounces or 1/4 lb Chocolate malt 350 Lov., at $1.90 a pound
We couldn’t get a hold on the Northdown – substitute Perle hops // also got the Fuggles (multiplied for a 10 gallon batch). For yeast – Scottish Ale #1728 – using a 2000ml starter.
Further brew details and pics later…
OG was 1.086, FG was 1.014 // so basically 10%
The beer tastes awesome only 1 week out of fermentor (one week in fridge/keg), test pour.. the classic chill haze is there, but a few weeks later it will all naturally clear up, follow-up photo later.. Very drinkable only after 1 week – so I think we have a winner here!