BrewManiacEx 0.3


There are more and more functions, but I can’t test all functions because I don’t have all the hardware setup. Neither can they be tested in one single brew. Therefore, please verify before put it into real use.

What’s new

  • Post Boil Hop(HopStand)
  • Customized audio
  • Multi-button in Web interface
  • New setting options
    • button feedback, buzz on button pressed, or not
    • pump priming cycle, on time, off time.
  • Iodine test.
    • There are two options after Iodine Test. Go to Mash Out or Extend the mashing rest.
  • Export/import settings in web interface
  • Dual heater support by compile option. config.h@39
    #define SecondaryHeaterSupport true


  • Sparge heater is no longer  by default supported.
  • revise setting temperature of web interface. Correct setting temperature will be displayed in manual mode.
  • code revision.

Known issues:

  • The sound doesn’t paly on mobile Safari.
  • If the audio file is larger than 120k, it might not work.
  • Sometimes, Chrome don’t play the audio unless reloading the page.

Post Boil Hop(HopStand)

Check this post.

Customized audio

Currently, it works on Safari and Chrome, not tested on other platform. It doesn’t work on mobile Safari of iOS because it doesn’t allow downloading and playing audio without users’ action.

Two files are involve: sounds.json and the audio file. All segments of sound is put in a audio file, preferred to m4a(AAC) format, and specified by the sounds.json file.

sounds.json should be put in the root of the file system of ESP8266. If it is missing or in wrong format, all the sound effect will be replaced by simple buzzing.

The format of sounds.json is like this:


“src” specifies the source of the audio file. It doesn’t have to be on the controller. It can be a HTTP URL, and you can put it anywhere that can be assess by your browser. (If your audio file is larger than 150k, you might need to put it anywhere else instead of the controller.)

“seg” sepcifies the voices:

  • “s”: start of the audio, by seconds
  • “t”: duration of the audio, by seconds. Use 0 if not used.
  • “r”: times of repeat.

The meaning of the tags:


tag When Example
open Successfully connecgted BrewManiac, at your service
tr Setting temperature reached. Temperature reached.
addhop reminder of adding hop Time to add hop
addmalt reminder of adding malt Time to add malt
boil Boiling phase starts start boiling
boilend Finish boiling boiling finished
bye brew finished. brew finished. goodbye.
chill reminder of chilling for hopstand start chilling
cool start of cooling stage time to cool
iodine reminder of iodine test Time for iodine test
maltin temperature reaches mash-in temperature ready to doughing-in
mashout start of mashout start mash out
nmash proceed to next mash steop continue to next mash step
removemalt reminder of removing malt Time to remove malt
whirlpool reminder of whirlpool starts time to whirlpool
disc connection disconnected Controller disconnected


Guideline/tips of audio files

  • Keep the file as small as possible. It’s not concert recording, so use lowest sampling rate as possible.
  • If your audio file are larger than 150k, putting it on the controller might not work. (This might be issues of ESPAsyncWebServer/ESPAsyncTcp. Keep it as a known issue.)
  • There is a lag of playing audio on Safari. Around 200~250ms silence before(including) and after(not including) the audio segment is necessary to make it work better on Safari. For example, if the audio segment is 1 seconds and will be appended at time 15 seconds, you should insert a silence of 0.2 second before the real audio, and another 0.2 second of silence after the audio segment. Then, mark the segment start at 15 second with 1.2 duration.
  • OSX has text to speech built-in. You can type something like this to create a audio segment.
    >say -v "Samantha" "Hello, I am Siri."

    To output the audio to a file, add “-o” option, like “-o siri”.

  • oceanaudio is very good for creating the audio file. You can use it to
    • merge the audio segments
    • insert/delete silence space between segments
    • re-sample the audio to make it smaller
    • check the start and duration of the audio segment.

Multi-button in Web interface


On iOS, you can just press the buttons simultaneously, and release at the same time. (Not tested on Android devices.)

Using mouse to press two or more buttons on laptops or desktops is trickier:

  1. Click (and hold) anywhere on the rectangle area around the buttons, but not on the buttons.
  2. Drag through the buttons. The buttons will be hiligh-lighted.
  3. Release the mouse on one of the button.
  4. Releasing the mouse outside the buttons will have no effect. Moving outside the rectangle area during dragging will also cancel the action.

Dual elements and 3-kettle system

Grainfather has a switch labelled as “normal/mash”. When the switch is at “Normal” position, the heating element runs at maximum power. When it is at “Mash” position, smaller power is used. Therefore, that switch is put on “Mash” only when mashing. I have forgotten to switch for serval times, so I have thought of using the additional actuator(relay control) to control it. By supporting dual elements, the controller can be configured to run at lower power when mashing and at maximum by using both elements during heating striking water and boiling stage

The setting should be able to config the usage of elements for

  • Pre-mash (mash-in)
  • Mashing (mash rest through mash out)
  • Boil
  • Post Boil

To provide maximum flexibility, the setting will be Primary, Secondary, and Both.

How about 3-kettle system? BrewManiaxEx is designed for E-BIAB, right? Yes, but after reading the Electric Brewery, I found that by providing this new dual elements support, BrewManaicEx can be used to control a 3-kettle system.

Hardware Setup: (Please check the Electric Brewery for detail)

  • three kettle: HLT/MLT/BK with E-HERMS
  • Two elements in HLT and BK. (Additional mechanical switch is highly recommended.)
  • Two pump: water pump and wort pump.
  • BrewManiacEx setup
    • Three temperature sensors in three kettles
    • Control the two elements of HLT and BK. (Let HLT be primary and BK be secondary)
    • One pump can be controlled by BrewManiacEx, but the other must be controlled by a mechanical switch.

BrewManiacEx settings

  • Sensor setting (the primary sensor is the sensor used in PID algorithm.)
    • Pre-Mash primary sensor: HLT sensor
    • Mashing Primary sensor: HLT (or MLT)
    • Boil primary sensor: BK
    • Post Boil primary sensor: BK
  • Elements Setting
    • Pre-Mash: Primary(HLT):on, Secondary(BK):off
    • Mashing: Primary(HLT):on, Secondary(BK):off
    • Boil: Primary(HLT):off, Secondary(BK):on
    • Post Boil: Primary(HLT):off, Secondary(BK):on
  • Other related Setting
    • PID doughing-in: ON
    • PID remove malt: OFF (Currently this setting is call PID pipe, active or passive
  • Pump setting, if BrewManiacEx controls water pump
    • pre-Mash ON
    • Mashing ON
    • Boil Off
  • Pump setting, if BrewManiacEx controls wort pump
    • pre-Mash OFF
    • Mashing ON
    • Boil Off

The pump can be controlled manually during the whole process, so it’s like a software switch.

Let’s go through the brew step by step:


Electric Brewing

3 – kettle by BrewManiacEx


    1. Fill HLT with water
 Connect water pump input/output to HLT

After filling water and configuring the pump, start automatic process

    1. Heat Strike Water
    1. [Water pump] Recirculate HLT to HLT
    2. Set PID of HLT to 149F

PID runs on Heater of HLT, and the temperature is automatically set to 149F

Set preMash heater to Primary Heater(Heater 1)

    1. Transfer water to MLT

By [Water pump]

When temperature reaches. Controller prompt to Dough IN. Transfer the water.

    1. Doughing-in
    1. HLT PID to 149F
    2. [Water pump] recirculate HLT to HLT
    3. [wort pump] recirculate wort from MLT to HLT(coil) back to MLT
    4. Add malt when temperature is steady at 149F

Setup pump in the same way as described. Start the pumps.

Wait the temperature reaches 149F and put malt in.

Set PID when Dough-In to ON

    1. Mashing

Start timer for mashing time.

Press “OK” for “Add Malt” prompt. The timer starts automatically when temperature reaches 149F.

Set Mashing heater to Primary Heater(Heater 1)

    1. Mash out

Rise PID of HLT to mashout temperature

Mashout temperature will be set when desired rest time expires.

    1. Sparge
    1. [wort pump] transfer wort from MLT to BK
    2. [waer pump] transfer water from HLT to MLT
    3. All PID off.

When mashout time strikes count, controller will prompt “Remove Malt”. Use the pump to transfer wort/water as described.

When it’s time to start heating of BK, press “OK”.(The wort should at least cover heating element in BK.)

 PID removing malt is set to OFF. Elements are off.

    1. Boil

Manual PID (PWM) of BK

In boil mode, the heating power is full on until boil temperature reaches.

Set Boil heater to Secondary Heater(Heater 2)

    1. (Post Boil)

Use heating element in BK if required.

I am not going to say that BrewManiacEx supports 3-kettle system, but it seems applicable.

Adding one more relay control for the pump is not difficult, but it complicated the user interface. Moreover, the user still need to manually control it because there is no sensor to detect the level of water/wort. I don’t see the advantages over mechanical button, except wireless control( which I really don’t recommend).

Any opinions?

Support of Hop Stands

Hop stands or Post-Boil Hops Additions is gaining popularity along with NEIPA. It should be convenient to have a controller that can help counting time and maintaining the temperature when necessary.


The illustration shows three hop additions in two temperature sessions. Let T1=85C, T2=60C, D1=30min, D2=20min, D3=30C for better illustration.

After boiling finishes, the controller prompts for wort chilling to 85C(T1). When 85CT1 is reached, it alarms and starts the PID to control the wort at 85C(T1). After 10 minutes, the controller alarms for the addition of Hop2, and prompts for chilling after 20 minutes more.

That is a perfect way to use hop stand, and it makes it possible to calculate a more precise IBU. However, cooling wort takes time and water. Heating the to-be-cooled wort does not seems right, and the “precise” IBU is not really precise. It might make no difference between 88C and 85C. Using a range of temperature instead of a exact temperate might save time, water, and energy.


This illustration shows a more common and easy way to use hop stands. Hop1 is added when T1(90) is reached, the wort is not temperature controlled unless necessary(the lower line under T1). If the lower bound is set to 80C, the heating might never be activated if you brew indoors.

It is a little more complicated to specify a range instead of a temperature, but it provides the flexibility. By specifying the same start and keep temperature, it will be exact the first scenario.


Please share your opinions.

BrewManiacEx v0.2.3 Release

Bugs Fixed

  • PWM display for multiple sensors.
  • Resumption after boil phase.


  • If PID is used during Malt-in., the setting temperature is set to the temperature of Mash-in.
  • Pump access during Adding Malt. The “No” option during “Add Malt” is moved to “Temperature Reached” screen of Mash-In. (It was only “Yes”.)
  • Full version label is displayed.

Everything in v0.2.2[preview] is included.

Some thought about temperature control in Kettle-RIMS

I know nothing about kettle-RIMS until Abel Ribeiro and  mojonojo mentioned about it.

It was a coincidence that I saw people discussing this setup on HBT soon after that. After roughly surveying LODO(Low oxygen brewing), my interest about K-RIMS rises.

Can BrewManiacEx support K-RIMS? Why not? If we move out the malt pipe of Grainfather, add a solid bottom and a drain, and then call the new malt pipe MLT. We are turning a Grainfather into a K-RIMS. BrewManiacEx works even better because we can use two temperature probes to monitor BK and MLT at the same time.

IMO, the most advantage compared to E-BIAB is that K-RIMS avoids the splash during lifting malt pipe or the bag.(Saving a pulley system should be another one if you brew big batch.)

The most disadvantage, except the lower efficiency of non-sparging nature, is the temperature difference between two kettles. The separation of two kettles will make the temperature difference bigger than the Grainfather.

I have been thinking about using the probe inside grain pipe (that would be MLT temperature for K-RIMS system)  as the PID input during mashing on Grainfahter. However, I am concerning the temperature of wort at the bottle of the kettle( BK for K-RIMS). I am not sure how high it will rise when the temperature of mash rises slowly because of solid grain bed.

A solution I come out is to limit the temperature of BK(or the reading of probe inside kettle) while using the temperature of MLT(or the probe inside the malt pipe) as PID input. The AUXiliary temperature will be limited by a maximum valve or a maximum difference to mashing temperature.

How do you think?



My concern about temperature difference issue was relived by a simple fact:

The enzyme exists in the LIQUID part, not the solid part. 

It means that the temperature of the liquid is the temperate needs to be controlled. Sure, it is better to have consistent temperature, but if it is not possible, the temperature of liquid part is what we need to take care of.

PID, PWM, and Doughing-In temperature

This is to clarify the time when PID or PWM is applied.


There are a few settings involved:

  • PID Start
    It specify when PID is applied. Before PID is applied, the heat is fully output.
  • PID Active/Passive
    If PID is applied during Doughing-In(Malt In), which is the duration you put the malt into the kettle.
  • Boiling Temperature
    PWM is applied after the temperature is higher than BOIL temperature and Setting Temperature. ( Yes, during boiling stage, there is a changeable setting temperature.)

One thing worths discussing is “Mash-In” temperature and the temperature during “Doughing-In”.


The picture above showing the condition that “Mash-in” temperature is used as “striking temperature‘, which is set a little bit higher than the first rest temperature. Because the temperature of grain is usually lower, mixing the grain with water at higher temperature will get the mash at a lower temperature, right on the first rest rest temperature.

Some people use “Mash-In” temperature in other way, in which the Mash-In temperature is lower than the temperature of first rest. For example, mash-in at 45C, and then rise temperature to first rest, e.g. 55C.


In normal condition, the temperature of mash after adding malt should be lower than the mash-in temperature.

If PID is used(PID Active), what temperature should it keep? Mash-in or Mash rest 1?

In the case of using Mash-in temperature as striking temperature, if the striking temperature is correctly and precisely calculated, the heating should be turned off during the time malt is added since the drop of temperature is already considered and expected. If PID should be used, the desired temperature should be Mash rest 1, which is the temperature we try to get.

When a lower mash-in temperature is used, the desired mash temperature should be the mash-in temperature.

Prior to v0.2, the temperature during Doughing-in is PID controlled and the temperature is set to Mash-In temperature. After v0.2.1, the option to enable or disable PID was added and Mash rest 1 temperature is used if PID is enabled.

After above discussion, I am thinking to change the setting temperature to Mash-In temperature during doughing-in if PID is enabled. Then, for people who use higher mash-in temperature as striking temperature can set PID off to get desired first rest temperature. People who use lower mash-in temperature can set PID ON to get the mash-in temperature.

Please share your opinions, if any.

BrewManiacEx Release v0.2.2[preview]

New features

  • Extended Mash Rest
    • When decoction mashing is used or conversion doesn’t finished, it provides the option to extend the mash rest after the time runs out.
    • During the mashing rest, long press STP(Enter) will bring a new option “Extend”(Up). Press the button to toggle extended mash. A “+” symbol will appear at the first line of LCD, indicating extended mash. The other two options is “Skip”(Start) and “Back”(Enter). “Skip”(Start) is used to skip current rest step and goto next step, while pressing “Back”(Enter) will result in returning to current rest step.
    • When the time of the rest counts to zero, it will start to count UP if extended mash is enabled. During extended mashing, STP(Enter) can be used to finish current mash rest step.
  • Paddle stirring instead of Pump recirculating (supported by compile option)
    • change the UsePaddleInsteadOfPump to true at line 38 in config.h

      #define UsePaddleInsteadOfPump true
    • Differences from PUMP
      • no “pump priming” at the start of automatic mode
      • The unit of Pump(stir) Rest/Pump(stir) cycle is second instead of minute
      • Heating control(PID) is not turned off during “Stir Rest”
      • ‘stir’ is used in place of ‘pump’ for button labels.

Bug fixed

  • Error updating automation/settings
    • caused by misuse of ArduinoJSON library
  • Error handling of Fahrenheit
    • Now the data is saved in its own unit. The down side is that temperature related settings must be set after temperature unit is changed.

Other changes

  • In manual mode, “Pump”(Stir) rest can be enabled by long pressing of “Pump/Stir” button
  • There will be no “–Pump Rest–” as button label when pump rests. During pump rest, the buttons are still accessible.

The release is temporarily available at preview branch at GitHub. It will be pushed to master branch after I use it in a real brew.

BrewManiacEx Release 0.2.1

  • Add “PID when Doughing-in” option in “PID-PWM” setting.
    • If it is set to “NO”, the heater will be turned off after temperature reached and “Continue? OK” is confirmed, before “Mash-in OK” is pressed.
    • If “YES”, the PID will be applied during doughing in, the setting temperature will be the temperature of first mash rest.
  • Add Plato/Gravity for recipe viewing
  • Add kettle thermal mass option
    • expressed in equivalence water amount

Mashing temperature, PID tuning, and wort circulation.

This is about my recently finding and thought about mashing temperature measure and control in recirculated E-BIAB.

Here is two typical designs of recirculated E-BIAB kettles. The main difference between them is the direction of wort circulation.

A. Top-down, eg. Grainfather.


B. Bottom-up. eg. Braumeister


I don’t have any experience with Braumeister or the like. My issues are about the design of Grainfather. My conclusion is that Braumeister might have a better design, and if you are going to build your own brew kettle, go with design B, the bottom-up method.

The issue wasn’t clear to me until I drew the picture: the design of Grainfather creates 3 zones of wort/mash.

When the wort drains down, a compact grain bed will be formed, which results in slow draining from middle part to the bottom. If the mash is mixed well when doughing in and the heat didn’t lose too much, it might be fine. However, it is a different story when multiple rest steps are needed because

the main sensor and the heater are at the bottom and the flow from middle part to bottom part is slow. The result is slow temperature ramp of the mash in the middle.

Conducting thin mash or add rice husks can speed up the wort draining but result in fast sparge.

The temperature of top portion can be risen quickly if the flow of wort is quick and drains through the overflow pipe.

I have been wondering why the PID parameters tuned with 2 gallon water worked “better” than that with 4.5 gallon water. Now it’s all clear to me: the PID was effectively controlling sound 2 gallon of wort.

Here are some charts. FYI.

I forget to switch the heater to “mash” position. The PID was tuned with 4(or 4.5) gallons of water.


The heater was switched to “mash” position. The PID was tuned with 4 gallons of water (same as above.)


The PID parameters were derived from tuning with 2 gallons of water.



Mash-in/Dough-in temperature

The following change will be available on next release

  • Kettle(equipement) thermal mass for more precise calculation
  • A setting to specify if temperature control(PID) is applied during doughing-in, which is the time you put malt into kettle. The calculated Mash-In temperature will not work as expected in current release.

TL;DR part 1:

The calculation of strike water temperature is easy if we simplify the model.

Grain at Tg, water at Tw, and target temperature is Tm.

The mash, mix of grain and water, will be at final temperature Tm.

The heat absorbed by grain is (TmTg)* [Grain weight] * [grain heat capacity].

The heat loss of water is (TwTm) * [water amount].

Assuming no heat is lost, in a simplified world, the heat is perfectly transferred from water to grain. Make a equation of these two terms will derive the formula that is the same as Palmer’s.

But, Wait, there are other objects in the “system”: the kettle. Because the kettle is heated with water, it is the heat-loss side. The relative idea formula should be added a term like grain: (Tw – Tm) * [kettle thermal mass]. This term can be simplified as “equipment adjustment“. Using [kettle thermal mass] should be more precise.

If you know the value of [kettle thermal mass] in your system, or you know how to get it. That would be a better option.

TL;DR part 2:

I used to use the first rest temperature as Mash-In temperature because I thought that the temperature should recover in a short time. Of course, the more precise the better. Using a calculated temperature to get exact the first rest temperature might be desired. There is a problem here: should we control the temperature during doughing-in? In original Open ArdBir, there’s a setting for it, which is the PID Pipe(Active or Passive). I thought it was unnecessary and just implemented it as active. That is, PID is applied during doughing-in. If the Mash-In temperature is the same as first rest temperature, it is fine. However, if the Mash-In temperature is calculated by the formula which assumes a CLOSED system, then the equation is broken and the result might not be as expected. It might be fine if the setting temperature is the same as the first rest. In this case, PID algorithm won’t turned the heating element if the temperature is greater than setting temperature. However, in current release, the setting temperature during doughing-in is the Mash-In temperature. Therefore, the calculated Mash-In temperature will not work as expected. This will be fixed as well.