dfco delay (#4482)
* dfco delay * config * using a function that doesn't exist? who does that * test new behavior * clearer test
This commit is contained in:
parent
fda9448798
commit
08d2aee17b
|
@ -51,13 +51,21 @@ void DfcoController::update() {
|
||||||
// If fuel is cut, reset the timer
|
// If fuel is cut, reset the timer
|
||||||
if (newState) {
|
if (newState) {
|
||||||
m_timeSinceCut.reset();
|
m_timeSinceCut.reset();
|
||||||
|
} else {
|
||||||
|
// If fuel is not cut, reset the not-cut timer
|
||||||
|
m_timeSinceNoCut.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_isDfco = newState;
|
m_isDfco = newState;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DfcoController::cutFuel() const {
|
bool DfcoController::cutFuel() const {
|
||||||
return m_isDfco;
|
float cutDelay = engineConfiguration->dfcoDelay;
|
||||||
|
|
||||||
|
// 0 delay means cut immediately, aka timer has always expired
|
||||||
|
bool hasBeenDelay = (cutDelay == 0) || m_timeSinceNoCut.hasElapsedSec(cutDelay);
|
||||||
|
|
||||||
|
return m_isDfco && hasBeenDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
float DfcoController::getTimeSinceCut() const {
|
float DfcoController::getTimeSinceCut() const {
|
||||||
|
|
|
@ -14,4 +14,5 @@ private:
|
||||||
bool m_isDfco = false;
|
bool m_isDfco = false;
|
||||||
|
|
||||||
Timer m_timeSinceCut;
|
Timer m_timeSinceCut;
|
||||||
|
Timer m_timeSinceNoCut;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1429,7 +1429,9 @@ tChargeMode_e tChargeMode;
|
||||||
|
|
||||||
uint8_t autoscale maxCamPhaseResolveRpm;Below this RPM, use camshaft information to synchronize the crank's position for full sequential operation. Use this if your cam sensor does weird things at high RPM. Set to 0 to disable, and always use cam to help sync crank.;"rpm", 50, 0, 0, 12500, 0
|
uint8_t autoscale maxCamPhaseResolveRpm;Below this RPM, use camshaft information to synchronize the crank's position for full sequential operation. Use this if your cam sensor does weird things at high RPM. Set to 0 to disable, and always use cam to help sync crank.;"rpm", 50, 0, 0, 12500, 0
|
||||||
|
|
||||||
int8_t[11] unused4080;;"", 1, 0, 0, 0, 0
|
uint8_t autoscale dfcoDelay;Delay before cutting fuel. Set to 0 to cut immediately with no delay. May cause rumbles and pops out of your exhaust...;"sec", 0.1, 0, 0, 10, 1
|
||||||
|
|
||||||
|
int8_t[10] unused4080;;"", 1, 0, 0, 0, 0
|
||||||
|
|
||||||
! Someday there will be a 6th option for BMW S55 that uses a separate shaft just for HPFP
|
! Someday there will be a 6th option for BMW S55 that uses a separate shaft just for HPFP
|
||||||
#define hpfp_cam_e_enum "NONE", "Intake 1", "Exhaust 1", "Intake 2", "Exhaust 2"
|
#define hpfp_cam_e_enum "NONE", "Intake 1", "Exhaust 1", "Intake 2", "Exhaust 2"
|
||||||
|
|
|
@ -3886,6 +3886,7 @@ dialog = tcuControls, "Transmission Settings"
|
||||||
field = "Vehicle speed restore below", coastingFuelCutVssLow, {coastingFuelCutEnabled == 1}
|
field = "Vehicle speed restore below", coastingFuelCutVssLow, {coastingFuelCutEnabled == 1}
|
||||||
field = "Cut fuel below TPS", coastingFuelCutTps, {coastingFuelCutEnabled == 1}
|
field = "Cut fuel below TPS", coastingFuelCutTps, {coastingFuelCutEnabled == 1}
|
||||||
field = "Cut fuel below MAP", coastingFuelCutMap, {coastingFuelCutEnabled == 1}
|
field = "Cut fuel below MAP", coastingFuelCutMap, {coastingFuelCutEnabled == 1}
|
||||||
|
field = "Fuel cut delay", dfcoDelay, {coastingFuelCutEnabled == 1}
|
||||||
field = "Inhibit closed loop fuel after cut", noFuelTrimAfterDfcoTime, {coastingFuelCutEnabled == 1}
|
field = "Inhibit closed loop fuel after cut", noFuelTrimAfterDfcoTime, {coastingFuelCutEnabled == 1}
|
||||||
|
|
||||||
dialog = rotaryDialog, "Rotary"
|
dialog = rotaryDialog, "Rotary"
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
|
|
||||||
using ::testing::_;
|
using ::testing::_;
|
||||||
|
|
||||||
|
// Define some helpers for not-cut and cut
|
||||||
|
#define EXPECT_NORMAL() EXPECT_FLOAT_EQ(normalInjDuration, engine->injectionDuration)
|
||||||
|
#define EXPECT_CUT() EXPECT_FLOAT_EQ(0, engine->injectionDuration)
|
||||||
|
|
||||||
TEST(fuelCut, coasting) {
|
TEST(fuelCut, coasting) {
|
||||||
EngineTestHelper eth(TEST_ENGINE);
|
EngineTestHelper eth(TEST_ENGINE);
|
||||||
EXPECT_CALL(*eth.mockAirmass, getAirmass(_))
|
EXPECT_CALL(*eth.mockAirmass, getAirmass(_))
|
||||||
|
@ -49,10 +53,6 @@ TEST(fuelCut, coasting) {
|
||||||
// process
|
// process
|
||||||
eth.engine.periodicFastCallback();
|
eth.engine.periodicFastCallback();
|
||||||
|
|
||||||
// Define some helpers for not-cut and cut
|
|
||||||
#define EXPECT_NORMAL() EXPECT_FLOAT_EQ(normalInjDuration, engine->injectionDuration)
|
|
||||||
#define EXPECT_CUT() EXPECT_FLOAT_EQ(0, engine->injectionDuration)
|
|
||||||
|
|
||||||
// this is normal injection mode (the throttle is opened), no fuel cut-off
|
// this is normal injection mode (the throttle is opened), no fuel cut-off
|
||||||
EXPECT_NORMAL();
|
EXPECT_NORMAL();
|
||||||
|
|
||||||
|
@ -130,3 +130,73 @@ TEST(fuelCut, coasting) {
|
||||||
EXPECT_CUT();
|
EXPECT_CUT();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(fuelCut, delay) {
|
||||||
|
EngineTestHelper eth(TEST_ENGINE);
|
||||||
|
EXPECT_CALL(*eth.mockAirmass, getAirmass(_))
|
||||||
|
.WillRepeatedly(Return(AirmassResult{0.1008f, 50.0f}));
|
||||||
|
|
||||||
|
// configure coastingFuelCut
|
||||||
|
engineConfiguration->coastingFuelCutEnabled = true;
|
||||||
|
engineConfiguration->coastingFuelCutRpmLow = 1300;
|
||||||
|
engineConfiguration->coastingFuelCutRpmHigh = 1500;
|
||||||
|
engineConfiguration->coastingFuelCutTps = 2;
|
||||||
|
engineConfiguration->coastingFuelCutClt = 30;
|
||||||
|
engineConfiguration->coastingFuelCutMap = 100;
|
||||||
|
// set cranking threshold
|
||||||
|
engineConfiguration->cranking.rpm = 999;
|
||||||
|
|
||||||
|
// delay is 1 second
|
||||||
|
engineConfiguration->dfcoDelay = 1.0f;
|
||||||
|
|
||||||
|
// basic engine setup
|
||||||
|
setupSimpleTestEngineWithMafAndTT_ONE_trigger(ð);
|
||||||
|
|
||||||
|
Sensor::setMockValue(SensorType::Map, 0);
|
||||||
|
|
||||||
|
// mock CLT - just above threshold ('hot engine')
|
||||||
|
float hotClt = engineConfiguration->coastingFuelCutClt + 1;
|
||||||
|
Sensor::setMockValue(SensorType::Clt, hotClt);
|
||||||
|
// mock TPS - throttle is opened
|
||||||
|
Sensor::setMockValue(SensorType::DriverThrottleIntent, 60);
|
||||||
|
// set 'running' RPM - just above RpmHigh threshold
|
||||||
|
Sensor::setMockValue(SensorType::Rpm, engineConfiguration->coastingFuelCutRpmHigh + 1);
|
||||||
|
// 'advance' time (amount doesn't matter)
|
||||||
|
eth.moveTimeForwardUs(1000);
|
||||||
|
|
||||||
|
const float normalInjDuration = 1.5f;
|
||||||
|
|
||||||
|
extern int timeNowUs;
|
||||||
|
timeNowUs = 1e6;
|
||||||
|
|
||||||
|
// process
|
||||||
|
eth.engine.periodicFastCallback();
|
||||||
|
|
||||||
|
// this is normal injection mode (the throttle is opened), no fuel cut-off
|
||||||
|
EXPECT_NORMAL();
|
||||||
|
|
||||||
|
// 'releasing' the throttle
|
||||||
|
Sensor::setMockValue(SensorType::DriverThrottleIntent, 0);
|
||||||
|
eth.engine.periodicFastCallback();
|
||||||
|
|
||||||
|
// Shouldn't cut yet, since not enough time has elapsed
|
||||||
|
EXPECT_NORMAL();
|
||||||
|
|
||||||
|
// Change nothing else, but advance time and update again
|
||||||
|
timeNowUs += 0.9e6;
|
||||||
|
eth.engine.periodicFastCallback();
|
||||||
|
|
||||||
|
// too soon, still no cut
|
||||||
|
EXPECT_NORMAL();
|
||||||
|
|
||||||
|
// Change nothing else, but advance time and update again
|
||||||
|
timeNowUs += 0.2e6;
|
||||||
|
eth.engine.periodicFastCallback();
|
||||||
|
|
||||||
|
// Should now be cut!
|
||||||
|
EXPECT_CUT();
|
||||||
|
|
||||||
|
// Put the throtle back, and it should come back instantly
|
||||||
|
Sensor::setMockValue(SensorType::DriverThrottleIntent, 30);
|
||||||
|
eth.engine.periodicFastCallback();
|
||||||
|
EXPECT_NORMAL();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue