Further tuning of the PID algorithm

This commit is contained in:
Josh Stewart 2016-05-28 23:53:15 +10:00
parent 726645d376
commit 7b9ef56e07
4 changed files with 20 additions and 20 deletions

View File

@ -88,7 +88,7 @@ struct statuses {
unsigned int RPM;
long longRPM;
int mapADC;
unsigned int MAP;
long MAP;
byte TPS; //The current TPS reading (0% - 100%)
byte TPSlast; //The previous TPS reading
unsigned long TPS_time; //The time the TPS sample was taken

View File

@ -12,7 +12,7 @@ These functions cover the PWM and stepper idle control
Idle Control
Currently limited to on/off control and open loop PWM and stepper drive
*/
integerPID idlePID(&currentStatus.RPM, &idle_pwm_target_value, &idle_cl_target_rpm, configPage3.idleKP, configPage3.idleKI, configPage3.idleKD, DIRECT); //This is the PID object if that algorithm is used. Needs to be global as it maintains state outside of each function call
integerPID idlePID(&currentStatus.longRPM, &idle_pwm_target_value, &idle_cl_target_rpm, configPage3.idleKP, configPage3.idleKI, configPage3.idleKD, DIRECT); //This is the PID object if that algorithm is used. Needs to be global as it maintains state outside of each function call
void initialiseIdle()
{
@ -74,6 +74,7 @@ void initialiseIdle()
idle2_pin_mask = digitalPinToBitMask(pinIdle2);
idle_pwm_max_count = 1000000L / (16 * configPage3.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz
idlePID.SetOutputLimits(0, idle_pwm_max_count);
idlePID.SetTunings(configPage3.idleKP, configPage3.idleKI, configPage3.idleKD);
idlePID.SetMode(AUTOMATIC); //Turn PID on
break;
@ -150,7 +151,7 @@ void idleControl()
case 3: //Case 3 is PWM closed loop
//No cranking specific value for closed loop (yet?)
idle_cl_target_rpm = table2D_getValue(&iacClosedLoopTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET) * 10; //All temps are offset by 40 degrees
idlePID.SetTunings(configPage3.idleKP, configPage3.idleKI, configPage3.idleKD);
//idlePID.SetTunings(configPage3.idleKP, configPage3.idleKI, configPage3.idleKD);
idlePID.Compute();
if( idle_pwm_target_value == 0 ) { TIMSK4 &= ~(1 << OCIE4C); digitalWrite(pinIdle1, LOW); }

View File

@ -203,7 +203,7 @@ int PID::GetDirection(){ return controllerDirection;}
* The parameters specified here are those for for which we can't set up
* reliable defaults, so we need to have the user set them.
***************************************************************************/
integerPID::integerPID(unsigned int* Input, long* Output, long* Setpoint,
integerPID::integerPID(long* Input, long* Output, long* Setpoint,
byte Kp, byte Ki, byte Kd, byte ControllerDirection)
{
@ -215,12 +215,12 @@ integerPID::integerPID(unsigned int* Input, long* Output, long* Setpoint,
integerPID::SetOutputLimits(0, 255); //default output limit corresponds to
//the arduino pwm limits
//SampleTime = 100; //default Controller Sample Time is 0.1 seconds
SampleTime = 100; //default Controller Sample Time is 0.1 seconds
integerPID::SetControllerDirection(ControllerDirection);
integerPID::SetTunings(Kp, Ki, Kd);
//lastTime = millis()-SampleTime;
lastTime = millis()-SampleTime;
}
@ -234,21 +234,20 @@ bool integerPID::Compute()
{
if(!inAuto) return false;
unsigned long now = millis();
SampleTime = (now - lastTime);
//if(timeChange>=SampleTime)
//SampleTime = (now - lastTime);
unsigned long timeChange = (now - lastTime);
if(timeChange>=SampleTime)
{
/*Compute all the working error variables*/
long input = *myInput;
long error = *mySetpoint - input;
ITerm+= (ki * error)/100;
//ITerm+= divs100(ki * error);
ITerm+= (ki * error)/1000; //Note that ki is multiplied by 1000 rather than 100, so it must be divided by 1000 here
if(ITerm > outMax) ITerm= outMax;
else if(ITerm < outMin) ITerm= outMin;
long dInput = (input - lastInput);
/*Compute PID Output*/
long output = (kp * error)/100 + ITerm- (kd * dInput)/100;
//long output = divs100(kp * error) + ITerm- divs100(kd * dInput);
long output = (kp * error)/100 + ITerm - (kd * dInput)/100;
if(output > outMax) output = outMax;
else if(output < outMin) output = outMin;
@ -256,10 +255,10 @@ bool integerPID::Compute()
/*Remember some variables for next time*/
lastInput = input;
//lastTime = now;
lastTime = now;
return true;
}
//else return false;
else return false;
}
@ -282,8 +281,8 @@ void integerPID::SetTunings(byte Kp, byte Ki, byte Kd)
*/
long InverseSampleTimeInSec = 100000 / SampleTime;
kp = Kp;
ki = (Ki * 100) / InverseSampleTimeInSec;
kd = (Kd * InverseSampleTimeInSec) / 100;
ki = (long)((long)Ki * 1000) / InverseSampleTimeInSec;
kd = ((long)Kd * InverseSampleTimeInSec) / 100;
if(controllerDirection ==REVERSE)
{

View File

@ -90,7 +90,7 @@ class integerPID
#define REVERSE 1
//commonly used functions **************************************************************************
integerPID(unsigned int*, long*, long*, // * constructor. links the PID to the Input, Output, and
integerPID(long*, long*, long*, // * constructor. links the PID to the Input, Output, and
byte, byte, byte, byte); // Setpoint. Initial tuning parameters are also set here
void SetMode(int Mode); // * sets PID to either Manual (0) or Auto (non-0)
@ -133,9 +133,9 @@ class integerPID
byte dispKi; // format for display purposes
byte dispKd; //
byte kp; // * (P)roportional Tuning Parameter
byte ki; // * (I)ntegral Tuning Parameter
byte kd; // * (D)erivative Tuning Parameter
int kp; // * (P)roportional Tuning Parameter
int ki; // * (I)ntegral Tuning Parameter
int kd; // * (D)erivative Tuning Parameter
int controllerDirection;