PID Control
Why would a home-brewer need a separate page just on control engineering? If you have a RIMS / HERMS brewing setup and you buy a neat little box that does all the tricks, why bother with PID control?As a home-brewer you have to understand a little how PID control works, because you can easily end up with a non-optimum PID controller, which causes significant temperature overshoots or very slow responses.
Suppose you think that you can do without PID control, you just switch off the heater when the temperature has reached its value. What happens in this situation is that the temperature in your setup continues to rise significantly. So you end up with a large overshoot. The heater should be switched off gradually, long before the final temperature is reached. That is where a controller comes in and the PID controller is the most common used one.
PID stands for Proportional, Integral and Derivative. If you look at the insides of a PID controller, you see that it indeed consists of three paths.
It used to be very common to build such a PID controller with discrete electronics, but nowadays every PID controller is realised in software, making it a digital PID controller.
Such a digital PID controller is contained in the ready-for-use devices that you can buy. And if you have read this page, you understand that it is a high price to pay for only a few lines of code (so building your own PID controller can be rewarding).
In the remainder of this page I will try to explain the following items:
- 1. PID Control Basics: some basic theory on PID control
- 2. Implementation of a PID controller: a real PID controller with C source code
- 3. Tuning the PID controller: finding the optimum parameters for your brewing system.
This paragraph consists of the following sub-paragraphs:
1. PID Control Basics
The key parts of a PID control loop are shown in the figure below.
The Proportional-Integral-Derivative (PID) algorithm is widely used in process control. The PID method of control adapts well to electronic solutions, whether implemented in analogue or digital (CPU) components. The brewing program implements the PID equations digitally by solving the basic equations in software.
Basically, there are two types of PID controls:
Another important feature of a control loop is whether it is a direct-acting loop or a reverse-acting loop:
In the figure shown above, three parallel paths were shown in the PID-loop calculation block:

The P, I and D terms work together as a team. To be able to control these terms, each term has a programmable gain:
There is one more remark to make about the type of PID controller (for details and more background, please read the PID controller Calculus document with full C source):
Back to the Top of the Page
2. Implementation of a PID controller
Many different implementations are possible. In fact, every modern PLC may have a different implementation of a PID controller, which makes things confusing.Deriving a form suitable for implementation requires a lot of Calculus. I did all this, so if you are really looking for a derivation of the PID controller implementation given here, together with the full C source code (so you can directly build your own controller), please read this document: PID Controller Calculus with full C source code.
However, if you are not really into math and you are only interested in an actual implementation, so that you can use this in your own software, then read this paragraph. The document also contains the full C source for the PID controllers.
Here, we will be using a PID velocity algorithm of Type A, which is direct-acting and has filtering of the D-action. The figure below shows a pseudo-code listing (although it is quite close to the real C implementation). This figure makes it easy (I hope) to transform the code to your own favourite programming language (the green lines of text are comments). Based on this example, it is relatively easy to make this into a 'real' Takahashi type C PID controller.
There are a few remarks to make about this implementation:
Please let me know if you find this listing easy or difficult to read. I would be interested to hear about it.
Before the first call to this function, it should be initialised. For this reason, I created a pid_init() function, that calculates the value of the necessary constants. If you observe the PID controller closely, you can see various improvements. For example: the I-term calculates the value of Kc * Ts / Ti every time again. This is not necessary, because you can calculate this once in the pid_init() function and then use it in the PID controller function (saves computing time).
Back to the Top of the Page
3. Tuning the PID controller
Tuning the PID controller means finding values for Kc, Ti and Td, such that the PID controller responds quickly to changes in setpoint value and/or temperature, while minimising any overshoot in temperature.Tuning a PID controller is always necessary, even if you bought a ready-to-use PID controller. The advantage of such a ready-to-use PID controller is that they contain an auto-setup function, which finds the optimum values automatically for you (well, most of the time).
But even such a ready-to-use PID controller uses the same algorithms as the ones I describe here. So this information might also be useful to you if you did not create your own PID controller, but bought one.
In order to understand the specific measurements which we are about to do, some terms and definitions have to be explained:
Stated in a formula: a = change in temperature divided by time-interval divided by PID controller output.
3.1 Determine Dead-Time and normalized slope of the HLT system
Manually set the PID-controller output to a certain value (e.g. 20 %). In case of a heavy load, 100 % is recommended (more accurate), but if you do not know the performance of the system, a lower value to start with is better. The temperature starts to increase and follows the following curve:
After doing this experiment with my HLT system (90 L of water, no lid on the pan, controller output set to 100 %, heating element only), combined with some regression analysis (for more accuracy), I found out that the dead-time for my HLT system is equal to 115 seconds.
During the experiment, the temperature change was 0.4 °C per minute when the PID controller output was set to 100 %. The normalized slope a is therefore equal to 0.004 °C / (%.minute) or 6.68E-5 °C/(%.s).
BUT... since I switched over to gas-burners, and more recently, to a new HLT kettle, I may have to do this experiment again!.
3.2 Determine Time-Constant of the HLT system
Because of the large time-constant presumably present in the HLT system, the previous experiment is not very accurate in determining the dead-time as well. This is the mean reason to conduct two experiments (theoretically, the step-response would give you all the required information to determine the three parameters).Manually set the PID-controller output to a certain value (e.g. 20 %). The temperature starts to increase and follows the following curve:

The difference with the previous experiment is that we let the PID controller settle, meaning that the HLT temperature will converge to a new value (in my experiment, this took a complete day, because I wanted it as reliable as possible).
After doing this experiment with my HLT system (90 L of water, no lid on the pan, controller output set to 20 %, heating element only), I collected the following data:
3.3 Calculate the Optimum values for the PID controller (Kc, Ti and Td)
A summary of the results from the two experiments for my particular HLT system:- Dead-Time TD = 115 seconds
- Normalized slope a = 6.68E-5 °C/(%.s).
- Gain (K) = 1.69 °C / %.
- Time-constant (tau) = tau = 14961 seconds.
The algorithms are:
- Ziegler-Nichols Open Loop
- Ziegler-Nichols Closed Loop
- Cohen-Coon
- Integral of Time weighted Absolute Error (ITAE-Load): this algorithm normally gives the best results. The error signal is minimized over time.
- Ziegler-Nichols Open Loop:
PID Kc [%/(°C)] Ti [sec.] Td [sec.] 1.2 / (TD * a) 2.0 * TD 0.5 * TD
PI-only, No D term Kc [%/(°C)] Ti [sec.] 0.9 / (TD * a) 3.33 * TD
- Ziegler-Nichols Closed Loop:
PID Kc [%/(°C)] Ti [sec.] Td [sec.] (1.2 * tau) / (K * TD) 2.0 * TD 0.5 * TD
PI-only, No D term Kc [%/(°C)] Ti [sec.] (0.9 * tau) / (K * TD) 3.33 * TD
- Cohen-Coon:
PID Kc [%/(°C)] Ti [sec.] Td [sec.] (tau / (K * TD)) *
(TD / (4 * tau) + 4 / 3)TD * (32 * tau + 6 * TD) /
(13 * tau + 8 * TD)4 * TD * tau /
(2 * TD + 11 * tau)
PI-only, No D term Kc [%/(°C)] Ti [sec.] (tau / (K * TD)) *
(TD / (12 * tau) + 9 / 10)TD * ((30 * tau + 3 * TD) /
(9 * tau + 20 * TD))
- Integral of Time weighted Absolute Error (ITAE-Load): this algorithm normally gives the best results. The error signal is minimized over time.
PID Kc [%/(°C)] Ti [sec.] Td [sec.] (1.357 / K) *
[(TD / tau)^-0.947](tau / 0.842) *
[(TD / tau)^0.738](0.381 * tau * [(TD / tau)^0.995]
PI-only, No D term Kc [%/(°C)] Ti [sec.] (0.859 / K) *
[(TD / tau)^-0.977](tau / 0.674) *
[(TD / tau)^0.680]
| Numeric values | |||
| Algorithm | Kc [%/(°C)] | Ti [sec.] | Td [sec.] |
| Ziegler-Nichols Open Loop |
156.2 | 230.0 | 57.5 |
| 117.2 | 383.0 | ||
| Ziegler-Nichols Closed Loop |
92.4 | 230.0 | 57.5 |
| 69.3 | 383.0 | ||
| Cohen-Coon | 102.8 | 282.3 | 41.8 |
| 69.4 | 377.2 | ||
| ITAE-Load | 80.8 | 489.0 | 44.9 |
| 59.2 | 810.2 | ||
I tried all these solutions in my HLT system and all of them gave good results. I found out that the D term was quite sensitive, especially with the ITAE-Load values. therefore I reduced the D-term and applied some more filtering (the low-pass filter time-constant was set to 10).
See How does it work? for a graph showing the performance of the PID-controller (at the bottom of that page).
After all this work, I am beginning to understand how the PID controller does its work in relation with my HLT system. Needless to say is that I am very happy with the performance of this PID controller.
It is funny to see that designing all this took several months, but that the actual implementation is only a couple of lines of code.
Not everything was written by myself. I found some excellent sources that explain some of the details I gave on this page:
If you have an interest in building your own PID controller, after having read this page, check out the page PID Do-it-Yourself. This page shows the complete design, implementation and test of such a PID controller, including all schematics and software.
Back to the Top of the Page