From e4b8aa374776ef06d47ce5fba53c23fedd4245b8 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Tue, 6 Aug 2024 13:10:10 -0700 Subject: [PATCH] oil pressure protection (while running) (#460) * config * implement * defaults * check array bins * gauge * test the new behavior --- .../algo/defaults/default_base_engine.cpp | 3 ++ firmware/controllers/engine_controller.cpp | 4 ++ firmware/controllers/limp_manager.cpp | 20 ++++++-- firmware/controllers/limp_manager.h | 3 ++ firmware/integration/rusefi_config.txt | 7 ++- firmware/tunerstudio/tunerstudio.template.ini | 11 +++++ unit_tests/tests/test_limp.cpp | 46 ++++++++++++++++++- 7 files changed, 87 insertions(+), 7 deletions(-) diff --git a/firmware/controllers/algo/defaults/default_base_engine.cpp b/firmware/controllers/algo/defaults/default_base_engine.cpp index c966e71c8a..c5e0cedf24 100644 --- a/firmware/controllers/algo/defaults/default_base_engine.cpp +++ b/firmware/controllers/algo/defaults/default_base_engine.cpp @@ -109,6 +109,9 @@ void setDefaultBaseEngine() { setDefaultVrThresholds(); + // Oil pressure protection + engineConfiguration->minimumOilPressureTimeout = 0.5f; + setLinearCurve(config->minimumOilPressureBins, 0, 7000); } void setPPSInputs(adc_channel_e pps1, adc_channel_e pps2) { diff --git a/firmware/controllers/engine_controller.cpp b/firmware/controllers/engine_controller.cpp index fc39f01778..2061ae9ada 100644 --- a/firmware/controllers/engine_controller.cpp +++ b/firmware/controllers/engine_controller.cpp @@ -664,6 +664,10 @@ bool validateConfig() { } #endif + if (engineConfiguration->enableOilPressureProtect) { + ensureArrayIsAscending("Oil pressure protection", config->minimumOilPressureBins); + } + return true; } diff --git a/firmware/controllers/limp_manager.cpp b/firmware/controllers/limp_manager.cpp index 7421bf1677..e67203596d 100644 --- a/firmware/controllers/limp_manager.cpp +++ b/firmware/controllers/limp_manager.cpp @@ -111,17 +111,17 @@ void LimpManager::updateState(int rpm, efitick_t nowNt) { } #if EFI_SHAFT_POSITION_INPUT if (engine->rpmCalculator.isRunning()) { + bool hasOilpSensor = Sensor::hasSensor(SensorType::OilPressure); + auto oilp = Sensor::get(SensorType::OilPressure); uint16_t minOilPressure = engineConfiguration->minOilPressureAfterStart; // Only check if the setting is enabled and you have an oil pressure sensor - if (minOilPressure > 0 && Sensor::hasSensor(SensorType::OilPressure)) { + if (minOilPressure > 0 && hasOilpSensor) { // Has it been long enough we should have pressure? bool isTimedOut = engine->rpmCalculator.getSecondsSinceEngineStart(nowNt) > 5.0f; // Only check before timed out if (!isTimedOut) { - auto oilp = Sensor::get(SensorType::OilPressure); - if (oilp) { // We had oil pressure! Set the flag. if (oilp.Value > minOilPressure) { @@ -135,9 +135,23 @@ void LimpManager::updateState(int rpm, efitick_t nowNt) { allowFuel.clear(ClearReason::OilPressure); } } + + if (oilp && engineConfiguration->enableOilPressureProtect) { + float minPressure = interpolate2d(rpm, config->minimumOilPressureBins, config->minimumOilPressureValues); + bool isPressureSufficient = oilp.Value > minPressure; + + if (isPressureSufficient) { + m_lowOilPressureTimer.reset(nowNt); + } + + if (m_lowOilPressureTimer.hasElapsedSec(engineConfiguration->minimumOilPressureTimeout)) { + allowFuel.clear(ClearReason::OilPressure); + } + } } else { // reset state in case of stalled engine m_hadOilPressureAfterStart = false; + m_lowOilPressureTimer.reset(nowNt); } // If we're in engine stop mode, inhibit fuel diff --git a/firmware/controllers/limp_manager.h b/firmware/controllers/limp_manager.h index 6b2852e713..69857009f2 100644 --- a/firmware/controllers/limp_manager.h +++ b/firmware/controllers/limp_manager.h @@ -157,6 +157,9 @@ private: // Tracks how long injector duty has been over the sustained limit Timer m_injectorDutySustainedTimer; + + // Tracks how long oil pressure has been below threshold + Timer m_lowOilPressureTimer; }; LimpManager * getLimpManager(); diff --git a/firmware/integration/rusefi_config.txt b/firmware/integration/rusefi_config.txt index 3ea03d5454..b1404147ff 100644 --- a/firmware/integration/rusefi_config.txt +++ b/firmware/integration/rusefi_config.txt @@ -779,7 +779,7 @@ custom uart_device_e 1 bits, U08, @OFFSET@, [0:1], "Off", "UART1", "UART2", "UAR pin_output_mode_e acRelayPinMode; output_pin_e acRelayPin; - uint8_t unused754 + uint8_t autoscale minimumOilPressureTimeout;Delay before cutting fuel due to low oil pressure. Use this to ignore short pressure blips and sensor noise.;"sec", 0.1, 0, 0, 5, 1 spi_device_e drv8860spiDevice; @@ -826,7 +826,7 @@ sensor_chart_e sensorChartMode;rusEFI console Sensor Sniffer mode; bit enableLaunchRetard bit enableCanVss;Read VSS from OEM CAN bus according to selected CAN vehicle configuration. bit enableInnovateLC2 - bit unused808b7 + bit enableOilPressureProtect bit stftIgnoreErrorMagnitude;If enabled, adjust at a constant rate instead of a rate proportional to the current lambda error. This mode may be easier to tune, and more tolerant of sensor noise. bit enableSoftwareKnock bit verboseVVTDecoding;Verbose info in console below engineSnifferRpmThreshold\nenable vvt_details @@ -1731,6 +1731,9 @@ uint8_t[FUEL_LEVEL_TABLE_COUNT] fuelLevelValues;;"%", 1, 0, 0, 100, 0 uint8_t[DWELL_CURVE_SIZE] autoscale dwellVoltageCorrVoltBins;;"volts", 0.1, 0, 0, 20, 1 uint8_t[DWELL_CURVE_SIZE] autoscale dwellVoltageCorrValues;;"multiplier", 0.02, 0, 0, 5, 2 +uint8_t[8] autoscale minimumOilPressureBins;;"RPM", 100, 0, 0, 25000, 0 +uint8_t[8] autoscale minimumOilPressureValues;;"kPa", 10, 0, 0, 1000, 0 + end_struct ! Pedal Position Sensor diff --git a/firmware/tunerstudio/tunerstudio.template.ini b/firmware/tunerstudio/tunerstudio.template.ini index b2bd73f7c6..20f2431b50 100644 --- a/firmware/tunerstudio/tunerstudio.template.ini +++ b/firmware/tunerstudio/tunerstudio.template.ini @@ -800,6 +800,14 @@ curve = 32Curve, "3-2 Shift Solenoid Percent by Speed" yBins = throttleEstimateEffectiveAreaValues gauge = TPSGauge + curve = minimumOilPressure, "Minimum oil pressure" + columnLabel = "RPM", "min pressure" + xAxis = 0, 8000, 9 + yAxis = 0, 500, 6 + xBins = minimumOilPressureBins, RPMValue + yBins = minimumOilPressureValues + gauge = OilPressGauge + [TableEditor] ; table_id, map3d_id, "title", page @@ -3805,6 +3813,9 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_ dialog = oilPressureProtection, "Oil pressure protection" field = "Minimum oil pressure after start", minOilPressureAfterStart + field = "Enable low oil pressure protection", enableOilPressureProtect + field = "Oil pressure protection timeout", minimumOilPressureTimeout + panel = minimumOilPressure dialog = etbLimits, "Electronic Throttle Limiting" field = "Smoothly close the throttle to limit RPM." diff --git a/unit_tests/tests/test_limp.cpp b/unit_tests/tests/test_limp.cpp index 8afff214cc..70797630f5 100644 --- a/unit_tests/tests/test_limp.cpp +++ b/unit_tests/tests/test_limp.cpp @@ -132,7 +132,7 @@ TEST(limp, boostCut) { EXPECT_TRUE(dut.allowInjection()); } -TEST(limp, oilPressureFailureCase) { +TEST(limp, oilPressureStartupFailureCase) { EngineTestHelper eth(engine_type_e::TEST_ENGINE); engineConfiguration->minOilPressureAfterStart = 200; @@ -165,7 +165,7 @@ TEST(limp, oilPressureFailureCase) { ASSERT_FALSE(dut.allowInjection()); } -TEST(limp, oilPressureSuccessCase) { +TEST(limp, oilPressureStartupSuccessCase) { EngineTestHelper eth(engine_type_e::TEST_ENGINE); engineConfiguration->minOilPressureAfterStart = 200; @@ -202,3 +202,45 @@ TEST(limp, oilPressureSuccessCase) { dut.updateState(1000, getTimeNowNt()); ASSERT_TRUE(dut.allowInjection()); } + +TEST(limp, oilPressureRunning) { + EngineTestHelper eth(engine_type_e::TEST_ENGINE); + engineConfiguration->enableOilPressureProtect = true; + engineConfiguration->minimumOilPressureTimeout = 1.0f; + setArrayValues(config->minimumOilPressureValues, 100); + + LimpManager dut; + + // Oil pressure starts OK + Sensor::setMockValue(SensorType::OilPressure, 110); + + // Start the engine + engine->rpmCalculator.setRpmValue(1000); + + // update & check: injection should be allowed + dut.updateState(1000, getTimeNowNt()); + EXPECT_TRUE(dut.allowInjection()); + + // A long time later, everything should still be OK + advanceTimeUs(60e6); + dut.updateState(1000, getTimeNowNt()); + EXPECT_TRUE(dut.allowInjection()); + + // Now oil pressure drops below threshold + Sensor::setMockValue(SensorType::OilPressure, 90); + + // 0.9 second later, injection should continue as timeout isn't hit yet + advanceTimeUs(0.9e6); + dut.updateState(1000, getTimeNowNt()); + ASSERT_TRUE(dut.allowInjection()); + + // 0.2 second later (1.1s since low pressure starts), injection should cut + advanceTimeUs(1.0e6); + dut.updateState(1000, getTimeNowNt()); + ASSERT_FALSE(dut.allowInjection()); + + // Oil pressure is restored, and fuel should be restored too + Sensor::setMockValue(SensorType::OilPressure, 110); + dut.updateState(1000, getTimeNowNt()); + ASSERT_TRUE(dut.allowInjection()); +}