|
|
@ -1,5 +1,7 @@
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
PID regulator.
|
|
|
|
The file implements a simple PID regulator. The time resolution is
|
|
|
|
|
|
|
|
1usec. The update function should be called regularily as often as
|
|
|
|
|
|
|
|
possible.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdio.h>
|
|
|
@ -7,6 +9,11 @@
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include "pid.h"
|
|
|
|
#include "pid.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
This this the class constructor. The min/max values are the minimum
|
|
|
|
|
|
|
|
and maximum values output by the regulator. The three regulator
|
|
|
|
|
|
|
|
parameters must be adjusted by experiments.
|
|
|
|
|
|
|
|
*/
|
|
|
|
PID::PID(double min, double max, double kp, double kd, double ki) {
|
|
|
|
PID::PID(double min, double max, double kp, double kd, double ki) {
|
|
|
|
Min = min;
|
|
|
|
Min = min;
|
|
|
|
Max = max;
|
|
|
|
Max = max;
|
|
|
@ -15,13 +22,20 @@ PID::PID(double min, double max, double kp, double kd, double ki) {
|
|
|
|
Ki = ki;
|
|
|
|
Ki = ki;
|
|
|
|
Integral = 0;
|
|
|
|
Integral = 0;
|
|
|
|
PreviousError = 0;
|
|
|
|
PreviousError = 0;
|
|
|
|
PreviousTime = getTime();
|
|
|
|
PreviousTime = GetTime();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Class destructor.
|
|
|
|
|
|
|
|
*/
|
|
|
|
PID::~PID() {
|
|
|
|
PID::~PID() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int64_t PID::getTime(void) {
|
|
|
|
/*
|
|
|
|
|
|
|
|
A static function to obtain a timestamp for the integrative/derivative
|
|
|
|
|
|
|
|
parts of the regulator.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
int64_t PID::GetTime(void) {
|
|
|
|
|
|
|
|
|
|
|
|
struct timeval current_time;
|
|
|
|
struct timeval current_time;
|
|
|
|
int64_t t;
|
|
|
|
int64_t t;
|
|
|
@ -31,8 +45,24 @@ int64_t PID::getTime(void) {
|
|
|
|
return t;
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
The function can be used to re-start the PID regulator. Re-setting
|
|
|
|
|
|
|
|
the integral and setting the current time as starting point.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
void PID::Start(void) {
|
|
|
|
|
|
|
|
Integral = 0;
|
|
|
|
|
|
|
|
PreviousError = 0;
|
|
|
|
|
|
|
|
PreviousTime = GetTime();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
This is the update function of the PID regulator. Passing the
|
|
|
|
|
|
|
|
target value of the regulator, the current process value and the
|
|
|
|
|
|
|
|
timestamp when the value was obtained.
|
|
|
|
|
|
|
|
*/
|
|
|
|
double PID::Update(double target, double value, int64_t time) {
|
|
|
|
double PID::Update(double target, double value, int64_t time) {
|
|
|
|
double error, out, dt;
|
|
|
|
double error, out;
|
|
|
|
|
|
|
|
int64_t dt;
|
|
|
|
double P, I, D;
|
|
|
|
double P, I, D;
|
|
|
|
double Derivative;
|
|
|
|
double Derivative;
|
|
|
|
|
|
|
|
|
|
|
@ -47,14 +77,19 @@ double PID::Update(double target, double value, int64_t time) {
|
|
|
|
Integral += error * dt;
|
|
|
|
Integral += error * dt;
|
|
|
|
I = Ki * Integral;
|
|
|
|
I = Ki * Integral;
|
|
|
|
|
|
|
|
|
|
|
|
// derivative part
|
|
|
|
if (dt > 0) {
|
|
|
|
Derivative = (error - PreviousError) / dt;
|
|
|
|
// derivative part
|
|
|
|
D = Kd * Derivative;
|
|
|
|
Derivative = (error - PreviousError) / dt;
|
|
|
|
|
|
|
|
D = Kd * Derivative;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
D = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// calculate output of regulator
|
|
|
|
// calculate output of regulator
|
|
|
|
out = P + I + D;
|
|
|
|
out = P + I + D;
|
|
|
|
|
|
|
|
|
|
|
|
// Min/Max
|
|
|
|
// Min/Max limitations of the regulator output
|
|
|
|
if (out > Max) out = Max;
|
|
|
|
if (out > Max) out = Max;
|
|
|
|
if (out < Min) out = Min;
|
|
|
|
if (out < Min) out = Min;
|
|
|
|
|
|
|
|
|
|
|
@ -64,3 +99,12 @@ double PID::Update(double target, double value, int64_t time) {
|
|
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
This is a shortcut function of the update function without passing
|
|
|
|
|
|
|
|
the timestamp. The timestamp will be the time when the fuction is
|
|
|
|
|
|
|
|
called.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
double PID::Update(double target, double value) {
|
|
|
|
|
|
|
|
return Update(target, value, GetTime());
|
|
|
|
|
|
|
|
}
|
|
|
|