Introduction: A .NET Gadgeteer Based Fermentation Temperature Controller

In this article I demonstrate the design and fabrication of a touchscreen based automated fermentation temperature controller using a combination of commercial and custom hardware and software. I have been home brewing for over 20 years using primarily partial mash methods, but few years ago I finally transitioned to all-grain brewing. While I have been able to brew some great beers, the next logical step to improve the quality and consistency of my brew is to control the fermentation temperature. I recently acquired an old used refrigerator to use as a fermentation chamber, but instead of purchasing a commercial temperature controller I decided it would be more fun to design and build my own. I wanted a controller that has a touch screen interface and, since my fridge is located in my non-heated shop, I wanted the ability to control both a heater and refrigerator at the same time. For this project I decided to use the Microsoft .NET Gadgeteer system, which is a relatively simple modular plug and play microcontroller platform. There are a wide variety of commercial modules available, but it is also relatively easy to create your own custom hardware modules which I have done for this project.

Step 1: System Hardware


The FEZ Spider mainboard from GHI is a good starting point. It is based on a 72 MHz ARM7 processor and has 14 Gadgeteer compatible expansion sockets. This board also supports touch input, which not all mainboards do.

In order to control temperature we need to be able to turn AC power on and off . This is a job for a relay. For this project 2 relays re needed; one to control a heater and one to control a refrigerator. There are several commercial Gadgeteer relay modules available, but they contain from 4 to 16 relays, and most of those relays are rated to carry 10 amps or less. So rather than buying one of those modules, I chose to design my own custom relay module instead. For temperature sensing I was unable to find any suitable modules that had the accuracy and repeatability that I wanted, so I decided to design my own custom temperature sensor module as well.

Power Supply

I really don’t want to have a separate wall-wart type power supply in order to power the microcontroller board, so the controller has an internal PCB mount 120VAC to 12VDC 10 Watt power supply. This is fed into a USB power module which in turn powers the microcontroller and provides the programming interface.


Since I am controlling power to a refrigerator I need relays that can switch mains power at 120 VAC. Most residential refrigerators typically draw about 5 Amps, but the inrush current can be higher. Also, if controlling a heater, the current draw could be much higher. For safety reasons I prefer to use a relay that can handle the full current of a typical household circuit, which is 15 Amps. Very few mechanical relays that can handle this much current can also be controlled directly from a microcontroller. In this case, a relay driver circuit must be used which can be as simple as a transistor and a diode.

Transistors are often used as small signal amplifiers, but they can easily be used as a switch by driving them into saturation. By applying a small current to the base of a transistor it can control the current through the relay’s coil, which will actuate the contacts to switch power on and off to the refrigerator or heater.

I have chosen to use a simple NPN bipolar junction transistor (BJT) for this project as I happened to have many 2N3904 transistors on hand, however, a field effect transistor (FET) could also be used. In order to use the BJT to control the relay I have used the so-called common emitter configuration as shown in the diagram.

The transistor has its collector connected to one side of the relay coil and the emitter connected to ground. The other side of the relay coil is connected directly to the power supply. The transistor’s base is connected to the microcontroller through a suitable resistor, in this case 10kΩ.

The final component to the relay driver circuit is a flyback protection diode connected antiparallel across the relay coil. This diode protects the transistor by shunting current from the back-EMF pulse that is generated by the relay’s coil when the current is turned off. Without this diode, back-EMF voltages can easily damage the transistor.

Step 2: Temperature Sensing

Since I couldn’t find a temperature sensor module that I was happy with, I chose to design my own. My custom temperature measurement module is based on the Dallas/Maxim DS18B20 which is a 9 to 12 bit programmable resolution, 1-Wire® digital thermometer. This device is accurate to +/- 1°C, and at 12 bits you can get 0.0625 °C resolution. For this project I selected the DS18B20 6” Stainless Steel Waterproof Probe from The main drawback to this sensor is the 1-Wire serial bus interface. The 1-Wire bus uses a single wire for power and data transfer, so serial communications are somewhat complex and require very tight timing control. To eliminate this complexity I have used a DS2482-100 I2C-to-1-Wire Bridge to interface between the microprocessor and the temperature probe.

Step 3: Putting It All Together


After laying the parts out on the table and playing with arrangement, I estimated the size of enclosure that I would need to put all of the hardware into. There are an almost unlimited selection of plastic enclosures available but I finally settled on a black Serpac model 172. It is a nice looking enclosure and I can easily add a couple panel mount AC plugs to the front.

Prototype Board

For the prototype I built the circuitry on a generic Radio Shack perf board. After cutting the board to fit inside the enclosure, I laid out the parts ensuring that there were no clearance issues from the touchscreen or plugs mounted in the lid. Once everything is laid out, the circuit is soldered together with hookup wire.

Step 4: Programming

The first thing to consider is the software architecture. For this project I really want to separate the user interface from the controller operation as much as possible. This is a relatively common approach and there are several different architectures that have been designed with that concept in mind, but I chose to use the Model-View-Controller (MVC) architecture, which I feel would be a very good fit for this application. In this architecture the data, the application behavior, and the user interface are separate. The Model contains the application data and the business logic. The Views provide the user with a representation of the underlying data and application state. The Controller, as you would expect, controls the application and defines the behavior by sending commands to the model.

The User Interface

For the interface I want to have several different screens or views. First I want a dashboard type overview of operating parameters. I also want the user to be able to adjust certain parameters such as temperature set point and operating mode. I would also like to have a separate idle view that will be displayed the majority of the time which simply displays current temperature and possibly an icon, such as a snowflake or a flame, to represent the controller’s current operating state. In this project I have implemented a basic Windows-like interface with a title bar and glass-style buttons.

Dashboard view

The Dashboard view provides a high-level view of important information about the temperature controller. The primary information of interest for this controller is of course the current temperature in the fermentation chamber. I would also like to see additional information such as the temperature set point, the current mode and the current state of operation: whether it is currently heating, cooling, or idle. The Dashboard view will update its display periodically to reflect the current state of the controller.

Settings view

From the settings view we should be able to change the temperature set point, toggle temperature units between Fahrenheit and Celsius, and change the control mode to Heat, Cool or Both (Temperature Hold Mode). Each parameter can be changed with simple up/down buttons.

Idle view

The idle view will be displayed 99% of the time while the controller is just doing its job of monitoring and controlling the refrigerator’s temperature. This view is intended to provide a minimum of information at a glance when no user interaction is required. This screen is a very simple display of current temperature with a status icon on a black background. When the temperature controller is calling for cooling it will display a snowflake icon, and when it is calling for heat it will display a flame icon. Otherwise, the icon will be blank.

Step 5: Controller Operation

The basic operation of the controller is to display a splash screen for 5 seconds, then switch to the dashboard screen. If there has been no user input for at least 10 seconds the controller will automatically switch to the Idle screen. Touching the screen while the Idle screen is displayed will cause the controller to return to the Dashboard screen.

As the internal temperature of our refrigerator gets to the temperature set point I don’t want it to cycle on and off rapidly as that could eventually damage it. To prevent this I use hysteresis. This basically just means that the turn-on and turn-off temperatures are different. To keep things simple I have used a hysteresis value of 1 degree. Thus when cooling, the refrigerator will turn off when the temperature has reached the set point, and won’t turn on again until the temperature rises to 1 degree above the set point. Also, in order to keep the displayed temperature from jumping around I incorporated a running average of the last 16 temperature samples.

Custom Module Drivers

The next step is to write the drivers for the custom hardware modules. For the relays this consists of little more than turning a couple of digital I/O pins on or off. The temperature sensor module is a little more complicated and involves communications with the interface chip and temperature sensor, as well as decoding and converting temperature samples. After the drivers are written the custom hardware modules can then be accessed from the main software project to take temperature readings and turn the heating and cooling relays on or off as needed. The project is then compiled and deployed to the microcontroller.

I now have a fully functional homemade controller to maintain proper temperature during fermentation! For a finishing touch I epoxied a couple of hard drive magnets to the back of the case so that I can mount the controller to the side of my refrigerator.

Step 6: Custom PWB

The controller works like a champ as-is, but the next step towards a more professional looking product is to design a custom circuit board. This can be done using a circuit board design program like Altium Designer or Eagle PCB.

There are many companies that will fabricate prototype or one-off PCBs for a reasonable price. Most simply require uploading the Gerber manufacturing files that are output by the PCB design program.

All of the source code for the software projects as well as the Altera circuit board design project files are released as open source under the Apache V2 license. All project files, including a much more detailed design tutorial, are hosted on Github at