HERMS PID Controller Guide
HERMS PID Controller Guide
1. Introduction
This document describes the derivation of a PID controller that can be implemented in the brew
application. The PID controller should be capable of controlling the temperature of the Hot
Liquid Tun (HLT, 90 L) to within 0.5 °C.
The HLT contains a heating element of 3 kW, which is driven by the PID controller output signal
Gamma [0..10 %]. The HLT temperature sensor is a LM92 12 bit + sign bit, ± 0.33°C accurate
temperature sensor.
y(t)
The generic equation1 for a PID controller in the time-continuous domain is:
1 de(t )
Ti ∫
u (t ) = K c . e(t ) + e (τ ) d τ + Td . eq. 01
dt
U ( s) 1
= K c .1 + + Td .s eq. 02
E (s)
Ti .s
This transfer function has no real practical use, since the gain is increased as the frequency
increases. Practical PID controllers limit this high frequency gain, using a first order low-pass
filter. This results in the following transfer function:
1
This is the ideal, textbook version of a continuous-time PID controller. See [1], page 54.
U (s) 1 T .s
1 Td
= K c .1 + + d = K c .1 + + eq. 03
E (s)
Ti .s γ .s + 1
Ti .s γ + s −1
where γ is a small time-constant and may be set as 10% of the value of the derivative term Td.
Equation eq. 03 needs to transferred to the Z domain to make it suitable for implementation on a
computer. This is done using the bilinear transformation (given in eq. 04):
2 1 − z −1
The bilinear transformation formula is given with: s = . eq. 04
Ts 1 + z −1
Now use the bilinear transformation, given in equation eq. 04, to transform equation eq.
03 onto an equivalent form in the Z –domain:
U ( z) T 1 + z −1 (
Td . 1 − z −1 )
= K c .1 + s . −1
+ eq.05-1
E( z) 2.Ti 1 − z T
( 2
)
γ . 1 − z −1 + s . 1 + z −1 ( )
U ( z) Ts 1 + z −1 2.Td 1 − z −1
= Kc . 1 + . + . eq.05-3
E( z) 2.Ti 1 − z −1 Ts + 2.γ T − 2.γ
1 + z −1. s
Ts + 2.γ
Rewrite equation eq.05-4 and combine all parts of z-1 and z-2 with each other:
1 + z −1. Ts − 2γ − z −1 − z −2 . Ts − 2γ + Ts .1 + z −1 . Ts − 2γ + z −1 + z −2 . Ts − 2γ + 2Td . 1 − 2 z −1 + z −2
Ts + 2γ Ts + 2γ
( )
U ( z) Ts + 2γ Ts + 2γ 2Ti Ts + 2γ
= K c .
E( z) T − 2.γ T − 2.γ
1 + z −1 . s − z −1 − z −2 . s
Ts + 2.γ Ts + 2.γ
... eq.05-5
Ts2 Ts .(Ts − 2γ )
− 4γ − 4Td 2γ − Ts + + 2Td
Ts 2Td −1 Ti + z −2 . 2.Ti
1 + 2T + T + 2γ + z . T + 2γ Ts + 2γ
i s
s
U ( z)
= K c . (eq.05-6)
E( z) 4γ T − 2γ
1 − z −1. − z −2 . s
Ts + 2γ Ts + 2γ
( ) (
U ( z ). 1 − p1.z −1 − p2 .z −2 = E ( z ). k0 + k1.z −1 + k2 .z −2 ) (eq. 07)
Equation eq.08 is implemented with pid_reg2() and eq.07 is implemented with init_pid2() (see
appendix for full C source listing).
Starting with equation 01 and differentiating both sides gives equation eq. 09
e(t ) d 2e(t )
du (t ) = K c . de(t ) + + Td . (eq. 09)
Ti dt
The D-term needs to be filtered with a Low-Pass Filter (LPF) to make it more practical. The
transfer function of a simple LPF is given with:
1
H (s) = , with γ typically set to about 10% of the Td value. (eq.11a)
γ .s + 1
H ( z) =
( )
Ts . 1 + z −1
=
Ts
.
1 + z −1
(eq.11b)
( ) ( )
2.γ . 1 − z −1 + Ts . 1 + z −1 Ts + 2.γ 1 + Ts − 2.γ .z −1
Ts + 2.γ
2.γ − Ts Ts
lpf k= .lpf k −1 + .(ek + ek −1 ) (eq.11c)
2.γ + Ts Ts + 2.γ
Equation 12 is still a type A equation (“textbook PID”), because the Kc term depends on ek and
the input of the LPF also has ek as input. Equation eq.11c and eq.12 are implemented with
pid_reg3() and with init_pid3() (see appendix for full C source listing).
Because it is not easy to transform this equation into a full type C controller (because of the
addition in eq.11c), we will revert to equation eq.10 and transform this equation into a type C
equation (eq. 13):
T .e T
uk = uk −1 + K c .(ek − ek −1 ) + s k + d .(ek − 2.ek −1 + ek −2 ) (eq .10)
Ti Ts
T .e T (eq .13)
u k = u k −1 + K c .SPk − PVk − (SPk −1 − PVk −1 ) + s k + d .(SPk − PVk − 2.(SPk −1 − PVk −1 ) + SPk −2 − PVk −2 )
T i T s
Here, PV is the process variable, which is Thlt (the actual temperature of the HLT). Furthermore
SP is the set-point or the reference temperature.
If we assume that the set-point is not changed, we can state the PVk = PVk-1 = PVk-2. With this,
the equation transforms into:
T .e T
u k = uk −1 + K c .(PVk −1 − PVk ) + s k + d .(2.PVk −1 − PVk − PVk −2 ) (eq .14)
Ti Ts
Equation 14 is a type C PID controller and normally referred to as a Takahaski PID controller.
This equation is implemented with pid_reg4() and with init_pid4() (see appendix for full C
source listing).
Three well-known algorithms for determining the PID parameters are described here:
• Ziegler-Nichols open-loop: set PID controller to a certain output and determine slope
and dead-time of HLT system
• Ziegler-Nichols closed-loop: measure step-response
• Cohen-Coon: also a closed-loop method. Measure step-response
• Integral of the time weighted absolute error (ITAE): results in the best performance. The error
signal is minimised (over time).
With these three parameters, the optimum PID parameters are determined using table 1 on the
next page (values are given both for PID operation and for PI-only operation):
To be able to find these three parameters accurately, two experiments need to be conducted.
These two experiments are described in the next two paragraphs.
The last paragraph (§ 4.3) shows the calculated PID parameters for all these methods.
Calculate the average slope of the rise (a = ∆T / ∆t) by using regression analysis if possible.
Calculate the normalised slope a*, which is defined as: a* = a / ∆p.
The dead-time Θ is defined as the time between t0 and t1 (by using regression analysis, this can
be done quite accurately).
Regression analysis of the data between 19 :12 :25 and 19:27 :21 resulted in the following:
y = a.x + b = 0,0334x + 48,278 R2 = 0,9995
Here, every data-point for x represents 5 seconds. Therefore, the average slope a is equal to:
a = 0,0334 °C / 5 sec. = 6,68E-03 °C/second (which is 0,4 °C/minute)
Now solve where this curve hits the Tenv line:
2
Measurements are recorded in HLT_open_loop_response_260404.xls
Because of the large time-constant presumably present in the HLT system, the step response is
not very accurate in determining the dead-time Θ. 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).
3
Measurements are recorded in HLT_step_response_290404.xls
Referenced Documents
Referenced documents
Version Date Title: Author Tag
2005 “Digital Self-Tuning Controllers”, V. Bobál, J. [01]
ISBN 1-85233-980-2, Springer Böhm, J.
Fessl, J.
Machácek
Version History
Date Version Description
01-02-2003 V1.0 First version for display on web-site
08-03-2004 V2.0 - Removed implementation 1 and 3
- Added description of types A, B and C
- Added type C PID algorithm
- Added auto-tuning algorithm + example
10-03-2004 V2.1 Incorrect dead-time calculation
09-05-2004 V2.2 - Added Cohen-Coon + ITAE methods
- Added two experiments + description
- Calculations are updated
10-05-2004 V3.0 - Derivation with Taylor series replaced by exact derivation. Current
implementation worked well, but simulation showed problems
13-05-2004 V3.01 - Update of document, corrected a few mistakes
- Add low-pass filter to the D-term of the PID-controllers
13-05-2004 V3.02 Some textual changes
09-05-2006 V3.03 Error corrected in equation eq.09
26-02-2007 V3.10 - Referenced documents added
- Typo corrected in eq.08
- Block diagram added
- Source code shortened, non-relevant code removed
- More consistent naming of variables
- More elaborate derivation in chapter 2.
06-05-2011 V3.20 - Better derivation for pid_reg3() and pid_reg4(). Pid_reg3() is now a
type A PID controller with filtering of the D-action. Pid_reg4() is now
a pure Takahashi type C PID controller.
#ifdef __cplusplus
extern "C" {
#endif
// These defines are needed for loop timing and PID controller timing
#define TWENTY_SECONDS (400)
#define TEN_SECONDS (200)
#define FIVE_SECONDS (100)
#define ONE_SECOND (20)
#define T_50MSEC (50) // Period time of TTimer in msec.
//--------------------
// Function Prototypes
//--------------------
void init_pid2(pid_params *p);
void pid_reg2(double xk, double *yk, double tset, pid_params *p, int vrg);
void init_pid3(pid_params *p);
void pid_reg3(double xk, double *yk, double tset, pid_params *p, int vrg);
void init_pid4(pid_params *p);
void pid_reg4(double xk, double *yk, double tset, pid_params *p, int vrg);
#ifdef __cplusplus
};
#endif
#endif
/*==================================================================
Function name: init_pid2(), pid_reg2()
init_pid3(), pid_reg3(), init_pid4(), pid_reg4()
Author : E. vd Logt
File name : $Id: pid_reg.c,v 1.6 2004/05/13 20:51:00 emile Exp $
------------------------------------------------------------------
Purpose : This file contains the main body of the PID controller.
For design details, please read the Word document
"PID Controller Calculus".
Ts 2.Td
k0 = Kc.(1 + ---- + ------------)
2.Ti Ts + 2.k_lpf
void pid_reg2(double xk, double *yk, double tset, pid_params *p, int vrg)
/*------------------------------------------------------------------
Purpose : This function implements the updated PID controller.
It is an update of pid_reg1(), derived with Bilinear
Transformation. It is a Type A controller.
This function should be called once every TS seconds.
Variables:
xk : The input variable x[k] (= measured temperature)
*yk : The output variable y[k] (= gamma value for power electronics)
Kc.Ts
k0 = ----- (for I-term)
Ti
Td
k1 = Kc . -- (for D-term)
Ts
void pid_reg3(double xk, double *yk, double tset, pid_params *p, int vrg)
/*------------------------------------------------------------------
Purpose : This function implements the type Allen Bradley Type A PID
controller. All terms are dependent on the error signal e[k].
The D term is also low-pass filtered.
This function should be called once every TS seconds.
Variables:
xk : The input variable x[k] (= measured temperature)
*yk : The output variable y[k] (= gamma value for power electronics)
tset : The setpoint value for the temperature
*p : Pointer to struct containing PID parameters
vrg: Release signal: 1 = Start control, 0 = disable PID controller
Returns : No values are returned
------------------------------------------------------------------*/
{
if (vrg)
{
//-----------------------------------------------------------
// Calculate PID controller:
// y[k] = y[k-1] + Kc*(e[k] - e[k-1] +
// Ts*e[k]/Ti +
// Td/Ts*(lpf[k] - 2*lpf[k-1]+lpf[k-2]))
//-----------------------------------------------------------
p->pp = p->kc * (ek - ek_1); // y[k] = y[k-1] + Kc*(e[k] - e[k-1])
p->pi = p->k0 * ek; // + Kc*Ts/Ti * e[k]
p->pd = p->k1 * (lpf - 2.0 * lpf_1 + lpf_2);
*yk += p->pp + p->pi + p->pd;
}
else *yk = 0.0;
void pid_reg4(double xk, double *yk, double tset, pid_params *p, int vrg)
/*------------------------------------------------------------------
Purpose : This function implements the Takahashi PID controller,
which is a type C controller: the P and D term are no
longer dependent on the set-point, only on PV (which is Thlt).
The D term is NOT low-pass filtered.
This function should be called once every TS seconds.
Variables:
xk : The input variable x[k] (= measured temperature)
*yk : The output variable y[k] (= gamma value for power electronics)
tset : The setpoint value for the temperature
*p : Pointer to struct containing PID parameters
vrg: Release signal: 1 = Start control, 0 = disable PID controller
Returns : No values are returned
------------------------------------------------------------------*/
{
double ek; // e[k]
double lpf; //LPF output
if (vrg)
{
//-----------------------------------------------------------
// Calculate PID controller:
// y[k] = y[k-1] + Kc*(PV[k-1] - PV[k] +
// Ts*e[k]/Ti +
// Td/Ts*(2*PV[k-1] - PV[k] - PV[k-2]))
//-----------------------------------------------------------
p->pp = p->kc * (xk_1 - xk); // y[k] = y[k-1] + Kc*(PV[k-1] - PV[k])
p->pi = p->k0 * ek; // + Kc*Ts/Ti * e[k]
p->pd = p->k1 * (2.0 * xk_1 - xk - xk_2);
*yk += p->pp + p->pi + p->pd;
}
else { *yk = p->pp = p->pi = p->pd = 0.0; }