diff --git a/firmware/controllers/actuators/idle_thread.cpp b/firmware/controllers/actuators/idle_thread.cpp index 94b81b97b0..1411a82e0b 100644 --- a/firmware/controllers/actuators/idle_thread.cpp +++ b/firmware/controllers/actuators/idle_thread.cpp @@ -193,6 +193,14 @@ void setManualIdleValvePosition(int positionPercent) { #endif /* EFI_UNIT_TEST */ +int IdleController::getTargetRpm(float clt) const { + // TODO: bump target rpm based on AC and/or fan(s)? + + float fsioBump = engine->fsioState.fsioIdleTargetRPMAdjustment; + + return fsioBump + interpolate2d("cltRpm", clt, CONFIG(cltIdleRpmBins), CONFIG(cltIdleRpm)); +} + static percent_t manualIdleController(float cltCorrection DECLARE_ENGINE_PARAMETER_SUFFIX) { percent_t correctedPosition = cltCorrection * CONFIG(manIdlePosition); @@ -269,7 +277,7 @@ static percent_t automaticIdleController(float tpsPos DECLARE_ENGINE_PARAMETER_S industrialWithOverrideIdlePid.derivativeFilterLoss = engineConfiguration->idle_derivativeFilterLoss; // get Target RPM for Auto-PID from a separate table - int targetRpm = getTargetRpmForIdleCorrection(PASS_ENGINE_PARAMETER_SIGNATURE); + int targetRpm = ENGINE(idleController)->getTargetRpm(Sensor::get(SensorType::Clt).value_or(0)); efitick_t nowNt = getTimeNowNt(); efitimeus_t nowUs = getTimeNowUs(); @@ -580,6 +588,8 @@ void startIdleThread(Logging*sharedLogger DECLARE_ENGINE_PARAMETER_SUFFIX) { INJECT_ENGINE_REFERENCE(&idleControllerInstance); INJECT_ENGINE_REFERENCE(&industrialWithOverrideIdlePid); + ENGINE(idleController) = &idleControllerInstance; + getIdlePid(PASS_ENGINE_PARAMETER_SIGNATURE)->initPidClass(&engineConfiguration->idleRpmPid); #if ! EFI_UNIT_TEST diff --git a/firmware/controllers/actuators/idle_thread.h b/firmware/controllers/actuators/idle_thread.h index cfc53b0069..9324acc51a 100644 --- a/firmware/controllers/actuators/idle_thread.h +++ b/firmware/controllers/actuators/idle_thread.h @@ -12,15 +12,23 @@ #include "rusefi_types.h" #include "periodic_task.h" +struct IIdleController { + virtual int getTargetRpm(float clt) const = 0; +}; + class Logging; class Pid; -class IdleController { + +class IdleController : public IIdleController { public: DECLARE_ENGINE_PTR; float getIdlePosition(); void update(); + + // TARGET DETERMINATION + int getTargetRpm(float clt) const override; }; void updateIdleControl(); diff --git a/firmware/controllers/algo/advance_map.cpp b/firmware/controllers/algo/advance_map.cpp index 2760a431dc..4c703377f9 100644 --- a/firmware/controllers/algo/advance_map.cpp +++ b/firmware/controllers/algo/advance_map.cpp @@ -128,7 +128,7 @@ angle_t getAdvanceCorrections(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX) { // PID Ignition Advance angle correction float pidTimingCorrection = 0.0f; if (CONFIG(useIdleTimingPidControl)) { - int targetRpm = getTargetRpmForIdleCorrection(PASS_ENGINE_PARAMETER_SIGNATURE); + int targetRpm = ENGINE(idleController)->getTargetRpm(Sensor::get(SensorType::Clt).value_or(0)); int rpmDelta = absI(rpm - targetRpm); auto [valid, tps] = Sensor::get(SensorType::Tps1); diff --git a/firmware/controllers/algo/engine.h b/firmware/controllers/algo/engine.h index 9e77022dd9..cd34b4ed9e 100644 --- a/firmware/controllers/algo/engine.h +++ b/firmware/controllers/algo/engine.h @@ -54,6 +54,7 @@ class AirmassModelBase; class IEtbController; struct IFuelComputer; struct IInjectorModel; +struct IIdleController; class PrimaryTriggerConfiguration final : public TriggerConfiguration { public: @@ -85,6 +86,7 @@ public: IEtbController *etbControllers[ETB_COUNT] = {nullptr}; IFuelComputer *fuelComputer = nullptr; IInjectorModel *injectorModel = nullptr; + IIdleController* idleController = nullptr; cyclic_buffer triggerErrorDetection; diff --git a/firmware/controllers/algo/engine_configuration.cpp b/firmware/controllers/algo/engine_configuration.cpp index 4f323e0354..a7139e018a 100644 --- a/firmware/controllers/algo/engine_configuration.cpp +++ b/firmware/controllers/algo/engine_configuration.cpp @@ -583,15 +583,6 @@ void setTargetRpmCurve(int rpm DECLARE_CONFIG_PARAMETER_SUFFIX) { setLinearCurve(engineConfiguration->cltIdleRpm, rpm, rpm, 10); } -int getTargetRpmForIdleCorrection(DECLARE_ENGINE_PARAMETER_SIGNATURE) { - // error is already reported, let's take the value at 0C since that should be a nice high idle - float clt = Sensor::get(SensorType::Clt).value_or(0); - - int targetRpm = interpolate2d("cltRpm", clt, CONFIG(cltIdleRpmBins), CONFIG(cltIdleRpm)); - - return targetRpm + engine->fsioState.fsioIdleTargetRPMAdjustment; -} - void setDefaultMultisparkParameters(DECLARE_ENGINE_PARAMETER_SIGNATURE) { // 1ms spark + 2ms dwell engineConfiguration->multisparkSparkDuration = 1000; diff --git a/firmware/controllers/algo/engine_configuration.h b/firmware/controllers/algo/engine_configuration.h index 72426b4d5f..6bbb555e1c 100644 --- a/firmware/controllers/algo/engine_configuration.h +++ b/firmware/controllers/algo/engine_configuration.h @@ -26,7 +26,6 @@ void setOperationMode(engine_configuration_s *engineConfiguration, operation_mod void prepareVoidConfiguration(engine_configuration_s *activeConfiguration); void setTargetRpmCurve(int rpm DECLARE_CONFIG_PARAMETER_SUFFIX); -int getTargetRpmForIdleCorrection(DECLARE_ENGINE_PARAMETER_SIGNATURE); void setLambdaMap(lambda_table_t table, float value); /** * See also setLinearCurve() diff --git a/unit_tests/tests/test_idle_controller.cpp b/unit_tests/tests/test_idle_controller.cpp index d729336dd6..7dc679e9d8 100644 --- a/unit_tests/tests/test_idle_controller.cpp +++ b/unit_tests/tests/test_idle_controller.cpp @@ -130,3 +130,17 @@ TEST(idle, timingPid) { ASSERT_FLOAT_EQ(-5.0f, corr) << "getAdvanceCorrections#7"; } + +TEST(idle_v2, testTargetRpm) { + WITH_ENGINE_TEST_HELPER(TEST_ENGINE); + IdleController dut; + INJECT_ENGINE_REFERENCE(&dut); + + for (size_t i = 0; i < efi::size(engineConfiguration->cltIdleRpmBins); i++) { + CONFIG(cltIdleRpmBins)[i] = i * 10; + CONFIG(cltIdleRpm)[i] = i * 100; + } + + EXPECT_FLOAT_EQ(100, dut.getTargetRpm(10)); + EXPECT_FLOAT_EQ(500, dut.getTargetRpm(50)); +}