This commit is contained in:
Josh Stewart 2020-05-22 11:43:30 +10:00
commit 61b92dd616
6 changed files with 149 additions and 165 deletions

View File

@ -576,9 +576,9 @@ page = 6
lnchHardLim = scalar, U08, 51, "rpm", 100, 0.0, 100, 25500, 0
lnchFuelAdd = scalar, U08, 52, "%", 1.0, 0.0, 0.0, 80, 0
idleKP = scalar, U08, 53, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
idleKI = scalar, U08, 54, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
idleKD = scalar, U08, 55, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
idleKP = scalar, U08, 53, "%", 0.03125, 0.0, 0.0, 7.96, 2 ; * ( 1 byte)
idleKI = scalar, U08, 54, "%", 0.03125, 0.0, 0.0, 7.96, 2 ; * ( 1 byte)
idleKD = scalar, U08, 55, "%", 0.00781, 0.0, 0.0, 1.99, 3 ; * ( 1 byte)
boostLimit = scalar, U08, 56, "kPa", 2.0, 0.0, 0.0, 511.0, 0
boostKP = scalar, U08, 57, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
boostKI = scalar, U08, 58, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
@ -1019,9 +1019,9 @@ page = 10
;All related to the closed loop VVT control
vvtCLholdDuty = scalar, U08, 126, "%", 1.0, 0.0, 0.0, 100.0, 0
vvtCLKP = scalar, U08, 127, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
vvtCLKI = scalar, U08, 128, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
vvtCLKD = scalar, U08, 129, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
vvtCLKP = scalar, U08, 127, "%", 0.03125, 0.0, 0.0, 7.96, 2 ; * ( 1 byte)
vvtCLKI = scalar, U08, 128, "%", 0.03125, 0.0, 0.0, 7.96, 2 ; * ( 1 byte)
vvtCLKD = scalar, U08, 129, "%", 0.00781, 0.0, 0.0, 1.99, 3 ; * ( 1 byte)
vvtCLMinAng = scalar, U16, 130, "deg", 1.0, 0.0, 0.0, 360.0, 0 ; * ( 1 bytes)
vvtCLMaxAng = scalar, U16, 132, "deg", 1.0, 0.0, 0.0, 360.0, 0 ; * ( 1 bytes)
@ -1367,7 +1367,7 @@ menuDialog = main
subMenu = idleSettings, "Idle Control"
subMenu = iacClosedLoop_curve, "Idle - RPM targets", 7, { iacAlgorithm == 3 || iacAlgorithm == 5 || idleAdvEnabled >= 1 }
subMenu = iacPwm_curve, "Idle - PWM Duty Cycle", 7, { iacAlgorithm == 2 }
subMenu = iacPwmCrank_curve, "Idle - PWM Cranking Duty Cycle", 7, { iacAlgorithm == 2 }
subMenu = iacPwmCrank_curve, "Idle - PWM Cranking Duty Cycle", 7, { iacAlgorithm == 2 || iacAlgorithm == 3 }
subMenu = iacStep_curve, "Idle - Stepper Motor", 7, { iacAlgorithm == 4 }
subMenu = iacStepCrank_curve, "Idle - Stepper Motor Cranking", 7, { iacAlgorithm == 4 || iacAlgorithm == 5 }
subMenu = std_separator

View File

@ -110,79 +110,55 @@ uint16_t TS_CommandButtonsHandler(int buttonCommand)
break;
case TS_CMD_INJ5_ON: // cmd group is for injector5 on actions
#if INJ_CHANNELS >= 5
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector5(); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector5(); }
break;
case TS_CMD_INJ5_OFF: // cmd group is for injector5 off actions
#if INJ_CHANNELS >= 5
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector5(); BIT_CLEAR(HWTest_INJ_50pc, 5); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector5(); BIT_CLEAR(HWTest_INJ_50pc, 5); }
break;
case TS_CMD_INJ5_50PC: // cmd group is for injector5 50%dc actions
#if INJ_CHANNELS >= 5
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 5); }
if(!BIT_CHECK(HWTest_INJ_50pc, 5)) { closeInjector5(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 5); }
if(!BIT_CHECK(HWTest_INJ_50pc, 5)) { closeInjector5(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
break;
case TS_CMD_INJ6_ON: // cmd group is for injector6 on actions
#if INJ_CHANNELS >= 6
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector6(); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector6(); }
break;
case TS_CMD_INJ6_OFF: // cmd group is for injector6 off actions
#if INJ_CHANNELS >= 6
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector6(); BIT_CLEAR(HWTest_INJ_50pc, 6); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector6(); BIT_CLEAR(HWTest_INJ_50pc, 6); }
break;
case TS_CMD_INJ6_50PC: // cmd group is for injector6 50% dc actions
#if INJ_CHANNELS >= 6
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 6); }
if(!BIT_CHECK(HWTest_INJ_50pc, 6)) { closeInjector6(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 6); }
if(!BIT_CHECK(HWTest_INJ_50pc, 6)) { closeInjector6(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
break;
case TS_CMD_INJ7_ON: // cmd group is for injector7 on actions
#if INJ_CHANNELS >= 7
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector7(); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector7(); }
break;
case TS_CMD_INJ7_OFF: // cmd group is for injector7 off actions
#if INJ_CHANNELS >= 7
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector7(); BIT_CLEAR(HWTest_INJ_50pc, 7); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector7(); BIT_CLEAR(HWTest_INJ_50pc, 7); }
break;
case TS_CMD_INJ7_50PC: // cmd group is for injector7 50%dc actions
#if INJ_CHANNELS >= 7
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 7); }
if(!BIT_CHECK(HWTest_INJ_50pc, 7)) { closeInjector7(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 7); }
if(!BIT_CHECK(HWTest_INJ_50pc, 7)) { closeInjector7(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
break;
case TS_CMD_INJ8_ON: // cmd group is for injector8 on actions
#if INJ_CHANNELS >= 8
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector8(); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ openInjector8(); }
break;
case TS_CMD_INJ8_OFF: // cmd group is for injector8 off actions
#if INJ_CHANNELS >= 8
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector8(); BIT_CLEAR(HWTest_INJ_50pc, 8); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ){ closeInjector8(); BIT_CLEAR(HWTest_INJ_50pc, 8); }
break;
case TS_CMD_INJ8_50PC: // cmd group is for injector8 50% dc actions
#if INJ_CHANNELS >= 8
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 8); }
if(!BIT_CHECK(HWTest_INJ_50pc, 8)) { closeInjector8(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_INJ_50pc, 8); }
if(!BIT_CHECK(HWTest_INJ_50pc, 8)) { closeInjector8(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
break;
case TS_CMD_IGN1_ON: // cmd group is for spark1 on actions
@ -238,79 +214,55 @@ uint16_t TS_CommandButtonsHandler(int buttonCommand)
break;
case TS_CMD_IGN5_ON: // cmd group is for spark5 on actions
#if IGN_CHANNELS >= 5
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil5Charge(); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil5Charge(); }
break;
case TS_CMD_IGN5_OFF: // cmd group is for spark5 off actions
#if IGN_CHANNELS >= 5
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil5Charge(); BIT_CLEAR(HWTest_IGN_50pc, 5); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil5Charge(); BIT_CLEAR(HWTest_IGN_50pc, 5); }
break;
case TS_CMD_IGN5_50PC: // cmd group is for spark4 50%dc actions
#if IGN_CHANNELS >= 5
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 5); }
if(!BIT_CHECK(HWTest_IGN_50pc, 5)) { coil5Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 5); }
if(!BIT_CHECK(HWTest_IGN_50pc, 5)) { coil5Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
break;
case TS_CMD_IGN6_ON: // cmd group is for spark6 on actions
#if IGN_CHANNELS >= 6
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil6Charge(); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil6Charge(); }
break;
case TS_CMD_IGN6_OFF: // cmd group is for spark6 off actions
#if IGN_CHANNELS >= 6
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil6Charge(); BIT_CLEAR(HWTest_IGN_50pc, 6); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil6Charge(); BIT_CLEAR(HWTest_IGN_50pc, 6); }
break;
case TS_CMD_IGN6_50PC: // cmd group is for spark6 50%dc actions
#if IGN_CHANNELS >= 6
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 6); }
if(!BIT_CHECK(HWTest_IGN_50pc, 6)) { coil6Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 6); }
if(!BIT_CHECK(HWTest_IGN_50pc, 6)) { coil6Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
break;
case TS_CMD_IGN7_ON: // cmd group is for spark7 on actions
#if IGN_CHANNELS >= 7
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil7Charge(); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil7Charge(); }
break;
case TS_CMD_IGN7_OFF: // cmd group is for spark7 off actions
#if IGN_CHANNELS >= 7
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil7Charge(); BIT_CLEAR(HWTest_IGN_50pc, 7); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil7Charge(); BIT_CLEAR(HWTest_IGN_50pc, 7); }
break;
case TS_CMD_IGN7_50PC: // cmd group is for spark7 50%dc actions
#if IGN_CHANNELS >= 7
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 7); }
if(!BIT_CHECK(HWTest_IGN_50pc, 7)) { coil7Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 7); }
if(!BIT_CHECK(HWTest_IGN_50pc, 7)) { coil7Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
break;
case TS_CMD_IGN8_ON: // cmd group is for spark8 on actions
#if IGN_CHANNELS >= 8
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil8Charge(); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { beginCoil8Charge(); }
break;
case TS_CMD_IGN8_OFF: // cmd group is for spark8 off actions
#if IGN_CHANNELS >= 8
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil8Charge(); BIT_CLEAR(HWTest_IGN_50pc, 8); }
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { endCoil8Charge(); BIT_CLEAR(HWTest_IGN_50pc, 8); }
break;
case TS_CMD_IGN8_50PC: // cmd group is for spark8 50%dc actions
#if IGN_CHANNELS >= 8
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 8); }
if(!BIT_CHECK(HWTest_IGN_50pc, 8)) { coil8Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
#endif
if( BIT_CHECK(currentStatus.testOutputs, 1) ) { BIT_TOGGLE(HWTest_IGN_50pc, 8); }
if(!BIT_CHECK(HWTest_IGN_50pc, 8)) { coil8Low(); } //Ensure this output is turned off (Otherwise the output may stay on permanently)
break;
//VSS Calibration routines

View File

@ -87,7 +87,7 @@ void initialiseIdle()
#elif defined(CORE_TEENSY)
idle_pwm_max_count = 1000000L / (32 * configPage6.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
#endif
idlePID.SetOutputLimits(percentage(configPage2.iacCLminDuty, idle_pwm_max_count), percentage(configPage2.iacCLmaxDuty, idle_pwm_max_count));
idlePID.SetOutputLimits(percentage(configPage2.iacCLminDuty, idle_pwm_max_count<<2), percentage(configPage2.iacCLmaxDuty, idle_pwm_max_count<<2));
idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD);
idlePID.SetMode(AUTOMATIC); //Turn PID on
@ -159,7 +159,7 @@ void initialiseIdle()
}
idlePID.SetSampleTime(100);
idlePID.SetOutputLimits(0, (configPage9.iacMaxSteps * 3)); //Maximum number of steps; always less than home steps count.
idlePID.SetOutputLimits(0, (configPage9.iacMaxSteps * 3)<<2); //Maximum number of steps; always less than home steps count.
idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD);
idlePID.SetMode(AUTOMATIC); //Turn PID on
break;
@ -247,6 +247,17 @@ void idleControl()
case IAC_ALGORITHM_PWM_CL: //Case 3 is PWM closed loop
//No cranking specific value for closed loop (yet?)
if( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) )
{
//Currently cranking. Use the cranking table
currentStatus.idleDuty = table2D_getValue(&iacCrankDutyTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
currentStatus.idleLoad = currentStatus.idleDuty;
idle_pwm_target_value = percentage(currentStatus.idleDuty, idle_pwm_max_count);
idle_pid_target_value = idle_pwm_target_value<<2; //Resolution increased
idlePID.Initialize(); //Update output to smooth transition
}
else
{
currentStatus.CLIdleTarget = (byte)table2D_getValue(&iacClosedLoopTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
idle_cl_target_rpm = (uint16_t)currentStatus.CLIdleTarget * 10; //Multiply the byte target value back out by 10
if( (idleCounter & 31) == 1) { idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD); } //This only needs to be run very infrequently, once every 32 calls to idleControl(). This is approx. once per second
@ -254,7 +265,7 @@ void idleControl()
PID_computed = idlePID.Compute(true);
if(PID_computed == true)
{
idle_pwm_target_value = idle_pid_target_value;
idle_pwm_target_value = idle_pid_target_value>>2; //increased resolution
if( idle_pwm_target_value == 0 )
{
disableIdle();
@ -267,6 +278,7 @@ void idleControl()
}
idleCounter++;
}
break;
case IAC_ALGORITHM_STEP_OL: //Case 4 is open loop stepper control
@ -291,9 +303,9 @@ void idleControl()
else
{
//Standard running
//Only do a lookup of the required value around 4 times per second (Once every 255 mainloops). Any more than this can create too much jitter and require a hyster value that is too high
//Only do a lookup of the required value around 4 times per second. Any more than this can create too much jitter and require a hyster value that is too high
//We must also have more than zero RPM for the running state
if (((mainLoopCount & 255) == 1) && (currentStatus.RPM > 0))
if (BIT_CHECK(LOOP_TIMER, BIT_TIMER_4HZ) && (currentStatus.RPM > 0))
{
idleStepper.targetIdleStep = table2D_getValue(&iacStepTable, (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET)) * 3; //All temps are offset by 40 degrees. Step counts are divided by 3 in TS. Multiply back out here
if(currentStatus.idleUpActive == true) { idleStepper.targetIdleStep += configPage2.idleUpAdder; } //Add Idle Up amount if active
@ -319,7 +331,7 @@ void idleControl()
//First thing to check is whether there is currently a step going on and if so, whether it needs to be turned off
if( (checkForStepping() == false) && (isStepperHomed() == true) ) //Check that homing is complete and that there's not currently a step already taking place. MUST BE IN THIS ORDER!
{
if( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK )/* ||currentStatus.rpmDOT>=500||currentStatus.rpmDOT<=-500*/)
if( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) )
{
//Currently cranking. Use the cranking table
idleStepper.targetIdleStep = table2D_getValue(&iacCrankStepsTable, (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET)) * 3; //All temps are offset by 40 degrees. Step counts are divided by 3 in TS. Multiply back out here
@ -332,36 +344,35 @@ void idleControl()
}
doStep();
idle_pid_target_value = idleStepper.targetIdleStep<<2; //Resolution increased
idlePID.Initialize(); //Update output to smooth transition
}
else
{
if( (idleCounter & 31) == 1)
{
//This only needs to be run very infrequently, once every 32 calls to idleControl(). This is approx. once per second
idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD);
iacStepTime_uS = configPage6.iacStepTime * 1000;
iacCoolTime_uS = configPage9.iacCoolTime * 1000;
if( (idleCounter & 31) == 1)
{
//This only needs to be run very infrequently, once every 32 calls to idleControl(). This is approx. once per second
idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD);
iacStepTime_uS = configPage6.iacStepTime * 1000;
iacCoolTime_uS = configPage9.iacCoolTime * 1000;
}
currentStatus.CLIdleTarget = (byte)table2D_getValue(&iacClosedLoopTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
idle_cl_target_rpm = (uint16_t)currentStatus.CLIdleTarget * 10; //All temps are offset by 40 degrees
PID_computed = idlePID.Compute(true);
idleStepper.targetIdleStep = idle_pid_target_value>>2; //Increase resolution
if(currentStatus.idleUpActive == true) { idleStepper.targetIdleStep += configPage2.idleUpAdder; } //Add Idle Up amount if active
//limit to the configured max steps. This must include any idle up adder, to prevent over-opening.
if (idleStepper.targetIdleStep > (configPage9.iacMaxSteps * 3) )
{
idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3;
}
doStep();
idleCounter++;
}
currentStatus.CLIdleTarget = (byte)table2D_getValue(&iacClosedLoopTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees
idle_cl_target_rpm = (uint16_t)currentStatus.CLIdleTarget * 10; //All temps are offset by 40 degrees
if(currentStatus.idleUpActive == true) { idle_pid_target_value += configPage2.idleUpAdder; } //Add Idle Up amount if active
PID_computed = idlePID.Compute(true);
idleStepper.targetIdleStep = idle_pid_target_value;
//limit to the configured max steps. This must include any idle up adder, to prevent over-opening.
if (idleStepper.targetIdleStep > (configPage9.iacMaxSteps * 3) )
{
idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3;
}
doStep();
idleCounter++;
}
currentStatus.idleLoad = idleStepper.curIdleStep / 2; //Current step count (Divided by 2 for byte)
currentStatus.idleLoad = idleStepper.curIdleStep / 2; //Current step count (Divided by 2 for byte)
}
//Set or clear the idle active flag
if(idleStepper.targetIdleStep != idleStepper.curIdleStep) { BIT_SET(currentStatus.spark, BIT_SPARK_IDLE); }

View File

@ -213,13 +213,12 @@ integerPID::integerPID(long* Input, long* Output, long* Setpoint,
byte Kp, byte Ki, byte Kd, byte ControllerDirection)
{
myOutput = Output;
myOutput = Output;
myInput = Input;
mySetpoint = Setpoint;
mySetpoint = Setpoint;
inAuto = false;
integerPID::SetOutputLimits(0, 255); //default output limit corresponds to
//the arduino pwm limits
integerPID::SetOutputLimits(0, 255); //default output limit corresponds to the arduino pwm limits
SampleTime = 250; //default Controller Sample Time is 0.25 seconds. This is the 4Hz control time for Idle and VVT
@ -240,45 +239,57 @@ bool integerPID::Compute(bool pOnE)
{
if(!inAuto) return false;
unsigned long now = millis();
//SampleTime = (now - lastTime);
unsigned long timeChange = (now - lastTime);
if(timeChange >= SampleTime)
{
/*Compute all the working error variables*/
long input = *myInput;
long error = *mySetpoint - input;
long dInput = (input - lastInput);
outputSum += (ki * error)/1024; //Note that ki is multiplied by 1024 so it must be divided by 1024 here
if(outputSum > outMax) { outputSum = outMax; }
else if(outputSum < outMin) { outputSum = outMin; }
/*Compute PID Output*/
long output;
if(pOnE)
long input = *myInput;
if(input > 0) //Fail safe, should never be 0
{
output = (kp * error) + outputSum - ((kd * dInput)/128);
long error = *mySetpoint - input;
long dInput = (input - lastInput);
long outMinResized = outMin<<PID_SHIFTS;
long outMaxResized = outMax<<PID_SHIFTS;
if (ki != 0)
{
outputSum += (ki * error); //integral += error × dt
if(outputSum > outMaxResized) { outputSum = outMaxResized; }
else if(outputSum < outMinResized) { outputSum = outMinResized; }
}
/*Compute PID Output*/
long output;
if(pOnE)
{
output = (kp * error);
if (ki != 0) { output += outputSum; }
if (kd != 0) { output -= (kd * dInput)>>2; }
output >>= PID_SHIFTS;
}
else
{
outputSum -= (kp * dInput);
if(outputSum > outMaxResized) { outputSum = outMaxResized; }
else if(outputSum < outMinResized) { outputSum = outMinResized; }
output = outputSum;
if (kd != 0) { output -= (kd * dInput)>>2; }
output >>= PID_SHIFTS;
}
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
{
outputSum -= kp * dInput;
if(outputSum > outMax) { outputSum = outMax; }
else if(outputSum < outMin) { outputSum = outMin; }
output = outputSum - ((kd * dInput)/128);
}
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;
}
@ -364,9 +375,10 @@ void integerPID::SetTunings(byte Kp, byte Ki, byte Kd)
kd = Kd / SampleTimeInSec;
*/
long InverseSampleTimeInSec = 1000 / SampleTime;
kp = Kp;
ki = (long)((long)Ki * 1024) / InverseSampleTimeInSec;
kd = ((long)Kd * InverseSampleTimeInSec);
//New resolution, 2 shifts to improve ki here | kp 1.563% | ki 1.563% | kd 0.195%
kp = (uint16_t)Kp<<2;
ki = (long)(Ki<<2) / InverseSampleTimeInSec;
kd = (long)(Kd<<2) * InverseSampleTimeInSec;
if(controllerDirection == REVERSE)
{
@ -409,8 +421,8 @@ void integerPID::SetOutputLimits(long Min, long Max)
if(*myOutput > outMax) *myOutput = outMax;
else if(*myOutput < outMin) *myOutput = outMin;
if(outputSum > outMax) { outputSum = outMax; }
else if(outputSum < outMin) { outputSum = outMin; }
if((outputSum>>PID_SHIFTS) > outMax) { outputSum = outMax<<PID_SHIFTS; }
else if((outputSum>>PID_SHIFTS) < outMin) { outputSum = outMin<<PID_SHIFTS; }
}
}
@ -435,11 +447,11 @@ void integerPID::SetMode(int Mode)
******************************************************************************/
void integerPID::Initialize()
{
outputSum = *myOutput;
outputSum = *myOutput<<PID_SHIFTS;
lastInput = *myInput;
lastMinusOneInput = *myInput;
if(outputSum > outMax) { outputSum = outMax; }
else if(outputSum < outMin) { outputSum = outMin; }
if((outputSum>>PID_SHIFTS) > outMax) { outputSum = outMax<<PID_SHIFTS; }
else if((outputSum>>PID_SHIFTS) < outMin) { outputSum = outMin<<PID_SHIFTS; }
}
/* SetControllerDirection(...)*************************************************

View File

@ -88,6 +88,7 @@ class integerPID
#define MANUAL 0
#define DIRECT 0
#define REVERSE 1
#define PID_SHIFTS 7 //Increased resolution
//commonly used functions **************************************************************************
integerPID(long*, long*, long*, // * constructor. links the PID to the Input, Output, and

View File

@ -334,7 +334,15 @@ void doUpdates()
configPage2.aeColdPct = 100;
configPage2.aeColdTaperMin = 40;
configPage2.aeColdTaperMax = 100;
//New PID resolution, old resolution was 100% for each increase, 100% now is stored as 32
configPage6.idleKP = configPage6.idleKP<<5;
configPage6.idleKI = configPage6.idleKI<<5;
configPage6.idleKD = configPage6.idleKD<<5;
configPage10.vvtCLKP = configPage10.vvtCLKP<<5;
configPage10.vvtCLKI = configPage10.vvtCLKI<<5;
configPage10.vvtCLKD = configPage10.vvtCLKD<<5;
//Cranking enrichment to run taper added. Default it to 0,1 secs
configPage10.crankingEnrichTaper = 1;