Fermentation Temperature Controller


The optimal temperature for the fermentation of beer is around 20°C, depending on the yeast strain. Let the beer ferment at too high a temperature and off-flavours will be produced, too cold and the fermentation may stall.  Realistically, you can leave the beer to ferment in a room which is roughly the right temperature and make good beer.  However, with a little effort, it’s possible to convert a fridge or freezer into the ideal fermentation temperature controller.

The Design

Many people simply hook one of these up to fridge and tube heater.  Put your fermentation bucket inside the fridge and the TC-10 will switch the fridge on when its too hot and switch the heater on when it’s too cold.  The main problem with the TC-10 and other similar devices (other than their high price tag!) is that they don’t log temperature over time.

With this in mind, I designed my own temperature controller, based on the TC-10, but with the added feature of temperature logging.

At the heart of my design is a PIC16F88 microcontroller.  This reads the temperature from the digital DS18B20+ thermometer, saves the temperature to a 512Kb EEPROM, displays the temperature to an LCD display and finally controls two relays to switch the heating and cooling circuits using a simple on-off control scheme.  A MAX232 is used to send EEPROM data over RS232 serial to a computer.

Here are the circuit diagram and single sided PCB:

(These can be downloaded in Eagle format here).

Writing the PIC Firmware

The PIC firmware is written in C, using the Hi-Tech compiler.  Hi-Tech provide some libraries for common tasks, which for the most part, proved useful.  I used the lcd.c library to control the LCD (with some modification to allow connection to any combination of IO pins) and the 1wire library for communication with the DS18B20+ thermometer.

The only problem was the I²C library provided by Hi-Tech, needed to communicate with the EEPROM.  After many hours of hair pulling (and coming extremely close to purchasing a Logic Analyser!), I discovered a bug in the I²C library itself.

Here’s the i2c_Stop function copied from the library.  Take a look at the spec here… this code is clearly wrong! SDA should transition from low to high, so the second line is wrong.

void i2c_Stop(void)
/* don't assume SCL is high on entry */

SDA_LOW();                    /* ensure data is low first */

SCL_DIR = I2C_INPUT;        /* float clock high */
SDA_HIGH();                    /* the low->high data transistion */
__delay_us(I2C_TM_BUS_FREE);    /* bus free time before next start */
SDA_DIR = I2C_INPUT;        /* float data high */


The fix is simple:

/* don't assume SCL is high on entry */

SDA_LOW();                    /* ensure data is low first */
SCL_LOW();                    /* ensure clock is low first */

SCL_DIR = I2C_INPUT;        /* float clock high */
SDA_HIGH();                    /* the low->high data transistion */
__delay_us(I2C_TM_BUS_FREE);    /* bus free time before next start */
SDA_DIR = I2C_INPUT;        /* float data high */


With that fixed, the rest was reasonably straightforward.  A Real Time Clock (RTC) was programmed using interrupts (on testing, it loses roughly a second every hour, which is fine for my purposes!) and care was taken to save state parameters (such as current time, the EEPROM pointer etc.) to the PIC’s internal EEPROM to protect against power cuts.

Using the RTC, the firmware performs on-off control with a period 8 minutes.  This is to ensure the fridge/freezer isn’t turned on and off too rapidly, which may shorten it’s life as well as the life of the relays.  Temperature and relay state is saved to EEPROM every 4 minutes, which allows up to 45 days of logging.

The On-Off Control Scheme

The following C code implements on-off control.

void control_temp(void)
//only control every 8 minutes
if(minutes%8 != 0 || minutes == minutes_when_checked_temp)

minutes_when_checked_temp = minutes;

if(temp > 30 || temp < 5)    //if erroneous measurement, switch everything off!

if(temp > setpoint + 0.5)
else if(temp < setpoint - 0.5)

Note there is a hysteresis of ±0.5°C.  This parameter might need tweaking depending on the performance of the system.

Download the firmware here.

Reading the EEPROM Temperature Log

The MAX232 allows connection of the PIC16F88 to the serial port of a computer.  The PIC is set to interrupt on each received byte.  If the byte read is ASCII ‘A’ (0×41), it will read and transmit the contents of the EEPROM over the serial port.  I wrote a small C# application to to send this control byte, parse the received output and save the result to a CSV file which can then be opened in Excel.

This is the first program I’ve written in C#, but I found it to be a fairly painless experience.  I based the program on the SerialPort example by Noah Coad.

The only interesting part of the code is handling the quirky float implementation of Hi-Tech’s C compiler for the PIC.  Hi-Tech base their implementation on the IEEE-754 floating pointing standard, but truncate the first byte (presumably to save space and speed up performance – the PIC has no FPU, so floats have to be implemented in software!).  The example below shows the hex representation of 24.5 in Hi-Tech and IEEE-754:

//float: 24.500000, hex: 00 C4 41 (Hi-Tech truncated format)
//float: 24.500000, hex: 00 00 C4 41 (IEEE-754)

Once the format is understood (took me some time to find out this info!), the conversion in software is simple. In fact, this truncated format is actually quite handy, as it saves precious EEPROM space.

Here’s a screenshot of the program:

As soon as you open the COM port, you start receiving output from the PIC, which continually sends the time from the RTC and occasionally some debug information.  When the ‘Go’ button is pressed, the ‘A’ command is sent.  The PIC then sends all the EEPROM data.  This is parsed and the log file saved.

Download the Data Retrieval Source Code

Building the Controller

The PCB was etched using the method explained in my previous post.  Here are a few pictures of the PCB after soldering:

Note the relays can handle up to 12A at mains voltage, more than enough for a fridge/freezer.  I also added a thick layer of solder to the traces carrying mains current to ensure resistance is low (wouldn’t want to start a fire!).

Here are a few pictures of the circuit mounted in an ABS plastic box:

The wire to the left provides 5V DC to power the electronics.  The three wires at the top are mains power in and heater and cooler power out.  The thin wire to the right is the temperature probe.  The buttons on the front allow the desired temperature to be set.

I purchased a DS18B20+ digital thermometer packaged in waterproof steel probe.  Here’s a close up of the end of the probe:

Close up of the temperature probe.

The controller needs two power connections:

Power. Left is power to heater/cooler, right is 5V power for electronics.

For cooling, I used an old freezer.  This also provides good insulation.  A hard-wired incandescent light bulb is used for heating, which is cheaper than, but just as effective as, a tubular heater.

Light bulb (for heating) and the temperature probe inside the freezer.

The freezer plugs into a trailing socket, thus requiring no modification of the freezer itself (whether or not the internal thermostat needs disabling remains to be seen):

Black trailing socket which the freezer plugs into.

The fermentation controller is now complete!  It’s time for testing.

Testing the Fermentation Temperature Controller

I initially tested the system by just placing the probe in the freezer, setting the desired temperature to 20°C and letting it run.  The light bulb came on (it was only 11°C in the garage!) and quickly heated the air in the freezer to over 25°C in under 5 minutes.  After the 8 minute period had elapsed, the freezer would have immediately switched on, had it been plugged in.  Obviously this behaviour is very inefficient!

One way to solve this problem would be to reduce the period of the on-off control, but this would quickly wear out the relays (and possibly break the freezer compressor), as previously mentioned.  Instead, I tried putting the probe in a glass of water:

This seemed to work better.  It took 16 minutes to raise the temperature of the water from 18°C to 20°C.

The First Fermentation

I was happy enough with the above results to give a real fermentation a go.  So after a days brewing it was time to test it for real!  I set it up as before – the sensor placed in a glass of water (this time mixed with some steriliser) and a 100W light bulb.  I decided not to place the sensor in the beer itself, as it’s just one more source of possible infection.

Here’s the brew after the first night fermenting:

I downloaded the temperature log in the morning using the data retrieval software previously explained with a laptop and a RS232 to USB converter cable:

And made a plot of the temperature against time:

This actually came as a bit of a surprise.  The desired temperature was set to 20°C.  Hour zero represents the time at which the beer went into the fermenter (I had left it running empty before putting the beer in to get it up to temperature and then reset the time).  The beer actually went in a bit cool, at 18°C.  After an hour, the glass of water and the sensor had cooled to 19.5°C, so the light came on.  However, it also seems that the fermentation started to kick off at roughly the same time.  The combination of the heat from the bulb and the heat generated from fermentation (the yeast is currently in the aerobic stage) caused a spike with peak 22.2°C.

Due to the good insulation of the freezer, the heat generated from the fermentation maintained the temperature at roughly 21°C throughout the night.  Note that the controller was trying to turn the cooling circuit on (the blue line), but I had disconnected the freezer, as I had assumed it wouldn’t be needed due to an ambient temperature of just 12°C.


The hardware itself seems to be working well.  The response of the freezer still needs some testing though.

The result of the first fermentation is reasonably satisfactory – it’s already a huge improvement over just leaving it in a warm room and crossing your fingers.  It’s definitely the healthiest fermentation I’ve had yet and it looks set to finish in just a few days, whereas previously it has taken over a week.  However, the response of the on-off control could definitely be improved.

Once this first fermentation is complete, I will measure the thermal conductivity and cooling power of the freezer.  I will also research calculating heat produced by respiration. The will allow a proper model of the system to be formed such that sensible variables, such as bulb power and on-off period, can be chosen.  I may also experiment with putting the sensor in the beer itself (this is probably wise, but more effort in terms of cleaning and sterilising).  A goal of achieving less than ±0.5C error seems reasonable.


Eagle PCB
PIC Firmware
Data Retrieval Software

How to Make PCBs at Home

There are two problems with having PCBs professionally made: firstly it costs a lot of money, especially if you only want one or two made, and secondly it takes a long time.

Making PCBs at home is cheap, quick and easy.  I’ll now describe the ‘Toner Transfer’ method I use, based on other people’s methods from across the internet.  The beauty of this method is that you probably already have everything you need to get started – the only likely exception being chemicals needed to etch the board… this really is the cheapest method possible!

Things you’ll need:

  • Glossy photo paper.
  • Copper clad board.
  • A monochrome laser printer.
  • A household iron.
  • An etchant solution (more on this later!).

I’ll be etching the PCB for my Fermentation Controller.

Step 1 – Print your Design

Print your design onto the glossy side of the photo paper.  Here I’m using Eagle. I like to print a test page onto plain paper first, to make sure the scale is correct.  I’ll also check the components will fit etc., as this is the last chance to easily fix any mistakes!

Printing options used in Eagle.

Be very careful not to touch the printed design.  Grease from your fingers will inhibit the adhesion of the toner onto the copper.

Step 2 – Clean your Copper Clad Board

We will soon be transferring the toner, which you printed onto the glossy paper, onto the copper clad board.  To ensure the toner bonds nicely to the copper, the copper needs to be clean.  I first use wire wool to remove the oxide layer of the board and then go over it again with some white spirit.

Cleaning the copper clad board.

To the left is the printed design. Note, when cutting out the design, I left a small strip at the far end with which to hold the paper.  This avoids touching the design itself.  Note also the dirt on the white cotton wool!

You can see the white spirit is almost dried – once it has, move onto the next step.

Step 3 – Iron the Design onto the PCB

Position the design with the printed side touching the clean copper.  Set your iron to maximum temperature and, once heated, place on top of the design.  The goal of this step is to melt the toner whilst simultaneously applying pressure from above.  This will make the toner stick like glue to the copper.

Press firmly down on the iron for several minutes – this will heat the board through and melt the toner as desired.  The glossy paper will now be stuck to the board.

Step 4 – Removing the Glossy Paper

We now want to remove the glossy paper whilst leaving the toner stuck to the board.  This is best done by soaking the board and paper in hot soapy water:

Soaking the board in hot soapy water.

Leave the board in the water for 20 minutes or so – the longer the better.  With any luck it should come out looking like this:

And the glossy paper will peal off with ease, leaving the toner stuck to the copper:

I generally find a glue-like residue is often left in places where the copper should be bear.  For example, take a look at the white residue either side of the track in the bottom left hand corner of the following photo:

This can be removed by gently rubbing the surface with a toothbrush.  Cut the board out and leave to dry – it should look something like this:

The board ready to etch.

If there are any areas where the toner has come away from the copper, touch them up with a permanent pen.  The board is now ready to etch!

Step 5 – Mixing the Etchant

I use a mix of Hydrogen Chloride (HCl) and Hydrogen Peroxide (H2O2).  This is easier to use than Ferric Chloride, is less messy and is also easier to source.  To learn about the chemistry, click here.

In the UK, H2O2 can be bought in small quantities from chemists.  Boots often don’t stock it – I’ve found it’s best to ring and check first.  Annoyingly, they often only let you buy one bottle at a time (good for an etch or two), due to anti-terrorist laws (buy enough and you can make a bomb!).

My source of HCl is brick cleaner.  The bottle shown below contains 10% HCl.  The bottle of H2O2 is 5%.  At these concentrations, they should be mixed at 2 parts HCl to one part H2O2.

Step 6 – Etching the PCB

It’s time to etch the PCB!  Obviously these chemicals are dangerous – use gloves and eye protection!

The board covered in etchant.

The etchant will dissolve the copper not covered by the toner, leaving you with your design.  Swill the etchant over the board to speed up the process:

Swilling the etchant over the board.

Here you can see the etching process is almost complete:

Note the etchant turns blue, due to the copper now in solution.  Once finished, carefully remove the board with a pair of pliers and wash it off with some water.  Finally, use some wire wool to remove the toner, revealing the copper tracks of the PCB!

Etching completed.

Step 7 – Drill the Board

I use a pillar drill, set to high speed, to drill the board.  Below are the drill bit and adaptor used.

Drilling the PCB.

You’re now ready to solder!