kill engine if no oil pressure (#2800)
* min oil pressure for crank * do it time-based * rename field * include * fix existing test * tests * fix logic * more test Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
parent
850d19aaa9
commit
3a30f038ce
|
@ -27,6 +27,9 @@ All notable user-facing or behavior-altering changes will be documented in this
|
|||
|
||||
## Month 202x Release - "Release Name"
|
||||
|
||||
### Added
|
||||
- "inhibit start until oil pressure" prevents starting the engine with no/low oil pressure #2799
|
||||
|
||||
# 2021 May "Piercing Day"
|
||||
### Fixed
|
||||
- LCD screen works again #2576
|
||||
|
|
|
@ -177,7 +177,7 @@ void EngineState::periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|||
updateLaunchConditions(PASS_ENGINE_PARAMETER_SIGNATURE);
|
||||
#endif //EFI_LAUNCH_CONTROL
|
||||
|
||||
engine->limpManager.updateState(rpm);
|
||||
engine->limpManager.updateState(rpm, nowNt);
|
||||
|
||||
#endif // EFI_ENGINE_CONTROL
|
||||
}
|
||||
|
|
|
@ -161,6 +161,11 @@ void RpmCalculator::setRpmValue(float value) {
|
|||
if (rpmValue == 0) {
|
||||
state = STOPPED;
|
||||
} else if (rpmValue >= CONFIG(cranking.rpm)) {
|
||||
if (state != RUNNING) {
|
||||
// Store the time the engine started
|
||||
engineStartTimer.reset();
|
||||
}
|
||||
|
||||
state = RUNNING;
|
||||
} else if (state == STOPPED || state == SPINNING_UP) {
|
||||
/**
|
||||
|
@ -311,6 +316,10 @@ void rpmShaftPositionCallback(trigger_event_e ckpSignalType,
|
|||
}
|
||||
}
|
||||
|
||||
float RpmCalculator::getTimeSinceEngineStart(efitick_t nowNt) const {
|
||||
return engineStartTimer.getElapsedSeconds(nowNt);
|
||||
}
|
||||
|
||||
static scheduling_s tdcScheduler[2];
|
||||
|
||||
static char rpmBuffer[_MAX_FILLER];
|
||||
|
|
|
@ -105,6 +105,10 @@ public:
|
|||
* see also SC_RPM_ACCEL
|
||||
*/
|
||||
float getRpmAcceleration() const;
|
||||
|
||||
// Get elapsed time (seconds) since the engine transitioned to the running state.
|
||||
float getTimeSinceEngineStart(efitick_t nowNt) const;
|
||||
|
||||
/**
|
||||
* this is RPM on previous engine cycle.
|
||||
*/
|
||||
|
@ -153,6 +157,8 @@ private:
|
|||
* Needed by spinning-up logic.
|
||||
*/
|
||||
bool isSpinning = false;
|
||||
|
||||
Timer engineStartTimer;
|
||||
};
|
||||
|
||||
// Just a getter for rpmValue which also handles mockRpm if not EFI_PROD_CODE
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
EXTERN_ENGINE;
|
||||
|
||||
void LimpManager::updateState(int rpm) {
|
||||
void LimpManager::updateState(int rpm, efitick_t nowNt) {
|
||||
Clearable allowFuel = CONFIG(isInjectionEnabled);
|
||||
Clearable allowSpark = CONFIG(isIgnitionEnabled);
|
||||
|
||||
|
@ -31,6 +31,36 @@ void LimpManager::updateState(int rpm) {
|
|||
}
|
||||
}
|
||||
|
||||
if (ENGINE(rpmCalculator).isRunning()) {
|
||||
uint16_t minOilPressure = CONFIG(minOilPressureAfterStart);
|
||||
|
||||
// Only check if the setting is enabled
|
||||
if (minOilPressure > 0) {
|
||||
// Has it been long enough we should have pressure?
|
||||
bool isTimedOut = ENGINE(rpmCalculator).getTimeSinceEngineStart(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) {
|
||||
m_hadOilPressureAfterStart = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If time is up, the sensor works, and no pressure, kill the engine.
|
||||
if (isTimedOut && !m_hadOilPressureAfterStart) {
|
||||
allowFuel.clear();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// reset state in case of stalled engine
|
||||
m_hadOilPressureAfterStart = false;
|
||||
}
|
||||
|
||||
m_transientAllowInjection = allowFuel;
|
||||
m_transientAllowIgnition = allowSpark;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "engine_ptr.h"
|
||||
#include "rusefi_types.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
@ -27,7 +28,7 @@ public:
|
|||
DECLARE_ENGINE_PTR;
|
||||
|
||||
// This is called from periodicFastCallback to update internal state
|
||||
void updateState(int rpm);
|
||||
void updateState(int rpm, efitick_t nowNt);
|
||||
|
||||
// Other subsystems call these APIs to determine their behavior
|
||||
bool allowElectronicThrottle() const;
|
||||
|
@ -54,4 +55,6 @@ private:
|
|||
|
||||
bool m_transientAllowInjection = true;
|
||||
bool m_transientAllowIgnition = true;
|
||||
|
||||
bool m_hadOilPressureAfterStart = false;
|
||||
};
|
||||
|
|
|
@ -625,7 +625,8 @@ custom ignition_mode_e 4 bits, U32, @OFFSET@, [0:1], "Single Coil", "Indiv
|
|||
ignition_mode_e ignitionMode;+Single coil = distributor\nIndividual coils = one coil per cylinder (COP, coil-near-plug), requires sequential mode\nWasted spark = Fires pairs of cylinders together, either one coil per pair of cylinders or one coil per cylinder\nTwo distributors = A pair of distributors, found on some BMW, Toyota and other engines\nset ignition_mode X
|
||||
|
||||
int8_t gapTrackingLengthOverride;;"count",1,0,0,@@GAP_TRACKING_LENGTH@@,0
|
||||
int8_t[3] unusedOldIgnitionOffset;;"unused",1,0,0,1,0
|
||||
int8_t[1] unusedOldIgnitionOffset;;"unused",1,0,0,1,0
|
||||
uint16_t minOilPressureAfterStart;+Expected oil pressure after starting the engine. If oil pressure does not reach this level within 5 seconds of engine start, fuel will be cut. Set to 0 to disable and always allow starting.;"kPa",1,0,0,1000,0
|
||||
|
||||
custom timing_mode_e 4 bits, U32, @OFFSET@, [0:0], "dynamic", "fixed"
|
||||
timing_mode_e timingMode;+Dynamic uses the timing map to decide the ignition timing, Static timing fixes the timing to the value set below (only use for checking static timing with a timing light).
|
||||
|
|
|
@ -3046,6 +3046,7 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00"
|
|||
field = "Cut spark on RPM limit", cutSparkOnHardLimit
|
||||
field = "RPM hard limit", rpmHardLimit, { cutFuelOnHardLimit || cutSparkOnHardLimit }
|
||||
field = "Boost cut pressure", boostCutPressure
|
||||
field = "Minimum oil pressure after start", minOilPressureAfterStart
|
||||
|
||||
dialog = etbLimits, "Electronic Throttle Limiting"
|
||||
field = "Smoothly close the throttle to limit RPM."
|
||||
|
|
|
@ -29,17 +29,17 @@ TEST(limp, revLimit) {
|
|||
INJECT_ENGINE_REFERENCE(&dut);
|
||||
|
||||
// Under rev limit, inj/ign allowed
|
||||
dut.updateState(2000);
|
||||
dut.updateState(2000, 0);
|
||||
EXPECT_TRUE(dut.allowIgnition());
|
||||
EXPECT_TRUE(dut.allowInjection());
|
||||
|
||||
// Over rev limit, no injection
|
||||
dut.updateState(3000);
|
||||
dut.updateState(3000, 0);
|
||||
EXPECT_FALSE(dut.allowIgnition());
|
||||
EXPECT_FALSE(dut.allowInjection());
|
||||
|
||||
// Now recover back to under limit
|
||||
dut.updateState(2000);
|
||||
dut.updateState(2000, 0);
|
||||
EXPECT_TRUE(dut.allowIgnition());
|
||||
EXPECT_TRUE(dut.allowInjection());
|
||||
}
|
||||
|
@ -55,22 +55,97 @@ TEST(limp, boostCut) {
|
|||
|
||||
// Below threshold, injection allowed
|
||||
Sensor::setMockValue(SensorType::Map, 80);
|
||||
dut.updateState(1000);
|
||||
dut.updateState(1000, 0);
|
||||
EXPECT_TRUE(dut.allowInjection());
|
||||
|
||||
// Above threshold, injection cut
|
||||
Sensor::setMockValue(SensorType::Map, 120);
|
||||
dut.updateState(1000);
|
||||
dut.updateState(1000, 0);
|
||||
EXPECT_FALSE(dut.allowInjection());
|
||||
|
||||
// Below threshold, should recover
|
||||
Sensor::setMockValue(SensorType::Map, 80);
|
||||
dut.updateState(1000);
|
||||
dut.updateState(1000, 0);
|
||||
EXPECT_TRUE(dut.allowInjection());
|
||||
|
||||
// SPECIAL CASE: threshold of 0 means never boost cut
|
||||
engineConfiguration->boostCutPressure = 0;
|
||||
Sensor::setMockValue(SensorType::Map, 500);
|
||||
dut.updateState(1000);
|
||||
dut.updateState(1000, 0);
|
||||
EXPECT_TRUE(dut.allowInjection());
|
||||
}
|
||||
|
||||
extern int timeNowUs;
|
||||
|
||||
TEST(limp, oilPressureFailureCase) {
|
||||
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
|
||||
engineConfiguration->minOilPressureAfterStart = 200;
|
||||
|
||||
LimpManager dut;
|
||||
INJECT_ENGINE_REFERENCE(&dut);
|
||||
|
||||
// Low oil pressure!
|
||||
Sensor::setMockValue(SensorType::OilPressure, 50);
|
||||
|
||||
// Start the engine
|
||||
ENGINE(rpmCalculator).setRpmValue(1000);
|
||||
|
||||
// update & check: injection should be allowed
|
||||
dut.updateState(1000, getTimeNowNt());
|
||||
EXPECT_TRUE(dut.allowInjection());
|
||||
|
||||
// 4.5 seconds later, should still be allowed (even though pressure is low)
|
||||
timeNowUs += 4.5e6;
|
||||
dut.updateState(1000, getTimeNowNt());
|
||||
EXPECT_TRUE(dut.allowInjection());
|
||||
|
||||
// 1 second later (5.5 since start), injection should cut
|
||||
timeNowUs += 1.0e6;
|
||||
dut.updateState(1000, getTimeNowNt());
|
||||
ASSERT_FALSE(dut.allowInjection());
|
||||
|
||||
// But then oil pressure arrives!
|
||||
// Injection still isn't allowed, since now we're late.
|
||||
Sensor::setMockValue(SensorType::OilPressure, 250);
|
||||
dut.updateState(1000, getTimeNowNt());
|
||||
ASSERT_FALSE(dut.allowInjection());
|
||||
}
|
||||
|
||||
TEST(limp, oilPressureSuccessCase) {
|
||||
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
|
||||
engineConfiguration->minOilPressureAfterStart = 200;
|
||||
|
||||
LimpManager dut;
|
||||
INJECT_ENGINE_REFERENCE(&dut);
|
||||
|
||||
// Low oil pressure!
|
||||
Sensor::setMockValue(SensorType::OilPressure, 50);
|
||||
|
||||
// Start the engine
|
||||
ENGINE(rpmCalculator).setRpmValue(1000);
|
||||
|
||||
// update & check: injection should be allowed
|
||||
dut.updateState(1000, getTimeNowNt());
|
||||
EXPECT_TRUE(dut.allowInjection());
|
||||
|
||||
// 4.5 seconds later, should still be allowed (even though pressure is low)
|
||||
timeNowUs += 4.5e6;
|
||||
dut.updateState(1000, getTimeNowNt());
|
||||
EXPECT_TRUE(dut.allowInjection());
|
||||
|
||||
// But then oil pressure arrives!
|
||||
Sensor::setMockValue(SensorType::OilPressure, 250);
|
||||
dut.updateState(1000, getTimeNowNt());
|
||||
ASSERT_TRUE(dut.allowInjection());
|
||||
|
||||
// 1 second later (5.5 since start), injection should be allowed since we saw pressure before the timeout
|
||||
timeNowUs += 1.0e6;
|
||||
dut.updateState(1000, getTimeNowNt());
|
||||
ASSERT_TRUE(dut.allowInjection());
|
||||
|
||||
// Later, we lose oil pressure, but engine should stay running
|
||||
timeNowUs += 10e6;
|
||||
Sensor::setMockValue(SensorType::OilPressure, 10);
|
||||
dut.updateState(1000, getTimeNowNt());
|
||||
ASSERT_TRUE(dut.allowInjection());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue