Steper OL+CL mode (#554)

This commit is contained in:
Vitor Moreno B. Sales 2021-12-08 18:52:56 -03:00 committed by GitHub
parent 8b262a0087
commit 1536b9196d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 166 additions and 59 deletions

View File

@ -221,7 +221,7 @@
delayAfterPortOpen=1000
;validateArrayBounds = true
blockReadTimeout = 2000
;tsWriteBlocks = on
tsWriteBlocks = on
interWriteDelay = 1 ;Ignored when tsWriteBlocks is on
pageActivationDelay = 10
restrictSquirtRelationship = false ;This requires TS 3.1 or above
@ -688,7 +688,7 @@ page = 6
iacCrankBins = array, U08, 112, [4], "F", 1.8, -22.23, -40, 215, 0
#endif
iacAlgorithm = bits , U08, 116, [0:2], "None", "On/Off", "PWM Open loop", "PWM Closed loop", "Stepper Open Loop", "Stepper Closed Loop", "PWM Closed+Open loop", "INVALID"
iacAlgorithm = bits , U08, 116, [0:2], "None", "On/Off", "PWM Open loop", "PWM Closed loop", "Stepper Open Loop", "Stepper Closed Loop", "PWM Closed+Open loop", "Stepper Closed+Open loop"
iacStepTime = bits , U08, 116, [3:5], "INVALID","1", "2", "3", "4", "5", "6","INVALID"
iacChannels = bits, U08, 116, [6:6], "1", "2"
iacPWMdir = bits , U08, 116, [7:7], "Normal", "Reverse"
@ -1723,13 +1723,13 @@ menuDialog = main
subMenu = ASE, "Afterstart Enrichment (ASE)"
subMenu = std_separator
subMenu = idleSettings, "Idle Control"
subMenu = iacClosedLoop_curve, "Idle - RPM targets", 7, { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || idleAdvEnabled >= 1 }
subMenu = iacClosedLoop_curve, "Idle - RPM targets", 7, { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 || idleAdvEnabled >= 1 }
subMenu = iacPwm_curve, "Idle - PWM Duty Cycle", 7, { iacAlgorithm == 2 || iacAlgorithm == 6}
subMenu = iacPwmCrank_curve, "Idle - PWM Cranking Duty Cycle", 7, { iacAlgorithm == 2 || iacAlgorithm == 3 || iacAlgorithm == 6}
subMenu = iacStep_curve, "Idle - Stepper Motor", 7, { iacAlgorithm == 4 }
subMenu = iacStepCrank_curve, "Idle - Stepper Motor Cranking", 7, { iacAlgorithm == 4 || iacAlgorithm == 5 }
subMenu = iacStep_curve, "Idle - Stepper Motor", 7, { iacAlgorithm == 4 || iacAlgorithm == 7 }
subMenu = iacStepCrank_curve, "Idle - Stepper Motor Cranking", 7, { iacAlgorithm == 4 || iacAlgorithm == 5 || iacAlgorithm == 7 }
subMenu = std_separator
subMenu = idleUpSettings, "Idle Up Settings", { iacAlgorithm == 2 || iacAlgorithm == 3 || iacAlgorithm == 4 || iacAlgorithm == 5 || iacAlgorithm == 6 }
subMenu = idleUpSettings, "Idle Up Settings", { iacAlgorithm == 2 || iacAlgorithm == 3 || iacAlgorithm == 4 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 }
subMenu = std_separator
subMenu = idleAdvanceSettings, "Idle Advance Settings"
@ -2503,12 +2503,12 @@ menuDialog = main
panel = pwm_fan_curve,
dialog = stepper_idle, "Stepper Idle"
field = "Step time (ms)", iacStepTime, { iacAlgorithm == 4 || iacAlgorithm == 5 }
field = "Cool time (ms)", iacCoolTime, { iacAlgorithm == 4 || iacAlgorithm == 5 }
field = "Home steps", iacStepHome, { iacAlgorithm == 4 || iacAlgorithm == 5 }
field = "Minimum Steps", iacStepHyster, { iacAlgorithm == 4 || iacAlgorithm == 5 }
field = "Don't exceed", iacMaxSteps, { iacAlgorithm == 4 || iacAlgorithm == 5 }
field = "Stepper Inverted", iacStepperInv, { iacAlgorithm == 4 || iacAlgorithm == 5 }
field = "Step time (ms)", iacStepTime, { iacAlgorithm == 4 || iacAlgorithm == 5 || iacAlgorithm == 7 }
field = "Cool time (ms)", iacCoolTime, { iacAlgorithm == 4 || iacAlgorithm == 5 || iacAlgorithm == 7 }
field = "Home steps", iacStepHome, { iacAlgorithm == 4 || iacAlgorithm == 5 || iacAlgorithm == 7 }
field = "Minimum Steps", iacStepHyster, { iacAlgorithm == 4 || iacAlgorithm == 5 || iacAlgorithm == 7 }
field = "Don't exceed", iacMaxSteps, { iacAlgorithm == 4 || iacAlgorithm == 5 || iacAlgorithm == 7 }
field = "Stepper Inverted", iacStepperInv, { iacAlgorithm == 4 || iacAlgorithm == 5 || iacAlgorithm == 7 }
dialog = pwm_idle, "PWM Idle"
field = "Number of outputs", iacChannels, { iacAlgorithm == 2 || iacAlgorithm == 3 || iacAlgorithm == 6 }
@ -2517,18 +2517,19 @@ menuDialog = main
field = "Run before start", iacPWMrun, { iacAlgorithm == 2 || iacAlgorithm == 3 || iacAlgorithm == 6 }
dialog = closedloop_idle, "Closed loop Idle"
field = "P", idleKP, { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6}
field = "I", idleKI, { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6}
field = "D", idleKD, { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6}
field = "Minimum valve duty", iacCLminDuty, { iacAlgorithm == 3 || iacAlgorithm == 6}
field = "Maximum valve duty", iacCLmaxDuty, { iacAlgorithm == 3 || iacAlgorithm == 6}
field = "Integeral reset above TPS", iacTPSlimit, { iacAlgorithm == 6 }
field = "Integeral reset RPM Hysteresis", iacRPMlimitHysteresis, { iacAlgorithm == 6 }
displayOnlyField = "# !!! Please note that 1.0 means 100% !!!"
field = "P", idleKP, { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 }
field = "I", idleKI, { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 }
field = "D", idleKD, { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 }
field = "Minimum valve duty", iacCLminDuty, { iacAlgorithm == 3 || iacAlgorithm == 6 }
field = "Maximum valve duty", iacCLmaxDuty, { iacAlgorithm == 3 || iacAlgorithm == 6 }
field = "Integeral reset above TPS", iacTPSlimit, { iacAlgorithm == 6 || iacAlgorithm == 7 }
field = "Integeral reset RPM Hysteresis", iacRPMlimitHysteresis, { iacAlgorithm == 6 || iacAlgorithm == 7 }
dialog = idleSettings, "Idle Settings"
topicHelp = "https://wiki.speeduino.com/en/configuration/Idle"
field = "Idle control type", iacAlgorithm
field = "Crank to run taper", idleTaperTime, { iacAlgorithm == 2 || iacAlgorithm == 4 }
field = "Crank to run taper", idleTaperTime, { iacAlgorithm == 2 || iacAlgorithm == 4 || iacAlgorithm == 5 || iacAlgorithm == 7 }
field = "#Fast Idle"
field = "Fast idle temp", iacFastTemp, { iacAlgorithm == 1 }
panel = pwm_idle
@ -2645,6 +2646,7 @@ menuDialog = main
field = " Use dwell map", useDwellMap
field = " Running dwell", dwellrun, { useDwellMap == 0 }
field = " Spark duration", sparkDur
field = " Dwell scale for repeated spark", ignRptScale, { crankIgnOutRpt }
field = ""
field = "#Note"
field = "The above times are for 12V. Voltage correction"
@ -2673,7 +2675,7 @@ menuDialog = main
topicHelp = "https://wiki.speeduino.com/en/configuration/IdleAdvance"
panel = idleAdvanceSettings_east
panel = idle_advance_curve, { idleAdvEnabled >= 1 }
panel = iacClosedLoop_curve, { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || idleAdvEnabled >= 1 }
panel = iacClosedLoop_curve, { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7|| idleAdvEnabled >= 1 }
dialog = rotary_ignition, "Rotary Ignition", 4
@ -2942,6 +2944,7 @@ menuDialog = main
field = "Minimum Cam angle", vvtCLMinAng
field = "Maximum Cam angle", vvtCLMaxAng
field = ""
displayOnlyField = "# !!! Please note that 1.0 means 100% !!!"
field = "Proportional Gain", vvtCLKP
field = "Integral Gain", vvtCLKI
field = "Differential Gain", vvtCLKD
@ -5041,8 +5044,8 @@ cmdVSSratio6 = "E\x99\x06"
entry = hardLimitOn , "Hard Limiter", int, "%d"
entry = idleControlOn, "Idle Control", int, "%d"
entry = idleLoad, "IAC value", int, "%d"
entry = CLIdleTarget, "Idle Target RPM", int, "%%d", { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || idleAdvEnabled >= 1 } ;Only show for closed loop idle modes and if idle advance is enabled
entry = CLIdleDelta, "Idle RPM Delta", int, "%d", { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || idleAdvEnabled >= 1 } ;Only show for closed loop idle modes and if idle advance is enabled
entry = CLIdleTarget, "Idle Target RPM", int, "%%d", { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 || idleAdvEnabled >= 1 } ;Only show for closed loop idle modes and if idle advance is enabled
entry = CLIdleDelta, "Idle RPM Delta", int, "%d", { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 || idleAdvEnabled >= 1 } ;Only show for closed loop idle modes and if idle advance is enabled
entry = baro, "Baro Pressure", int, "%d"
entry = nitrousOn, "Nitrous", int, "%d", { n2o_enable > 0 }
entry = fanStatus, "Fan", int, "%d"

View File

@ -12,6 +12,7 @@
#define IAC_ALGORITHM_STEP_OL 4
#define IAC_ALGORITHM_STEP_CL 5
#define IAC_ALGORITHM_PWM_OLCL 6 //Openloop plus closedloop IAC control
#define IAC_ALGORITHM_STEP_OLCL 7 //Openloop plus closedloop IAC control
#define STEPPER_FORWARD 0
#define STEPPER_BACKWARD 1
@ -51,6 +52,7 @@ volatile PORT_TYPE *idleUpOutput_pin_port;
volatile PINMASK_TYPE idleUpOutput_pin_mask;
volatile bool idle_pwm_state;
bool lastDFCOValue;
unsigned int idle_pwm_max_count; //Used for variable PWM frequency
volatile unsigned int idle_pwm_cur_value;
long idle_pid_target_value;

View File

@ -26,7 +26,7 @@ static inline void enableIdle()
{
IDLE_TIMER_ENABLE();
}
else if ( (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OL) )
else if ( (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OLCL) )
{
}
@ -85,6 +85,7 @@ void initialiseIdle()
break;
case IAC_ALGORITHM_PWM_OLCL:
//Case 6 is PWM closed loop with open loop table used as feed forward
iacPWMTable.xSize = 10;
iacPWMTable.valueSize = SIZE_BYTE;
iacPWMTable.axisSize = SIZE_BYTE;
@ -113,7 +114,8 @@ void initialiseIdle()
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
idle_pid_target_value = 0;
idlePID.Initialize();
idleCounter = 0;
break;
@ -142,8 +144,10 @@ void initialiseIdle()
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
idle_pid_target_value = table2D_getValue(&iacCrankDutyTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET);
idlePID.Initialize();
idleCounter = 0;
break;
case IAC_ALGORITHM_STEP_OL:
@ -162,9 +166,14 @@ void initialiseIdle()
iacStepTime_uS = configPage6.iacStepTime * 1000;
iacCoolTime_uS = configPage9.iacCoolTime * 1000;
completedHomeSteps = 0;
idleStepper.curIdleStep = 0;
idleStepper.stepperStatus = SOFF;
if( completedHomeSteps < (configPage6.iacStepHome * 3) )
{
//Change between modes running make engine stall
completedHomeSteps = 0;
idleStepper.curIdleStep = 0;
idleStepper.stepperStatus = SOFF;
}
if (! configPage9.iacStepperInv)
{
idleStepper.lessAirDirection = STEPPER_BACKWARD;
@ -194,10 +203,13 @@ void initialiseIdle()
iacStepTime_uS = configPage6.iacStepTime * 1000;
iacCoolTime_uS = configPage9.iacCoolTime * 1000;
completedHomeSteps = 0;
idleCounter = 0;
idleStepper.curIdleStep = 0;
idleStepper.stepperStatus = SOFF;
if( completedHomeSteps < (configPage6.iacStepHome * 3) )
{
//Change between modes running make engine stall
completedHomeSteps = 0;
idleStepper.curIdleStep = 0;
idleStepper.stepperStatus = SOFF;
}
if (! configPage9.iacStepperInv)
{
@ -210,11 +222,63 @@ void initialiseIdle()
idleStepper.moreAirDirection = STEPPER_BACKWARD;
}
idlePID.SetSampleTime(100);
idlePID.SetOutputLimits(0, (configPage9.iacMaxSteps * 3)<<2); //Maximum number of steps; always less than home steps count.
idlePID.SetSampleTime(250); //4Hz means 250ms
idlePID.SetOutputLimits((configPage6.iacOLStepVal[9]*3)<<1, (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
configPage6.iacPWMrun = false; // just in case. This needs to be false with stepper idle
idle_pid_target_value = table2D_getValue(&iacClosedLoopTable, (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET)) * 3;
idlePID.Initialize();
break;
case IAC_ALGORITHM_STEP_OLCL:
//Case 7 is Stepper closed loop with open loop table used as feed forward
iacStepTable.xSize = 10;
iacStepTable.valueSize = SIZE_BYTE;
iacStepTable.axisSize = SIZE_BYTE;
iacStepTable.values = configPage6.iacOLStepVal;
iacStepTable.axisX = configPage6.iacBins;
iacClosedLoopTable.xSize = 10;
iacClosedLoopTable.valueSize = SIZE_BYTE;
iacClosedLoopTable.axisSize = SIZE_BYTE;
iacClosedLoopTable.values = configPage6.iacCLValues;
iacClosedLoopTable.axisX = configPage6.iacBins;
iacCrankStepsTable.xSize = 4;
iacCrankStepsTable.valueSize = SIZE_BYTE;
iacCrankStepsTable.axisSize = SIZE_BYTE;
iacCrankStepsTable.values = configPage6.iacCrankSteps;
iacCrankStepsTable.axisX = configPage6.iacCrankBins;
iacStepTime_uS = configPage6.iacStepTime * 1000;
iacCoolTime_uS = configPage9.iacCoolTime * 1000;
if( completedHomeSteps < (configPage6.iacStepHome * 3) )
{
//Change between modes running make engine stall
completedHomeSteps = 0;
idleStepper.curIdleStep = 0;
idleStepper.stepperStatus = SOFF;
}
if (! configPage9.iacStepperInv)
{
idleStepper.lessAirDirection = STEPPER_BACKWARD;
idleStepper.moreAirDirection = STEPPER_FORWARD;
}
else
{
idleStepper.lessAirDirection = STEPPER_FORWARD;
idleStepper.moreAirDirection = STEPPER_BACKWARD;
}
idlePID.SetSampleTime(250); //4Hz means 250ms
idlePID.SetOutputLimits((configPage6.iacOLStepVal[9]*3)<<1, (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
configPage6.iacPWMrun = false; // just in case. This needs to be false with stepper idle
idle_pid_target_value = 0;
idlePID.Initialize();
break;
default:
@ -504,7 +568,7 @@ void idleControl()
idle_pid_target_value = idle_pwm_target_value << 2; //Resolution increased
idlePID.Initialize(); //Update output to smooth transition
}
else
else
{
//Read the OL table as feedforward term
FeedForwardTerm = percentage(table2D_getValue(&iacPWMTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET), idle_pwm_max_count<<2); //All temps are offset by 40 degrees
@ -542,7 +606,7 @@ void idleControl()
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!
{
//Check for cranking pulsewidth
if( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) )
if( !BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN) ) //If ain't running it means off or cranking
{
//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
@ -559,9 +623,7 @@ void idleControl()
else
{
//Standard running
//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 (BIT_CHECK(LOOP_TIMER, BIT_TIMER_4HZ) && (currentStatus.RPM > 0))
if (BIT_CHECK(LOOP_TIMER, BIT_TIMER_10HZ) && (currentStatus.RPM > 0))
{
if ( runSecsX10 < configPage2.idleTaperTime )
{
@ -595,11 +657,12 @@ void idleControl()
else { BIT_CLEAR(currentStatus.spark, BIT_SPARK_IDLE); }
break;
case IAC_ALGORITHM_STEP_OLCL: //Case 7 is closed+open loop stepper control
case IAC_ALGORITHM_STEP_CL: //Case 5 is closed loop stepper control
//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) )
if( !BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN) ) //If ain't running it means off or cranking
{
//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
@ -613,45 +676,78 @@ void idleControl()
doStep();
idle_pid_target_value = idleStepper.targetIdleStep << 2; //Resolution increased
idlePID.Initialize(); //Update output to smooth transition
idlePID.ResetIntegeral();
FeedForwardTerm = idle_pid_target_value;
}
else
{
if( (idleCounter & 31) == 1)
if( BIT_CHECK(LOOP_TIMER, BIT_TIMER_10HZ) )
{
//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; //Multiply the byte target value back out by 10
if( runSecsX10 < configPage2.idleTaperTime )
{
uint16_t minValue = table2D_getValue(&iacCrankStepsTable, (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET)) * 3;
if( idle_pid_target_value < minValue<<2 ) { idle_pid_target_value = minValue<<2; }
uint16_t maxValue = idle_pid_target_value>>2;
if( configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OLCL ) { maxValue = table2D_getValue(&iacStepTable, (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET)) * 3; }
//Tapering between cranking IAC value and running
FeedForwardTerm = map(runSecsX10, 0, configPage2.idleTaperTime, minValue, maxValue)<<2;
idle_pid_target_value = FeedForwardTerm;
}
else if (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OLCL)
{
//Standard running
FeedForwardTerm = (table2D_getValue(&iacStepTable, (currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET)) * 3)<<2; //All temps are offset by 40 degrees. Step counts are divided by 3 in TS. Multiply back out here
//reset integeral to zero when TPS is bigger than set value in TS (opening throttle so not idle anymore). OR when RPM higher than Idle Target + RPM Histeresis (comming back from high rpm with throttle closed)
if (((currentStatus.RPM - idle_cl_target_rpm) > configPage2.iacRPMlimitHysteresis*10) || (currentStatus.TPS > configPage2.iacTPSlimit) || lastDFCOValue )
{
idlePID.ResetIntegeral();
}
}
else { FeedForwardTerm = idle_pid_target_value; }
}
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
PID_computed = idlePID.Compute(true, FeedForwardTerm);
//limit to the configured max steps. This must include any idle up adder, to prevent over-opening.
if (idleStepper.targetIdleStep > (configPage9.iacMaxSteps * 3) )
//If DFCO conditions are met keep output from changing
if( (currentStatus.TPS > configPage2.iacTPSlimit) || lastDFCOValue
|| ((configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OLCL) && (runSecsX10 < configPage2.idleTaperTime)) )
{
idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3;
idle_pid_target_value = FeedForwardTerm;
}
idleStepper.targetIdleStep = idle_pid_target_value>>2; //Increase resolution
doStep();
idleCounter++;
}
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();
if( ( (uint16_t)configPage9.iacMaxSteps * 3) > 255 ) { currentStatus.idleLoad = idleStepper.curIdleStep / 2; }//Current step count (Divided by 2 for byte)
else { currentStatus.idleLoad = idleStepper.curIdleStep; }
}
//Set or clear the idle active flag
if(idleStepper.targetIdleStep != idleStepper.curIdleStep) { BIT_SET(currentStatus.spark, BIT_SPARK_IDLE); }
else { BIT_CLEAR(currentStatus.spark, BIT_SPARK_IDLE); }
if (BIT_CHECK(LOOP_TIMER, BIT_TIMER_1HZ)) //Use timer flag instead idle count
{
//This only needs to be run very infrequently, once per second
idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD);
iacStepTime_uS = configPage6.iacStepTime * 1000;
iacCoolTime_uS = configPage9.iacCoolTime * 1000;
}
break;
default:
//There really should be a valid idle type
break;
}
lastDFCOValue = BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO);
}
@ -663,7 +759,7 @@ void disableIdle()
IDLE_TIMER_DISABLE();
digitalWrite(pinIdle1, LOW);
}
else if ((configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OL) )
else if( (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OLCL) )
{
//Only disable the stepper motor if homing is completed
if( (checkForStepping() == false) && (isStepperHomed() == true) )
@ -680,6 +776,7 @@ void disableIdle()
{
idleStepper.targetIdleStep = configPage9.iacMaxSteps * 3;
}
idle_pid_target_value = idleStepper.targetIdleStep<<2;
}
}
BIT_CLEAR(currentStatus.spark, BIT_SPARK_IDLE); //Turn the idle control flag off

View File

@ -408,7 +408,12 @@ void loop()
} //1Hz timer
if( (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_CL) ) { idleControl(); } //Run idlecontrol every loop for stepper idle.
if( (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OL)
|| (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_CL)
|| (configPage6.iacAlgorithm == IAC_ALGORITHM_STEP_OLCL) )
{
idleControl(); //Run idlecontrol every loop for stepper idle.
}
//VE and advance calculation were moved outside the sync/RPM check so that the fuel and ignition load value will be accurately shown when RPM=0