diff --git a/firmware/controllers/actuators/idle_thread.cpp b/firmware/controllers/actuators/idle_thread.cpp index b76fafd06d..955e3ae0ad 100644 --- a/firmware/controllers/actuators/idle_thread.cpp +++ b/firmware/controllers/actuators/idle_thread.cpp @@ -268,6 +268,12 @@ float IdleController::getOpenLoop(Phase phase, float clt, SensorResult tps) cons return cranking; } + // If coasting (and enabled), use the coasting position table instead of normal open loop + // TODO: this should be a table of open loop mult vs. RPM, not vs. clt + if (CONFIG(useIacTableForCoasting) && phase == Phase::Coasting) { + return interpolate2d(clt, CONFIG(iacCoastingBins), CONFIG(iacCoasting)); + } + // Interpolate between cranking and running over a short time // This clamps once you fall off the end, so no explicit check for running required auto revsSinceStart = engine->rpmCalculator.getRevolutionCounterSinceStart(); diff --git a/firmware/controllers/actuators/idle_thread.h b/firmware/controllers/actuators/idle_thread.h index 2b5919cbed..a69635ce41 100644 --- a/firmware/controllers/actuators/idle_thread.h +++ b/firmware/controllers/actuators/idle_thread.h @@ -26,6 +26,7 @@ struct IIdleController { virtual float getCrankingOpenLoop(float clt) const = 0; virtual float getRunningOpenLoop(float clt, SensorResult tps) const = 0; virtual float getOpenLoop(Phase phase, float clt, SensorResult tps) const = 0; + virtual float getClosedLoop(Phase phase, float tps, int rpm, int target) = 0; }; class IdleController : public IIdleController { @@ -52,7 +53,7 @@ public: float getIdleTimingAdjustment(int rpm, int targetRpm, Phase phase); // CLOSED LOOP CORRECTION - float getClosedLoop(IIdleController::Phase phase, float tpsPos, int rpm, int targetRpm); + float getClosedLoop(IIdleController::Phase phase, float tpsPos, int rpm, int targetRpm) override; // Allow querying state from outside bool isIdling() { diff --git a/unit_tests/tests/test_idle_controller.cpp b/unit_tests/tests/test_idle_controller.cpp index 7980b25f3b..3c18aa9b03 100644 --- a/unit_tests/tests/test_idle_controller.cpp +++ b/unit_tests/tests/test_idle_controller.cpp @@ -270,6 +270,22 @@ TEST(idle_v2, openLoopRunningTaper) { EXPECT_FLOAT_EQ(25, dut.getOpenLoop(ICP::Idling, 30, 0)); } +TEST(idle_v2, openLoopCoastingTable) { + WITH_ENGINE_TEST_HELPER(TEST_ENGINE); + IdleController dut; + INJECT_ENGINE_REFERENCE(&dut); + + // enable & configure feature + CONFIG(useIacTableForCoasting) = true; + for (size_t i = 0; i < CLT_CURVE_SIZE; i++) { + CONFIG(iacCoastingBins)[i] = 10 * i; + CONFIG(iacCoasting)[i] = 5 * i; + } + + EXPECT_FLOAT_EQ(10, dut.getOpenLoop(ICP::Coasting, 20, 0)); + EXPECT_FLOAT_EQ(20, dut.getOpenLoop(ICP::Coasting, 40, 0)); +} + extern int timeNowUs; TEST(idle_v2, closedLoopBasic) {