From 60b9ddeb1eeb8b5a039a50f253858c804411fd2c Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Thu, 27 Jan 2022 11:05:18 -0800 Subject: [PATCH] vss based dfco (#3845) * vss based dfco * fix digits while we're here * fix some other digits for fun * don't use custom assert * simplify test * less than or equal, test vss behavior * even better than comments are tooltips --- firmware/controllers/algo/fuel/dfco.cpp | 16 +++++-- firmware/integration/rusefi_config.txt | 12 +++-- firmware/tunerstudio/rusefi.input | 6 ++- .../tests/ignition_injection/test_fuelCut.cpp | 47 ++++++++++++++++--- 4 files changed, 62 insertions(+), 19 deletions(-) diff --git a/firmware/controllers/algo/fuel/dfco.cpp b/firmware/controllers/algo/fuel/dfco.cpp index fb9d7ad990..da25641ec8 100644 --- a/firmware/controllers/algo/fuel/dfco.cpp +++ b/firmware/controllers/algo/fuel/dfco.cpp @@ -5,7 +5,6 @@ bool DfcoController::getState() const { return false; } - auto rpm = Sensor::getOrZero(SensorType::Rpm); const auto [tpsValid, tpsPos] = Sensor::get(SensorType::DriverThrottleIntent); const auto [cltValid, clt] = Sensor::get(SensorType::Clt); const auto [mapValid, map] = Sensor::get(SensorType::Map); @@ -15,6 +14,9 @@ bool DfcoController::getState() const { return false; } + float rpm = Sensor::getOrZero(SensorType::Rpm); + float vss = Sensor::getOrZero(SensorType::VehicleSpeed); + bool mapActivate = map < engineConfiguration->coastingFuelCutMap; bool tpsActivate = tpsPos < engineConfiguration->coastingFuelCutTps; bool cltActivate = clt > engineConfiguration->coastingFuelCutClt; @@ -24,13 +26,17 @@ bool DfcoController::getState() const { bool rpmActivate = (rpm > engineConfiguration->coastingFuelCutRpmHigh); bool rpmDeactivate = (rpm < engineConfiguration->coastingFuelCutRpmLow); - // RPM is high enough, and DFCO allowed - if (dfcoAllowed && rpmActivate) { + // greater than or equal so that it works if both config params are set to 0 + bool vssActivate = (vss >= engineConfiguration->coastingFuelCutVssHigh); + bool vssDeactivate = (vss < engineConfiguration->coastingFuelCutVssLow); + + // RPM is high enough, VSS high enough, and DFCO allowed + if (dfcoAllowed && rpmActivate && vssActivate) { return true; } - // RPM too low, or DFCO not allowed - if (!dfcoAllowed || rpmDeactivate) { + // RPM too low, VSS too low, or DFCO not allowed + if (!dfcoAllowed || rpmDeactivate || vssDeactivate) { return false; } diff --git a/firmware/integration/rusefi_config.txt b/firmware/integration/rusefi_config.txt index ccf1ee3f69..78022ff8a7 100644 --- a/firmware/integration/rusefi_config.txt +++ b/firmware/integration/rusefi_config.txt @@ -1172,16 +1172,18 @@ int16_t tps2Max;Full throttle#2. tpsMax value as 10 bit ADC value. Not Voltage!\ uint8_t autoscale tpsAccelLookback;+How long to look back for TPS-based acceleration enrichment. Increasing this time will trigger enrichment for longer when a throttle position change occurs.;"sec", 0.05, 0, 0, 5, 2 - uint8_t[3] unused1689;;"", 1,0,0,0,0 - float tpsAccelEnrichmentThreshold;+Maximum change delta of TPS percentage over the 'length'. Actual TPS change has to be above this value in order for TPS/TPS acceleration to kick in.;"roc", 1, 0, 0, 200, 3 + uint8_t coastingFuelCutVssLow;+Below this speed, disable DFCO. Use this to prevent jerkiness from fuel enable/disable in low gears.;"kph", 1, 0, 0, 255, 0 + uint8_t coastingFuelCutVssHigh;+Above this speed, allow DFCO. Use this to prevent jerkiness from fuel enable/disable in low gears.;"kph", 1, 0, 0, 255, 0 + uint8_t[1] unused1689;;"", 1,0,0,0,0 + float tpsAccelEnrichmentThreshold;+Maximum change delta of TPS percentage over the 'length'. Actual TPS change has to be above this value in order for TPS/TPS acceleration to kick in.;"roc", 1, 0, 0, 200, 1 int engineLoadAccelLength;;"cycles", 1, 0, 1, 200, 0 uint32_t uartConsoleSerialSpeed;Band rate for primary TTL;"BPs", 1, 0, 0, 1000000, 0 - float tpsDecelEnleanmentThreshold;For decel we simply multiply delta of TPS and tFor decel we do not use table?!;"roc", 1, 0, 0, 200, 3 - float tpsDecelEnleanmentMultiplier;Magic multiplier, we multiply delta of TPS and get fuel squirt duration;"coeff", 1, 0, 0, 200, 3 + float tpsDecelEnleanmentThreshold;For decel we simply multiply delta of TPS and tFor decel we do not use table?!;"roc", 1, 0, 0, 200, 1 + float tpsDecelEnleanmentMultiplier;Magic multiplier, we multiply delta of TPS and get fuel squirt duration;"coeff", 1, 0, 0, 200, 2 float slowAdcAlpha;+ExpAverage alpha coefficient;"coeff", 1, 0, 0, 200, 3 debug_mode_e debugMode;+See http://rusefi.com/s/debugmode\n\nset debug_mode X @@ -1359,7 +1361,7 @@ float[CRANKING_ADVANCE_CURVE_SIZE] crankingAdvance ;+Optional timing advance int16_t coastingFuelCutRpmHigh;+This sets the RPM above which fuel cut is active.;"rpm", 1, 0, 0, 5000, 0 int16_t coastingFuelCutRpmLow;+This sets the RPM below which fuel cut is deactivated, this prevents jerking or issues transitioning to idle;"rpm", 1, 0, 0, 5000, 0 - int16_t coastingFuelCutTps;+Throttle position below which fuel cut is active. With an electronic throttle enabled, this checks against pedal position.;"%", 1, 0, 0, 20, 1 + int16_t coastingFuelCutTps;+Throttle position below which fuel cut is active. With an electronic throttle enabled, this checks against pedal position.;"%", 1, 0, 0, 20, 0 int16_t coastingFuelCutClt;+Fuel cutoff is disabled when the engine is cold.;"C", 1, 0, -100, 100, 0 int16_t pidExtraForLowRpm;+Increases PID reaction for RPMinjectionDuration) + #define EXPECT_CUT() EXPECT_FLOAT_EQ(0, engine->injectionDuration) + // this is normal injection mode (the throttle is opened), no fuel cut-off - assertEqualsM("inj dur#1 norm", normalInjDuration, engine->injectionDuration); + EXPECT_NORMAL(); // 'releasing' the throttle Sensor::setMockValue(SensorType::DriverThrottleIntent, 0); eth.engine.periodicFastCallback(); // Fuel cut-off is enabled now - assertEqualsM("inj dur#2 cut", 0.0f, engine->injectionDuration); + EXPECT_CUT(); // Now drop the CLT below threshold Sensor::setMockValue(SensorType::Clt, engineConfiguration->coastingFuelCutClt - 1); eth.engine.periodicFastCallback(); // Fuel cut-off should be diactivated - the engine is 'cold' - assertEqualsM("inj dur#3 clt", normalInjDuration, engine->injectionDuration); + EXPECT_NORMAL(); // restore CLT Sensor::setMockValue(SensorType::Clt, hotClt); @@ -74,27 +78,56 @@ TEST(fuelCut, coasting) { eth.engine.periodicFastCallback(); // Fuel cut-off is enabled - nothing should change - assertEqualsM("inj dur#4 mid", normalInjDuration, engine->injectionDuration); + EXPECT_NORMAL(); // Now drop RPM just below RpmLow threshold Sensor::setMockValue(SensorType::Rpm, engineConfiguration->coastingFuelCutRpmLow - 1); eth.engine.periodicFastCallback(); // Fuel cut-off is now disabled (the engine is idling) - assertEqualsM("inj dur#5 idle", normalInjDuration, engine->injectionDuration); + EXPECT_NORMAL(); // Now change RPM just below RpmHigh threshold Sensor::setMockValue(SensorType::Rpm, engineConfiguration->coastingFuelCutRpmHigh - 1); eth.engine.periodicFastCallback(); // Fuel cut-off is still disabled - assertEqualsM("inj dur#6 mid", normalInjDuration, engine->injectionDuration); + EXPECT_NORMAL(); // Now set RPM just above RpmHigh threshold Sensor::setMockValue(SensorType::Rpm, engineConfiguration->coastingFuelCutRpmHigh + 1); eth.engine.periodicFastCallback(); // Fuel cut-off is active again! - assertEqualsM("inj dur#7 cut", 0.0f, engine->injectionDuration); + EXPECT_CUT(); + + // Configure vehicle speed thresholds + engineConfiguration->coastingFuelCutVssHigh = 50; + engineConfiguration->coastingFuelCutVssLow = 40; + + // High speed, should still be cut. + Sensor::setMockValue(SensorType::VehicleSpeed, 55); + eth.engine.periodicFastCallback(); + EXPECT_CUT(); + + // Between thresholds, still cut. + Sensor::setMockValue(SensorType::VehicleSpeed, 45); + eth.engine.periodicFastCallback(); + EXPECT_CUT(); + + // Below lower threshold, normal fuel resumes + Sensor::setMockValue(SensorType::VehicleSpeed, 35); + eth.engine.periodicFastCallback(); + EXPECT_NORMAL(); + + // Between thresholds, still normal. + Sensor::setMockValue(SensorType::VehicleSpeed, 45); + eth.engine.periodicFastCallback(); + EXPECT_NORMAL(); + + // Back above upper, cut again. + Sensor::setMockValue(SensorType::VehicleSpeed, 55); + eth.engine.periodicFastCallback(); + EXPECT_CUT(); }