From bdeeb82f932d91fdae86ba5f39c8ae3a18dcfa32 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Mon, 27 Mar 2023 00:42:56 -0700 Subject: [PATCH] better idle VE table transition --- firmware/controllers/algo/airmass/airmass.cpp | 9 ++++++-- .../ignition_injection/test_fuel_math.cpp | 21 +++++++++++++------ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/firmware/controllers/algo/airmass/airmass.cpp b/firmware/controllers/algo/airmass/airmass.cpp index 2de12a1bd2..0145db0f23 100644 --- a/firmware/controllers/algo/airmass/airmass.cpp +++ b/firmware/controllers/algo/airmass/airmass.cpp @@ -26,14 +26,19 @@ float AirmassVeModelBase::getVe(int rpm, float load) const { auto tps = Sensor::get(SensorType::Tps1); // get VE from the separate table for Idle if idling if (engine->module()->isIdlingOrTaper() && - tps && engineConfiguration->useSeparateVeForIdle) { + tps && engineConfiguration->useSeparateVeForIdle) { percent_t idleVe = interpolate3d( config->idleVeTable, config->idleVeLoadBins, load, config->idleVeRpmBins, rpm ); + // interpolate between idle table and normal (running) table using TPS threshold - ve = interpolateClamped(0.0f, idleVe, engineConfiguration->idlePidDeactivationTpsThreshold, ve, tps.Value); + // 0 TPS -> idle table + // 1/2 threshold -> idle table + // idle threshold -> normal table + float idleThreshold = engineConfiguration->idlePidDeactivationTpsThreshold; + ve = interpolateClamped(idleThreshold / 2, idleVe, idleThreshold, ve, tps.Value); } #endif // EFI_IDLE_CONTROL diff --git a/unit_tests/tests/ignition_injection/test_fuel_math.cpp b/unit_tests/tests/ignition_injection/test_fuel_math.cpp index b2d53ae1c1..0db8b9b5b0 100644 --- a/unit_tests/tests/ignition_injection/test_fuel_math.cpp +++ b/unit_tests/tests/ignition_injection/test_fuel_math.cpp @@ -271,11 +271,20 @@ TEST(FuelMath, IdleVeTable) { idler.isIdling = true; EXPECT_FLOAT_EQ(dut.getVe(1000, 50), 0.4f); + // Below half threshold, fully use idle VE table + Sensor::setMockValue(SensorType::Tps1, 0); + EXPECT_FLOAT_EQ(dut.getVe(1000, 50), 0.4f); + Sensor::setMockValue(SensorType::Tps1, 2); + EXPECT_FLOAT_EQ(dut.getVe(1000, 50), 0.4f); + Sensor::setMockValue(SensorType::Tps1, 5); + EXPECT_FLOAT_EQ(dut.getVe(1000, 50), 0.4f); + // As TPS approaches idle threshold, phase-out the idle VE table - Sensor::setMockValue(SensorType::Tps1, 2.5f); - EXPECT_FLOAT_EQ(dut.getVe(1000, 50), 0.425f); - Sensor::setMockValue(SensorType::Tps1, 5.0f); - EXPECT_FLOAT_EQ(dut.getVe(1000, 50), 0.45f); - Sensor::setMockValue(SensorType::Tps1, 7.5f); - EXPECT_FLOAT_EQ(dut.getVe(1000, 50), 0.475f); + + Sensor::setMockValue(SensorType::Tps1, 6); + EXPECT_FLOAT_EQ(dut.getVe(1000, 50), 0.42f); + Sensor::setMockValue(SensorType::Tps1, 8); + EXPECT_FLOAT_EQ(dut.getVe(1000, 50), 0.46f); + Sensor::setMockValue(SensorType::Tps1, 10); + EXPECT_FLOAT_EQ(dut.getVe(1000, 50), 0.5f); }