Steper OL+CL mode (#554)
This commit is contained in:
parent
8b262a0087
commit
1536b9196d
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue