Introduction: Multiple Fermentation Chamber Control With BrewPi

In this Instructable I will try to explain how I built a BrewPi based fermentation chamber control system for multiple chamber control. If you are a brewer like me, you don't usually have just one beer going at a time. I have several. Subsequently, I have several fridges/freezers that I use as fermentation chambers. A single BrewPi setup will not work for me and making 3 separate setups, each with an individual Raspberry Pi is expensive and complicated.

There is a lot of information already out on the web on how to build a BrewPi system but there is not a whole lot of info on how use multiple Arduinos with a single Raspberry Pi in this type of build and what is out there is a bit disjointed and rather technical.

This Instructable will so you how to set up the system and then I will link to instructions on how to install the sensors, relays and LCD screen as these are pretty straightforward and have been covered extensively elsewhere.

BrewPi is an amazing little piece of software that was developed by Elco Jacobs several years ago. See their website here. It uses a Raspberry Pi to program and log data from one or more Arduino boards, and those boards in turn do the actual control of the relays for heating and cooling of a fermentation chamber.

The guys at BrewPi used to sell DIY kits, but they are no longer in production as they have moved to a different platform. The downside is that the new platform is not quite ready for stable use and it has a lot of missing features. It also doesn't come as a kit and costs a fair amount of money.

By making your own BrewPi control system you will save a TON of cash. I sourced almost all of the parts from Amazon and other sites like It took me a week to get all of the products and another few nights to put it together. But in the end, I had a really nice fermentation control system that logs all of my data and can replicate brews with a high degree of accuracy and I did it all for under $200, which is about the price of a new BrewPi Spark without any accessories or extra features.

Going forward, it would be best to remember a few things:

  1. I built a 3 chamber setup, so the instructions will reflect that; duplicate steps where necessary to add more.
  2. I named all of my files to correspond with "chamber1", "chamber2", "chamber3", etc. It would be best if you stuck to that theme for simplicity.
  3. I used LCD displays on my Arduinos, and they are the hardest part of this build. They are also completely optional.
  4. Look for a link at the end of the Instructable where you can download an exact image of my Raspberry Pi SD card. If you can't get it to work using these steps, downloading and writing the image to card card is a viable option. From there you can customize whatever you would like.
  5. It is SO much easier to configure the Raspberry Pi over an SSH terminal like PuTTY on your PC. For instructions how to connect to your Pi via SSH, look here.

Let's get started!

Step 1: Parts Required

To build the Raspberry Pi side of the system:

  • 1 Raspberry Pi 1 B or better. (You may be able to use earlier versions but I find that even the B runs a bit slow. I would recommend the Pi 2 B)
  • Powered USB Hub (If you are running more than 1 Arduino than this is recommended.)
  • 8 GB SD Card


  • USB WiFi Dongle
  • Case for Raspberry Pi

To program the Arduino Controller, you need the following for each chamber:

As I said, I will link to the instructions for adding the sensors, relays and LCD screens, this Instructable will focus on the multiple chamber programming and setup only. However...

To build the Arduino controller sensors, relays and (optional) LCDs you need a set of these items for EACH CHAMBER:

Step 2: Setup Raspbian OS and Identify USB Ports

We'll set up the BrewPi scripts and such on the Raspberry Pi first. There is already some documentation on this here. But in order to follow those directions you have to switch back and forth between that page and the original instructions so I will simplify it here.

Grab your SD card, connect it to your PC and make sure it was been formatted and contains the latest version of NOOBS, found here. If you don't have the latest version, download it, unzip, and copy all of the files onto your empty SD card. (If you are not familiar with Raspberry Pi, it uses an SD card as it's "hard drive" and NOOBS is the set of files you need on the card for the Raspberry Pi to build the Rasbian OS.)

Place the SD card into your Raspberry Pi, plug it into a monitor, attach a keyboard and mouse, and then the power cable. The Pi will boot into the NOOBS setup screen where you should select the Raspbian OS to install. This will take some time.

Once Raspian has been installed, it should boot directly into theraspi-config program, where you should set up a few things:

  • Enable SSH under Advanced options. This allows you to control your Pi over a network.
  • Make sure you set your internationalization options so you will have the correct time zone.
  • Choose the option to boot to the graphical desktop for now so we can configure wireless internet and check the web server later.

After you have set up all of your options, exit the configuration program and reboot. Attach an Ethernet cable to the port on the Pi and then to your network, or plug in your WiFi adapter and follow these instructions to connect to your WiFi network.

If you chose to boot to the graphical desktop, when it finishes, open a terminal window for the next steps.

In the terminal type:

sudo apt-get udate

and when that is finished, type:

sudo apt-get upgrade

This will take some time, but it will make sure that your Pi is up to date with all of the latest software.

We will now begin telling the Pi which USB ports we will use for which chamber. These ports will be permanently assigned to that Arduino device; if you have a USB hub plug it into the Pi now and turn it on. You'll also need at least 1 Arduino with USB cable so we can assign specific USB ports. The Arduino does not have to be set up yet.

Connect the Arduino to the hub port where your first chamber controller will be connected. You may want to mark the ports on the hub with a marker as "1", "2", "3", etc....

Type the following command: ls /dev/ttyACM*

This command basically asks the Pi "What device node is the Arduino using?"

This will return a node name such as: ttyACM0

Then type this command: udevadm info -a -n /dev/******* | less

(Where the ******* is, you will place the name of the node that was returned in the previous step.)

This will return a log list of data in several sections. The section you are looking for is the one that contains the text "ATTRS{product}=="Arduino" or something similar.

You will then be looking for a line in that section that says something similar to:


Write down that information somewhere and note that it applies to chamber 1, USB port 1, or however you will remember it.

Repeat the above steps for the remaining chambers, moving the Arduino to a new USB port each time. It does not have to be a different Arduino. I had 3 chambers, so I did these steps a total of three times.

I ended up with this in my notes:

Chamber 1: KERNELS=="1-1.3.1"

Chamber 2: KERNELS=="1-1.3.3"

Chamber 3: KERNELS=="1-1.3.2"

Once you have completed these steps and have written the information down, proceed to the next step.

Step 3: Writing the UDEV Rules for Raspberry Pi

Now we have to tell the Raspberry Pi that these ports should not change and are specific to our setup, so that no matter what happens, the specific port you chose for Chamber 1 will always be for Chamber 1. Otherwise the software could confuse the ports and you would be controlling the wrong chamber.

Start by typing the following in the terminal:

cd /etc/udev/rules.d/

This will put you into the correct directory to place your new UDEV rules file.

We will create the file and edit it at the same time by typing:

sudo nano 99-arduino.rules

This will open the terminal text editor. You will then write the rules (copy and paste if you wish) which will look similar to this:

SUBSYSTEM=="tty", KERNEL=="ttyACM0", KERNELS=="1-1.3.2", SYMLINK+="chamber1"

SUBSYSTEM=="tty", KERNEL=="ttyACM0", KERNELS=="1-1.3.1", SYMLINK+="chamber2"

SUBSYSTEM=="tty", KERNEL=="ttyACM0", KERNELS=="1-1.3.3", SYMLINK+="chamber3"

Where the ttyACM0 will be the node that you found in the first step, and the final part after SYMLINK will be the name you wish to use for each chamber. The KERNELS section is where you will put the information you recorded earlier for each chamber. You will have 1 line for each Arduino/Chamber you are controlling. In my case, there are 3 chambers with names chamber1, chamber2, and chamber3.

Once you have finished, use CTRL+X to exit the editor and save the file. Then, unplug your Arduino(s) and reload the UDEV rules by typing the following in the terminal:

sudo /etc/init.d/udev reload

Now would be a good time to reboot, then head to the next step.

Step 4: Installing BrewPi: Setting Up the Web Server

There are instructions for installing BrewPi here. There is even an automatic process; however, we need to do this manually and with some special changes such as adding multiple script instances so it would be best to follow the instructions below:

Install your web server:

BrewPi is configured by a web server, and as such you need what is known as LAMP (Linux, Apache, MySQL, and PHP/Python/Perl) to run it for you. Type the following commands into the terminal:

sudo apt-get update

sudo apt-get install apache2

sudo apt-get install libapache2-mod-php5 php5-cli php5-common php5-cgi

Now, test your server by typing the IP address of your Pi into a web browser running on a separate PC. You should see a page that says something like "It Works!"

Now install PHP by typing this into the terminal:

sudo apt-get install php5

That's it! Your're web server is now complete!

BrewPi does not support MySQL and it does not need to be installed.

Step 5: Installing BrewPi: Installing Python Components

BrewPi uses Python scripts to work. Therefore we need to install a few Python components to make it work. In the terminal, type the following:

sudo apt-get install python-serial python-simplejson python-configobj python-psutil python-git

and then to install Arduino core, use this command:

sudo apt-get install arduino-core

Let's get the some other Python stuff we need too; type this command:

sudo apt-get install build-essential python-dev python-pipsudo pip install psutil --upgrade

Step 6: Installing BrewPi: Go Git It

To install the BrewPi script we will use Git. In a terminal window, type the following commands:

sudo apt-get install git-core

This installs Git so you can use it to, well... Git the scripts.

We will now clone the repository from Git into each directory where we want BrewPi to run. You will do this for every chamber you want to control, in my example we will clone it 3 times into each of the chamber directories as such:

Type into the terminal:

sudo -u brewpi git clone /home/brewpi/chamber1

sudo -u brewpi git clone /home/brewpi/chamber2

sudo -u brewpi git clone /home/brewpi/chamber3

To update the script in the future, it would be best to start from this step and move forward. Automatically updating will not likely work correctly.

Step 7: Installing BrewPi: Modifying Configuration Files

We need to modify the config files to look for the Arduino exactly where we said they would be with the UDEV step.

Type the following into the terminal (Where "chamber1" is whatever you named your file if you changed it.):

sudo nano/home/brewpi/chamber1/settings/config.cfg

Then use the editor to write the configuration as below:

scriptPath = /home/brewpi/chamber1/

wwwPath = /var/www/chamber1/

port = /dev/chamber1

altport = /dev/null

boardType = uno

Under "boardType", enter whatever board type you have used, most commonly "uno". The altport is set to "null" so it doesn't look for a different port if it can't find the one you specified.

Hit CTRL-X to save and exit the editor.

Repeat this step for each chamber/directory you have set up.

Step 8: Installing BrewPi: Edit Web Interface Configuration Files

Now we need to edit the web interface configuration files for each instance:

Type the following command into the terminal:

sudo nano /var/www/chamber1/config_user.php

Then copy the following text into the blank file, save exit and repeat the process for the remaining chamber directories:

	// The default settings in config.php are overruled by the settings in config_user.php
        // To use custom settings, copy this file to config_user.php and make your changes in config_user.php
        // do not add a php closing tag, because newlines after closing tag might be included in the html
	// Do not include a trailing slash on the path
        $scriptPath = '/home/brewpi/chamber1';

Step 9: Installing BrewPi: CRON Jobs to Start Scripts

We now need to set up CRON jobs to start the script instances separately.

Type the following command into the terminal:

sudo nano /etc/cron.d/brewpi_chamber1

When the editor opens, copy in the following text:


* * * * * brewpi $PYTHON $SCRIPTPATH/ --config $SCRIPTPATH/settings/config.cfg --checkstartuponly --dontrunfile; [ $? != 0 ] && $PYTHON -u $SCRIPTPATH/ --config $SCRIPTPATH/settings/config.cfg 1>$SCRIPTPATH/logs/stdout.txt 2>>$SCRIPTPATH/logs/stderr.txt &

Note the "SCRIPTPATH=/home/brewpi/chamber1" entry and enter the directory for your first chamber there. Hit CTRL-X, save and exit, then repeat this process for subsequent chamber set ups.

Step 10: Installing BrewPi: Setting User Permissions

We need to create and give the Pi user "brewpi" permission to run and access the scripts remotely. For security purposes, we will create a "brewpi" user and give it full permissions for the BrewPi scripts only.

In the terminal, type the following:

sudo useradd -m -k /dev/null -G www-data,dialout brewpi

sudo passwd brewpi

This will create the "brewpi" user and ask you to set a password, write it down for later.

Verify what you created, by executing the following command in the terminal:

id brewpi

If successful, you should see something similar to:

uid=1001(brewpi) gid=1002(brewpi) groups=1002(brewpi),20(dialout),33(www-data)

Now, type the following commands into the terminal to set up permission groups for brewpi user.


sudo usermod -a -G www-data pi
sudo usermod -a -G brewpi pi

The next terminal commands are lengthy and best copied and pasted into the terminal using SSH from a PC:


sudo chown -R www-data:www-data /var/www/chamber1
sudo chown -R www-data:www-data /var/www/chamber2
sudo chown -R www-data:www-data /var/www/chamber3
sudo chown -R brewpi:brewpi /home/brewpi/chamber1
sudo chown -R brewpi:brewpi /home/brewpi/chamber2
sudo chown -R brewpi:brewpi /home/brewpi/chamber3
sudo find /home/brewpi/chamber1 -type f -exec chmod g+rwx {} \;
sudo find /home/brewpi/chamber2 -type f -exec chmod g+rwx {} \;
sudo find /home/brewpi/chamber3 -type f -exec chmod g+rwx {} \;
sudo find /home/brewpi/chamber1 -type d -exec chmod g+rwxs {} \;
sudo find /home/brewpi/chamber2 -type d -exec chmod g+rwxs {} \;
sudo find /home/brewpi/chamber3 -type d -exec chmod g+rwxs {} \;
sudo find /var/www/chamber1 -type d -exec chmod g+rwxs {} \;
sudo find /var/www/chamber2 -type d -exec chmod g+rwxs {} \;
sudo find /var/www/chamber3 -type d -exec chmod g+rwxs {} \;
sudo find /var/www/chamber1 -type f -exec chmod g+rwx {} \;
sudo find /var/www/chamber2 -type f -exec chmod g+rwx {} \;
sudo find /var/www/chamber3 -type f -exec chmod g+rwx {} \;

These commands set the permissions for all of the directories that we placed our BrewPi script in. The script does not work with a multiple chamber setup. If you have permissions issues later, run these commands again. Remember that "chamber1", "chamber2" etc... are the directories where you placed your BrewPi scripts. If you named them something different. Don't forget to replace them with what you used. Add or subtract sets of commands depending on how many directories you have created.

Now, use the following command to reboot your Pi:

sudo reboot

Step 11: Program Arduino(s) Using Web Interface

Now you can program your Arduinos with the proper script.

Plug your Arduinos into their respective ports on the USB hub, they should power up but probably don't have any code installed on them yet.

On your PC go to:

Download the appropriate HEX file for your Arduino (For example: uno-brewpi-revC.hex) and save it to your desktop or somewhere you will be able to find it later.

Open a browser window on your PC which is connected to the same network as your Pi and type in the Pi's IP address into the navigation bar.

It should open a folder with each chamber directory as shown in the photo.

Click on the first directory that you wish to access and it will open up the BrewPi web interface.

The script will not be running because it is not uploaded, so click on the Maintenance Panel button.

When the window opens, click "Reprogram Arduino"

When the reprogram window opens select the correct board type from the drop down, click the reprogram radio button, and then click to browse for your HEX file. Navigate to your HEX file you downloaded and click to open. When this is complete, click the "Reprogram" button.

The Arduino should program and you can watch the status in the window. Sometimes it will ask you to update certain software that is missing. If this happens, follow the instructions given in the status window and be sure to reboot your Pi every time you install/update something.

Repeat these steps for each Arduino/Chamber you have connected.

Step 12: Set Up a Monitoring/Navigation Page

If you would like, instead of accessing each BrewPi instance by typing in it's address and file name you can set up a main page in the /www/var directory so you can see all of the LCD status monitors at once.

In the terminal type:

sudo nano /www/var/chamber1/lcd.php

Then when the editor opens, copy and paste the following script:


* Copyright 2012 BrewPi/Elco Jacobs.
* This file is part of BrewPi.
* BrewPi is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* BrewPi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with BrewPi.  If not, see <>.

//load default settings from file
$defaultSettings = file_get_contents('defaultSettings.json');
if($defaultSettings == false){
	die("Cannot open default settings file: defaultSettings.json");
$settingsArray = json_decode(prepareJSON($defaultSettings), true);
	die("Cannot decode defaultSettings.json");
// overwrite default settings with user settings

	$userSettings = file_get_contents('userSettings.json');
	if($userSettings == false){
		die("Error opening settings file userSettings.json");
	$userSettingsArray = json_decode(prepareJSON($userSettings), true);
		die("Cannot decode userSettings.json");
	foreach ($userSettingsArray as $key => $value)

		$settingsArray[$key] = $userSettingsArray[$key];

$beerName = $settingsArray["beerName"];
$tempFormat = $settingsArray["tempFormat"];
$profileName = $settingsArray["profileName"];
$dateTimeFormat = $settingsArray["dateTimeFormat"];
$dateTimeFormatDisplay = $settingsArray["dateTimeFormatDisplay"];

function prepareJSON($input) 

    //This will convert ASCII/ISO-8859-1 to UTF-8.
    //Be careful with the third parameter (encoding detect list), because
    //if set wrong, some input encodings will get garbled (including UTF-8!)
    $input = mb_convert_encoding($input, 'UTF-8', 'ASCII,UTF-8,ISO-8859-1');

//Remove UTF-8 BOM if present, json_decode() does not like it.
    if(substr($input, 0, 3) == pack("CCC", 0xEF, 0xBB, 0xBF)) $input = substr($input, 3);</p><p>    return $input;

<!DOCTYPE html >
		<meta http-equiv="content-type" content="text/html; charset=utf-8" />
		<title>BrewPi reporting for duty!</title>
		<link type="text/css" href="css/redmond/jquery-ui-1.10.3.custom.css" rel="stylesheet" />
		<link type="text/css" href="css/style.css" rel="stylesheet"/>
		<link rel="apple-touch-icon" href="touch-icon-iphone.png">
        <link rel="apple-touch-icon" sizes="76x76" href="touch-icon-ipad.png&quoquot;>
        <link rel="apple-touch-icon" sizes="120x120" href="touch-icon-iphone-retina.png">
        <link rel="apple-touch-icon" sizes="152x152" href="touch-icon-ipad-retina.png">
        <meta name="apple-mobile-web-app-title" content="BrewPi">
        <meta name="apple-mobile-web-app-capable" content="yes" />
        <link rel="apple-touch-startup-image" href="splash.png" />
		<div id="lcd" class="lcddisplay"><span class="lcd-text">
		<span class="lcd-line" id="lcd-line-0">Live LCD waiting</span>
		<span class="lcd-line" id="lcd-line-1">for update from</span>
		<span class="lcd-line" id="lcd-line-2">script...</span>
		<span class="lcd-line" id="lcd-line-3"></span></p><p>		

		<script type="text/javascript" src="js/jquery-1.11.0.min.js"></script>
		<script type="text/javascript" src="js/jquery-ui-1.10.3.custom.min.js"></script>
		<script type="text/javascript" src="js/jquery-ui-timepicker-addon.js"></script>
		<script type="text/javascript" src="js/spin.js"></script>
		<script type="text/javascript" src="js/dygraph-combined.js"></script>
		<script type="text/javascript">
			// pass parameters to JavaScript
			window.tempFormat = <?php echo "'$tempFormat'" ?>;
			window.beerName = <?php echo "\"$beerName\""?>;
			window.profileName = <?php echo "\"$profileName\""?>;
			window.dateTimeFormat = <?php echo "\"$dateTimeFormat\""?>;
			window.dateTimeFormatDisplay = <?php echo "\"$dateTimeFormatDisplay\""?>;
		<script type="text/javascript" src="js/main.js"></script>
		<script type="text/javascript" src="js/device-config.js"></script>
		<script type="text/javascript" src="js/control-panel.js"></script>
		<script type="text/javascript" src="js/maintenance-panel.js"></script>
		<script type="text/javascript" src="js/beer-chart.js"></script>
		<script type="text/javascript" src="js/profile-table.js"></script>
  • Hit CTRL-X, save and exit. Do this for each chamber/directory you have created.

When you have created all of the lcd.php scripts you need, type the following command into the terminal:

sudo nano /www/var/main.html

Where "main.html" is the name you want to use for your monitor page.

Then enter the html code shown below into the editor:


<iframe src="../chamber1/lcd.php" scrolling="no" seamless="seamless"></iframe>
<iframe src="../chamber2/lcd.php" scrolling="no" seamless="seamless"></iframe><br/>
<iframe src="../chamber3/lcd.php" scrolling="no" seamless="seamless"></iframe>

Add more lines if necessary if you have more than 3 chambers or delete, if you only have 2. Hit CTRL-X, save and exit. Then open: http://your-rpi-ip/main.html in your browser,to open the monitor page.

Be sure to replace the IP address with YOUR Pi's IP address and to point it to the correct directories. You can then add clickable links, photos, or any other HTML that you would like to this page. I even added links to the other chambers in each Web Interface page so that I can click back and forth as needed.

Step 13: Installing Devices and Final Notes

I will not cover the installation of your Relays, Temperature Sensors and LCD screen as it is fairly straight forward and the instructions are well documented.

To install the devices to the Arduino, look here. (Skip past the software installation and go straight to the wiring schematic.)

To install the LCD screen look here.

Once you have everything attached, you should be able to go to your Web Interface and program some temperature settings. Be sure the relays function and that the temperature sensors are reading the corect values. There you have it! Multiple chamber control for the BrewPi set up!

If you have patience and high bandwidth, feel free to download my image of my Raspberry Pi SD card here:


Then use an imaging program in Windows on your PC to write the image to the card. It will give you a functioning 3 chamber setup, but you will still have to program the Arduinos, get your WiFi working with it, and possibly change some graphics around from my LCD monitor page. (I used the logo from our upcoming brewery.)

I used many references for this post and I will list them all here:

I hope you enjoyed this Instructable and that it made sense of a lot of confusing information!