diff --git a/firmware/config/stm32f4ems/efifeatures.h b/firmware/config/stm32f4ems/efifeatures.h index f89e57bd28..f516422eaa 100644 --- a/firmware/config/stm32f4ems/efifeatures.h +++ b/firmware/config/stm32f4ems/efifeatures.h @@ -130,6 +130,8 @@ #define EFI_IDLE_CONTROL TRUE +#define EFI_IDLE_INCREMENTAL_PID_CIC FALSE + /** * Control the main power relay based on measured ignition voltage (Vbatt) */ diff --git a/firmware/config/stm32f7ems/efifeatures.h b/firmware/config/stm32f7ems/efifeatures.h index 7214a177ba..d0294daa79 100644 --- a/firmware/config/stm32f7ems/efifeatures.h +++ b/firmware/config/stm32f7ems/efifeatures.h @@ -126,6 +126,8 @@ #define EFI_IDLE_CONTROL TRUE +#define EFI_IDLE_INCREMENTAL_PID_CIC FALSE + /** * Control the main power relay based on measured ignition voltage (Vbatt) */ diff --git a/firmware/controllers/idle_thread.cpp b/firmware/controllers/idle_thread.cpp index 9846cf56af..8304a6b25b 100644 --- a/firmware/controllers/idle_thread.cpp +++ b/firmware/controllers/idle_thread.cpp @@ -45,7 +45,12 @@ EXTERN_ENGINE static bool shouldResetPid = false; +#if EFI_IDLE_INCREMENTAL_PID_CIC || defined(__DOXYGEN__) +// Use new PID with CIC integrator +static PidCic idlePid(&engineConfiguration->idleRpmPid); +#else static Pid idlePid(&engineConfiguration->idleRpmPid); +#endif /* EFI_IDLE_INCREMENTAL_PID_CIC */ // todo: extract interface for idle valve hardware, with solenoid and stepper implementations? static SimplePwm idleSolenoid; @@ -59,6 +64,10 @@ static float lastCrankingIacPosition; * that's current position with CLT and IAT corrections */ static percent_t currentIdlePosition = -100.0f; +/** + * the same as currentIdlePosition, but without adjustments (iacByTpsTaper, afterCrankingIACtaperDuration) + */ +static percent_t baseIdlePosition = currentIdlePosition; void idleDebug(const char *msg, percent_t value) { scheduleMsg(logger, "idle debug: %s%f", msg, value); @@ -155,9 +164,10 @@ percent_t getIdlePosition(void) { } static float autoIdle(float cltCorrection) { - if (getTPS(PASS_ENGINE_PARAMETER_SIGNATURE) > boardConfiguration->idlePidDeactivationTpsThreshold) { - // just leave IAC position as is - return currentIdlePosition; + percent_t tpsPos = getTPS(PASS_ENGINE_PARAMETER_SIGNATURE); + if (tpsPos > boardConfiguration->idlePidDeactivationTpsThreshold) { + // just leave IAC position as is (but don't return currentIdlePosition - it may already contain additionalAir) + return baseIdlePosition; } // get Target RPM for Auto-PID from a separate table @@ -172,6 +182,16 @@ static float autoIdle(float cltCorrection) { percent_t newValue = idlePid.getValue(targetRpm, getRpmE(engine), engineConfiguration->idleRpmPid.period); +#if EFI_IDLE_INCREMENTAL_PID_CIC || defined(__DOXYGEN__) + // Treat the 'newValue' as if it contains not an actual IAC position, but an incremental delta. + // So we add this delta to the base IAC position, with a smooth taper for TPS transients. + newValue = baseIdlePosition + interpolateClamped(0.0f, newValue, boardConfiguration->idlePidDeactivationTpsThreshold, 0.0f, tpsPos); + + // apply the PID limits + newValue = maxF(newValue, CONFIG(idleRpmPid.minValue)); + newValue = minF(newValue, CONFIG(idleRpmPid.maxValue)); +#endif /* EFI_IDLE_INCREMENTAL_PID_CIC */ + return newValue; } @@ -212,19 +232,28 @@ static msg_t ivThread(int param) { undoIdleBlipIfNeeded(); float clt = engine->sensors.clt; - float cltCorrection = cisnan(clt) ? 1 : interpolate2d("cltT", clt, config->cltIdleCorrBins, config->cltIdleCorr, - CLT_CURVE_SIZE) / PERCENT_MULT; + bool isRunning = engine->rpmCalculator.isRunning(PASS_ENGINE_PARAMETER_SIGNATURE); + float cltCorrection; + if (cisnan(clt)) + cltCorrection = 1.0f; + // Use separate CLT correction table for cranking + else if (engineConfiguration->overrideCrankingIacSetting && !isRunning) + cltCorrection = interpolate2d("cltCrankingT", clt, config->cltCrankingCorrBins, config->cltCrankingCorr, CLT_CRANKING_CURVE_SIZE) / PERCENT_MULT; + else + cltCorrection = interpolate2d("cltT", clt, config->cltIdleCorrBins, config->cltIdleCorr, CLT_CURVE_SIZE) / PERCENT_MULT; float iacPosition; if (timeToStopBlip != 0) { iacPosition = blipIdlePosition; - } else if (!engine->rpmCalculator.isRunning(PASS_ENGINE_PARAMETER_SIGNATURE)) { + baseIdlePosition = iacPosition; + } else if (!isRunning) { // during cranking it's always manual mode, PID would make no sence during cranking iacPosition = cltCorrection * engineConfiguration->crankingIACposition; // save cranking position & cycles counter for taper transition lastCrankingIacPosition = iacPosition; lastCrankingCyclesCounter = engine->rpmCalculator.getRevolutionCounterSinceStart(); + baseIdlePosition = iacPosition; } else { if (engineConfiguration->idleMode == IM_MANUAL) { // let's re-apply CLT correction @@ -233,6 +262,9 @@ static msg_t ivThread(int param) { iacPosition = autoIdle(cltCorrection); } + // store 'base' iacPosition without adjustments + baseIdlePosition = iacPosition; + percent_t tpsPos = getTPS(PASS_ENGINE_PARAMETER_SIGNATURE); float additionalAir = (float)engineConfiguration->iacByTpsTaper; iacPosition += interpolateClamped(0.0f, 0.0f, boardConfiguration->idlePidDeactivationTpsThreshold, additionalAir, tpsPos); diff --git a/firmware/tunerstudio/rusefi.input b/firmware/tunerstudio/rusefi.input index 7aed81d51d..10dc80b5da 100644 --- a/firmware/tunerstudio/rusefi.input +++ b/firmware/tunerstudio/rusefi.input @@ -1507,8 +1507,8 @@ cmd_stop_engine = "w\x00\x99\x00\x00" field = "Use separate Advance Table for idle", useSeparateAdvanceForIdle field = "Use separate VE Table for idle", useSeparateVeForIdle field = "Cranking Idle Air", crankingIACposition - field = "# Warmup Idle multipplier is apploed to target RPM" - field = "Auto target", targetIdleRpm, { idleMode == 0} +; field = "# Warmup Idle multipplier is apploed to target RPM" +; field = "Auto target", targetIdleRpm, { idleMode == 0} field = "idle P", idleRpmPid_pFactor, { idleMode == 0} field = "idle I", idleRpmPid_iFactor, { idleMode == 0} field = "idle D", idleRpmPid_dFactor, { idleMode == 0} diff --git a/simulator/simulator/efifeatures.h b/simulator/simulator/efifeatures.h index 190c192fbb..7d66ca4408 100644 --- a/simulator/simulator/efifeatures.h +++ b/simulator/simulator/efifeatures.h @@ -56,6 +56,7 @@ #define EFI_ENGINE_CONTROL TRUE #define EFI_IDLE_CONTROL FALSE +#define EFI_IDLE_INCREMENTAL_PID_CIC FALSE #define EFI_MAIN_RELAY_CONTROL FALSE #define EFI_HIP_9011 FALSE #define EFI_ELECTRONIC_THROTTLE_BODY FALSE