From 0a7cd2b08c3fe505359fc29c6ef2af04aaa81f90 Mon Sep 17 00:00:00 2001 From: Patryk Chmura <79016748+pchmura4@users.noreply.github.com> Date: Tue, 24 Oct 2023 23:43:29 +0200 Subject: [PATCH] Closed Loop Idle Ignition Timing small improvements (#5635) * After-start enrichment handling more similar to OEM and other Standalone EFI systems * Corrections and tidying-up * Corrected small mistake in TunerStudio definition * Compatibility fixes * Readability fix * Changed to more appropriate cycles instead of seconds, bugfix for TS * Typo fix... * Idle Ignition Timing improvements * Uninitialized variable for Unit Tests? * Zero value should disable new feature --------- Co-authored-by: pchmura4 <> --- firmware/CHANGELOG.md | 4 +++- firmware/controllers/actuators/idle_thread.cpp | 11 +++++++++++ firmware/controllers/actuators/idle_thread.h | 3 +++ firmware/integration/rusefi_config.txt | 1 + firmware/tunerstudio/rusefi.input | 3 +++ unit_tests/tests/test_idle_controller.cpp | 1 + 6 files changed, 22 insertions(+), 1 deletion(-) diff --git a/firmware/CHANGELOG.md b/firmware/CHANGELOG.md index e4b317e0ea..76bb73b4c3 100644 --- a/firmware/CHANGELOG.md +++ b/firmware/CHANGELOG.md @@ -34,7 +34,9 @@ Release template (copy/paste this for new release): ### Added - DAC with Lua #5601 - - TunerStudio cacerts fix script #5536 + - TunerStudio cacerts fix script #5536 + - Idle Timing Control - Soft Entry mechanism, in case of aggresive PID tuning this can help when engine enters close loop idle + - Idle Timing Control - I factor configurable now ### Fixed - Changing idle stepper settings causes kernel panic diff --git a/firmware/controllers/actuators/idle_thread.cpp b/firmware/controllers/actuators/idle_thread.cpp index 96807f306b..7dfecba244 100644 --- a/firmware/controllers/actuators/idle_thread.cpp +++ b/firmware/controllers/actuators/idle_thread.cpp @@ -187,8 +187,19 @@ float IdleController::getIdleTimingAdjustment(int rpm, int targetRpm, Phase phas if (phase != Phase::Idling) { m_timingPid.reset(); return 0; + } else { + // If we are entering idle, and the PID settings are aggressive, it's good to make a soft entry upon entering closed loop + if (m_lastPhase == Phase::CrankToIdleTaper) { + m_crankTaperEndTime = engine->fuelComputer.running.timeSinceCrankingInSecs; + m_idleTimingSoftEntryEndTime = m_crankTaperEndTime + engineConfiguration->idleTimingSoftEntryTime; + } + if (engineConfiguration->idleTimingSoftEntryTime > 0.0f) { + // Use interpolation for correction taper + m_timingPid.setErrorAmplification(interpolateClamped(m_crankTaperEndTime, 0.0f, m_idleTimingSoftEntryEndTime, 1.0f, engine->fuelComputer.running.timeSinceCrankingInSecs)); + } } + // We're now in the idle mode, and RPM is inside the Timing-PID regulator work zone! return m_timingPid.getOutput(targetRpm, rpm, FAST_CALLBACK_PERIOD_MS / 1000.0f); } diff --git a/firmware/controllers/actuators/idle_thread.h b/firmware/controllers/actuators/idle_thread.h index e430e04561..026b457f82 100644 --- a/firmware/controllers/actuators/idle_thread.h +++ b/firmware/controllers/actuators/idle_thread.h @@ -95,6 +95,9 @@ private: efitimeus_t restoreAfterPidResetTimeUs = 0; // used by 'dashpot' (hold+decay) logic for iacByTpsTaper efitimeus_t lastTimeRunningUs = 0; + // used by "soft" idle entry + float m_crankTaperEndTime = 0.0f; + float m_idleTimingSoftEntryEndTime = 0.0f; // This is stored by getClosedLoop and used in case we want to "do nothing" float m_lastAutomaticPosition = 0; diff --git a/firmware/integration/rusefi_config.txt b/firmware/integration/rusefi_config.txt index ed9e4eeab8..1f8a354022 100644 --- a/firmware/integration/rusefi_config.txt +++ b/firmware/integration/rusefi_config.txt @@ -1355,6 +1355,7 @@ tChargeMode_e tChargeMode; int16_t etb_iTermMax;iTerm max value;"", 1, 0, -30000, 30000, 0 pid_s idleTimingPid;See useIdleTimingPidControl + float idleTimingSoftEntryTime int16_t etbRocExpAverageLength;By the way ETB PID runs at 500hz, length in 1/500 of second here. diff --git a/firmware/tunerstudio/rusefi.input b/firmware/tunerstudio/rusefi.input index 3d03f9afe9..164931372d 100644 --- a/firmware/tunerstudio/rusefi.input +++ b/firmware/tunerstudio/rusefi.input @@ -3465,11 +3465,14 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_ field = "#Gain is in degrees advance per rpm away from target" field = "#A good starting point is 0.1 = 10 deg per 100 rpm" field = "Proportional gain", idleTimingPid_pFactor, {useIdleTimingPidControl == 1} + field = "Integral gain", idleTimingPid_iFactor, {useIdleTimingPidControl == 1} field = "Derivative gain", idleTimingPid_dFactor, {useIdleTimingPidControl == 1} field = "" field = "Min adjustment (retard)", idleTimingPid_minValue, {useIdleTimingPidControl == 1} field = "Max adjustment (advance)", idleTimingPid_maxValue, {useIdleTimingPidControl == 1} field = "" + field = "Soft entry time", idleTimingSoftEntryTime, {useIdleTimingPidControl == 1} + field = "" field = "#Use debug mode 'Timing' to view idle timing adjustment" ; Engine->Fan Settings diff --git a/unit_tests/tests/test_idle_controller.cpp b/unit_tests/tests/test_idle_controller.cpp index b29387ed2d..2ce1742994 100644 --- a/unit_tests/tests/test_idle_controller.cpp +++ b/unit_tests/tests/test_idle_controller.cpp @@ -26,6 +26,7 @@ TEST(idle_v2, timingPid) { engineConfiguration->idleTimingPid.pFactor = 0.1; engineConfiguration->idleTimingPid.minValue = -10; engineConfiguration->idleTimingPid.maxValue = 10; + engineConfiguration->idleTimingSoftEntryTime = 0.0f; dut.init(); // Check that out of idle mode it doesn't do anything