In the previous guide (here), the PID controller has been introduced and discussed. This part, we shall use the equation introduced in part 1 to implement the code.
In this guide, we shall cover the following:
- Header file implementation.
- Source file implementation.
- Main implementation.
1. Header File Implementation:
To start off, create a new header file with name of pid.h.
Inside this header file, we shall use header guard as following:
#ifndef PID_H_ #define PID_H_ #endif /* PID_H_ */
Then we create a data structure with the following parameters:
- Kp
- Ki
- Kd
- Ts
- Set_point
- Anti_windup_error
- Out_max
- Out_min
- Anit_windup
the structure shall be like this:
typedef struct { float Kp; float Ki; float Kd; float Ts; float Set_point; float Anti_windup_error; float Outmin; float Outmax; int Anti_windup; }PID_Param_t;
Also the header file shall contain the initialization function and compute function as following:
void PID_init(PID_Param_t *par); float PID_Calculation(float input);
Thats all for the header file.
2. Source File Implementation:
To start off, create a new source file with name of pid.c and include the pid.h file as following:
#include "pid.h"
We need some global variable as following:
float Kp,Ki,Kd,Ts,Outmin,Outmax,set_point,antiwinduperror; int windup; float error,prev_input,error_sum;
Those variable are only accessed in the source file
For the initialization function, the declared variable are set according to the values stored in the structure as following:
void PID_init(PID_Param_t *par) { ; Kp=par->Kp; Ki=par->Ki; Kd=par->Kd; Ts=par->Ts; set_point=par->Set_point; antiwinduperror=par->Anti_windup_error; Outmin=par->Outmin; Outmax=par->Outmax; windup=par->Anti_windup; if(0==par->Anti_windup_error){antiwinduperror=10;} }
Now, for the calculation:
float PID_Calculation(float input) { error=(set_point-input); float out; if(Anti_windup_enabled==windup) { if(antiwinduperror<abs(error)) { out=Kp*(error)+Kd*(input-prev_input)/Ts; } else { out=(Kp*(error)) +( Ki*(Ki_sum)*Ts) -( Kd*(input-prev_input)/Ts); } } else { out=Kp*(error) + Ki*(Ki_sum)*Ts - Kd*(input-prev_input)/Ts; } Ki_sum=Ki_sum+(Ki_sum); if(out>Outmax){out=Outmax;} if(out<Outmin){out=Outmin;} prev_input=input; return out; }
First, the error calculation:
error=input-set_point;
Accumulate the error for the integrator part:
error_sum+=error;
Check if the error is bigger than the output max and less than output minimum as following:
if(error_sum<Outmin){error_sum=Outmin;} if(error_sum>Outmax){error_sum=Outmax;}
For the calculation, we have two paths, first one if the anti windup is enabled:
This will have two condition:
If the error bigger than what the anti windup set point, the calculation shall not include the integrator part:
if(antiwinduperror<abs(error)) { *output=Kp*(error)+Kd*(input-prev_input)/Ts; }
If the error is less, calculate with integrator part :
else { *output=Kp*(error) + Ki*(error_sum)*Ts - Kd*(input-prev_input)/Ts; }
If the ani windup is not active, calculate the PID out as usual:
else { *output=Kp*(error) + Ki*(error_sum)*Ts - Kd*(input-prev_input)/Ts; }
Also, store the previous input for the differential part:
prev_input=input;
3. Main Implementation:
For the main source file, we shall first include the header file following:
#include "pid.h"
Then declare the structure of the PID parameters as following:
PID_Param_t PIDParam;
Set the PID parameters as following:
PIDParam.Kp=15.2; PIDParam.Kd=0.3; PIDParam.Ki=0.001; PIDParam.Outmin=0; PIDParam.Outmax=1000; PIDParam.Ts=200; PIDParam.Set_point=200; PIDParam.Anti_windup=Anti_windup_enabled; PIDParam.Anti_windup_error=10;
Note: those are not actual parameters, just for demonstration only .
Then pass the address of the structure to the PID_init function as following:
PID_init(&PIDParam);
The compute_pid function shall be called according the sample time stated in the structure:
if(millis()-previous>PIDParam->Ts) { PID_Calculation(input, &output); previous=millis(); }
In part three, we shall see how to use PID in simple application
Happy coding 🙂
2 Comments
Where is part 3?
We shall post part three soon.
Add Comment