PID Controller

The PID controller is the main element of the oven. It controls the output of the solid state relais in order to achieve the desired temperature.

The PID controller is implemented in the pid-controller.c file. See the PID Controller Code API for details.

Functional Description

The following figure shows the PID controller’s structure.

../_images/pid.svg

The controller is composed of 3 paths. The proportional, the derivate, and the integrator path. Compared to a textbook PID controller, this version contains a few additional features.

The integrator has a configurable maximum limit of pid_controller.integral_max. Once this value is reached (plus or minus), the integrator freezes. The integrator is also frozen in case the output value is in saturation. This serves as an anti-windup protection.

The output value saturates at configurable high and low limits (pid_controller.output_sat_max and pid_controller.output_sat_min). The controller instance used for the reflow oven’s solid state relais output is saturated by software to a limit of 0 to 100.

In addition to the above features, the derivate term contains an additional first order low pass filter in order to prevent coupling of high frequency noise amplified by the derivate term. The low pass filter is charcterized by its time constant \(k_{d\tau}\).

Time Continuous Transfer Function

The time continous transfer function of the PID controller is

\[H_c(s) = \frac{Y_c(s)}{X_c(s)} = k_p + \frac{k_i}{s} + \frac{k_ds}{1+sk_{d\tau}}\]

Time Discrete Transfer Function

The time descrete transfer function which is implemented in the code is derived by converting the time continuous transfer function with the bilinear transformation:

\[s = \frac{2}{T_s}\cdot \frac{z-1}{z+1}\]

The frequency warping of the bilinear transform can be considered negligible because the PID controller is targetted for low frequency temperature signal data with a maximum far below the nyquist freqency. In this area, the mapping of the continuous frequencies to the time descrete can be considered linear.

The time discrete transfer function after inserting the bilinear transform is:

\[H_d(z) = H_c(s)\bigg|_{s=\frac{2}{T_s}\cdot \frac{z-1}{z+1}} = k_p + \frac{k_i T_s (z+1)}{2(z-1)} + \frac{\frac{2}{T_s}k_d(z-1)}{\left(1+\frac{2k_{d\tau}}{T_s}\right)z+\left(1-\frac{2k_{d\tau}}{T_s}\right)}.\]

Converted to an implementable form:

\[H_d(z) = k_p + \frac{k_iT_s(1+ z^{-1})}{2(1-z^{-1})} + \frac{\frac{2}{T_s}k_d(1-z^{-1})}{(1+2k_{d\tau}T_s^{-1})+(1-2k_{d\tau}T_s^{-1})z^{-1}}\]

This function can be splitted in the three individual parts of the PID controller:

\[H_{d1}(z) = k_p\]
\[H_{d2}(z) = \frac{k_iT_s(1+ z^{-1})}{2(1-z^{-1})}\]
\[H_{d3}(z) = \frac{\frac{2}{T_s}k_d(1-z^{-1})}{(1+2k_{d\tau}T_s^{-1})+(1-2k_{d\tau}T_s^{-1})z^{-1}}\]

The individual time domain difference equations \(y_i[n] = \mathcal{Z}^{-1}\left\lbrace H_{di} * X(z)\right\rbrace\) that are implemented in software are:

\[y_1[n] = k_p x[n]\]
\[y_2[n] = \underbrace{\frac{k_iT_s}{2}}_{k_{i_t}} \left( x[n] + x[n-1]\right) + y_2[n-1]\]
\[y_3[n] = \underbrace{\frac{2k_{d}}{2k_{d\tau} + T_s}}_{k_{d_t}}\left( x[n] - x[n-1] \right) + \underbrace{\frac{2k_{d\tau} - T_s}{2k_{d\tau} + T_s}}_{\overline{k_{d_t}}} y_3[n-1]\]

The final output value is the sum of all three terms:

\[y[n] = \sum_{i=1}^{3} y_i[n]\]

PID Controller Code API

group pid-controller

Functions

void pid_init(struct pid_controller *pid, float k_deriv, float k_int, float k_p, float output_sat_min, float output_sat_max, float integral_max, float kd_tau, float sample_period)

Initialize a pid_controller struct.

Parameters
  • pid: Struct to initilaize

  • k_deriv: Derivate term

  • k_int: integral term

  • k_p: Proportional term

  • output_sat_min: Minimum output saturation

  • output_sat_max: Maximum output saturation

  • integral_max: Maximum integral term

  • kd_tau: Time constant of derivate term low pass filter

  • sample_period: Sample time in seconds

void pid_zero(struct pid_controller *pid)

Reset a PID controller.

This sets all internal states to 0.

Parameters
  • pid: Controller

float pid_sample(struct pid_controller *pid, float deviation)

Execute a tiome step of the PID controller. This function must be periodically called in an pid_controller::sample_period interval.

Note

This function does not check its calling interval. It must be ensured by the caller.

Return

Current controller output after the calculated time step

Parameters
  • pid: Pid controller to execute

  • deviation: Input deviation

float pid_get_control_output(const struct pid_controller *pid)

Retrieve the controller’s current output.

Return

Output

Parameters
  • pid: Pid controller

int pid_copy(struct pid_controller *dest, const struct pid_controller *src)

Duplicate a PID controller.

Return

0 if successful

Parameters
  • dest: destination controller

  • src: Source controller

void calculate_integral(struct pid_controller *pid, float deviation)
struct pid_controller
#include <pid-controller.h>

Representation of a PID controller.

Public Members

float k_deriv

Derivate term \(k_d\).

float k_int

Integral term \(k_i\).

float k_p

Proportional term \(k_p\).

float k_int_t

Internally precalculated auxiliary value. \(k_{i_t} = \frac{1}{2}k_{i} \cdot T_s\).

This value is caluclated during the pid_init function to reduce calculations during the continous PID sampling.

float k_deriv_t

Internally precalculated auxiliary value. \(k_{d_t} = 2\frac{k_{d}}{T_s + 2 k_{d\tau}}\).

This value is caluclated during the pid_init function to reduce calculations during the continous PID sampling.

float k_inv_deriv_t

Internally precalculated auxiliary value. \(\overline{k_{d_t}} = \frac{2 k_{d\tau} - T_s}{ 2k_{d\tau} + T_s}\).

This value is caluclated during the pid_init function to reduce calculations during the continous PID sampling.

float output_sat_max

Saturation of output value.

Note

This value is set to 100 (corresponding to 100%) for the temperature controller

float output_sat_min

Minumum saturation of PID output value.

Note

This value is set to 0 for the temperature controller as the oven driver is not able to cool

float integral_max

Maximum value \(i_{max}\) the inegrator in the PID controller can reach.

The output of the integral term of the PID controller is limited to \(\pm i_{max}\)

float sample_period

Sampling period \(T_s\) of the PID controller in seconds.

float control_output

Output value of the PID controller.

float last_in

Internal state variable holding the last input value.

float integral

integral term’s value

float derivate

derivate term’s value