
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