Hello,
I've opened the PID library created by Brett Beauregard with Notepad++ to see what's inside the file. I'm interested in this part of the code
PID::PID(double* Input, double* Output, double* Setpoint,
double Kp, double Ki, double Kd, int ControllerDirection)
{
myOutput = Output;
myInput = Input;
mySetpoint = Setpoint;
inAuto = false;
[color=red][b]PID::SetOutputLimits(0, 255); [/b] [/color] //default output limit corresponds to
//the arduino pwm limits
SampleTime = 100; //default Controller Sample Time is 0.1 seconds
PID::SetControllerDirection(ControllerDirection);
PID::SetTunings(Kp, Ki, Kd);
lastTime = millis()-SampleTime;
}
void PID::SetOutputLimits([color=red][b]double Min, double Max[/b][/color])
{
if(Min >= Max) return;
[color=red][b] outMin = Min;
outMax = Max;[/b][/color]
if(inAuto)
{
if(*myOutput > outMax) *myOutput = outMax;
else if(*myOutput < outMin) *myOutput = outMin;
if(ITerm > outMax) ITerm= outMax;
else if(ITerm < outMin) ITerm= outMin;
}
bool PID::Compute()
{
if(!inAuto) return false;
unsigned long now = millis();
unsigned long timeChange = (now - lastTime);
if(timeChange>=SampleTime)
{
/*Compute all the working error variables*/
double input = *myInput;
double error = *mySetpoint - input;
[color=red][b] ITerm+= (ki * error);
if(ITerm > outMax) ITerm= outMax;
else if(ITerm < outMin) ITerm= outMin;[/b][/color]
double dInput = (input - lastInput);
/*Compute PID Output*/
double output = kp * error + ITerm- kd * dInput;
if(output > outMax) output = outMax;
else if(output < outMin) output = outMin;
*myOutput = output;
/*Remember some variables for next time*/
lastInput = input;
lastTime = now;
return true;
}
else return false;
}
As the code which is highlighted with red color, It's shown that the integral term will be limited on the range of 0 to 255.
But I think the integral term should be on the range of -255 to 255. My reason is the steady state error might be caused by an excessive output so the Setpoint-Feedback < 0
I've tried to do sth. like this, delete the old file and resave the new one:
if(ITerm > 255) ITerm= 255;
else if(ITerm < -255) ITerm= -255;
After I run the program I got an error as shown in the picture
Is there any good way to do this? (I need the case that SP-FB<0 because I'm gonna apply it to a boost converter. When I the voltage is too much, I should be able to decrease it.)
Thanks
PS: Here is the code for PWM of the boost converter, the output is an Arduino Pin11, The feedback(Input) is the Pin (A0)
#include <PID_v1_corrected.h>
//Define Variables we'll be connecting to
double voltage=0.000;
double Setpoint, Output, Input, duty;
int Input_int=0;
double Kp=5, Ki=1.000, Kd=0.000;
const int sampleRate=1;
int Out_int=0;
PID myPID(&Input, &Output, &Setpoint,Kp,Ki,Kd, DIRECT);
//Specify the links and initial tuning parameters
void setup()
{
Input = analogRead(A0);
Serial.begin(9600);
pinMode(11, OUTPUT);
TCCR2A = _BV(COM2A1) | _BV(WGM21) | _BV(WGM20);
analogReference(DEFAULT);
myPID.SetMode(AUTOMATIC);
myPID.SetSampleTime(sampleRate);
myPID.SetTunings(Kp, Ki, Kd);
}
void loop()
{
voltage = 170.000;
Setpoint= map_double(voltage, 0.000, 170.000, 0.000, 1023.000);
Serial.print("Setpoint=");
Serial.print(Setpoint);
Serial.print("\n");
Input_int = analogRead(A0);
if (Input_int>=1023)
Input_int=1023;
else if (Input_int<=0)
Input_int=0;
Input = (double)Input_int;
Serial.print("Input=");
Serial.print(Input);
Serial.print("\n");
myPID.Compute();
if (Output>255.000)
Output=255.000;
else if (Output<0.000)
Output=0.000;
Serial.print("Output=");
Serial.print(Output);
Serial.print("\n");
Out_int=(int)Output;
if (Out_int>250)
Out_int=250;
else if (Out_int<0)
Out_int=0;
OCR2A=Out_int;//Digital Pin 11 as an O/P
Serial.print("OCR2A=");
Serial.print(OCR2A);
Serial.print("\n");
duty = map_double(Output,0.000,255.000,0.000,100.000);
Serial.print("Duty=");
Serial.print(duty);
Serial.print("\n\n");
digitalWrite(13,HIGH);
}
double mapnew(double x, long in_min, long in_max, double out_min, double out_max)
{
in_min = (double)in_min;
in_max = (double)in_max;
return ((x - in_min) * (out_max - out_min) / (in_max - in_min)) + out_min;
}
double map_double(double x, double in_min, double in_max, double out_min, double out_max)
{
return ((x-in_min)*(out_max-out_min)/(in_max-in_min))+out_min;
}