mirror of https://github.com/rusefi/rusefi.git
Dashpot for return-to-idle from coasting
This commit is contained in:
parent
ad29882308
commit
1a8cacf7c1
|
@ -111,12 +111,28 @@ if (engine->antilagController.isAntilagCondition) {
|
||||||
}
|
}
|
||||||
#endif /* EFI_ANTILAG_SYSTEM */
|
#endif /* EFI_ANTILAG_SYSTEM */
|
||||||
|
|
||||||
|
// 'dashpot' (hold+decay) logic for coasting->idle
|
||||||
|
float tpsForTaper = tps.value_or(0);
|
||||||
|
efitimeus_t nowUs = getTimeNowUs();
|
||||||
|
if (phase == Phase::Running) {
|
||||||
|
lastTimeRunningUs = nowUs;
|
||||||
|
}
|
||||||
|
// imitate a slow pedal release for TPS taper (to avoid engine stalls)
|
||||||
|
if (tpsForTaper <= engineConfiguration->idlePidDeactivationTpsThreshold) {
|
||||||
|
// make sure the time is not zero
|
||||||
|
float timeSinceRunningPhaseSecs = (float)(nowUs - lastTimeRunningUs + 1) / US_PER_SECOND_F;
|
||||||
|
// we shift the time to implement the hold correction (time can be negative)
|
||||||
|
float timeSinceRunningAfterHoldSecs = timeSinceRunningPhaseSecs - engineConfiguration->iacByTpsHoldTime;
|
||||||
|
// implement the decay correction (from tpsForTaper to 0)
|
||||||
|
tpsForTaper = interpolateClamped(0, engineConfiguration->idlePidDeactivationTpsThreshold, engineConfiguration->iacByTpsDecayTime, tpsForTaper, timeSinceRunningAfterHoldSecs);
|
||||||
|
}
|
||||||
|
|
||||||
// Now bump it by the specified amount when the throttle is opened (if configured)
|
// Now bump it by the specified amount when the throttle is opened (if configured)
|
||||||
// nb: invalid tps will make no change, no explicit check required
|
// nb: invalid tps will make no change, no explicit check required
|
||||||
iacByTpsTaper = interpolateClamped(
|
iacByTpsTaper = interpolateClamped(
|
||||||
0, 0,
|
0, 0,
|
||||||
engineConfiguration->idlePidDeactivationTpsThreshold, engineConfiguration->iacByTpsTaper,
|
engineConfiguration->idlePidDeactivationTpsThreshold, engineConfiguration->iacByTpsTaper,
|
||||||
tps.value_or(0));
|
tpsForTaper);
|
||||||
|
|
||||||
running += iacByTpsTaper;
|
running += iacByTpsTaper;
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,8 @@ private:
|
||||||
Phase m_lastPhase = Phase::Cranking;
|
Phase m_lastPhase = Phase::Cranking;
|
||||||
int m_lastTargetRpm = 0;
|
int m_lastTargetRpm = 0;
|
||||||
efitimeus_t restoreAfterPidResetTimeUs = 0;
|
efitimeus_t restoreAfterPidResetTimeUs = 0;
|
||||||
|
// used by 'dashpot' (hold+decay) logic for iacByTpsTaper
|
||||||
|
efitimeus_t lastTimeRunningUs = 0;
|
||||||
|
|
||||||
// This is stored by getClosedLoop and used in case we want to "do nothing"
|
// This is stored by getClosedLoop and used in case we want to "do nothing"
|
||||||
float m_lastAutomaticPosition = 0;
|
float m_lastAutomaticPosition = 0;
|
||||||
|
|
|
@ -207,6 +207,46 @@ TEST(idle_v2, runningOpenLoopTpsTaper) {
|
||||||
EXPECT_FLOAT_EQ(50, dut.getRunningOpenLoop(IIdleController::Phase::Cranking, 0, 0, 20));
|
EXPECT_FLOAT_EQ(50, dut.getRunningOpenLoop(IIdleController::Phase::Cranking, 0, 0, 20));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int timeNowUs;
|
||||||
|
|
||||||
|
TEST(idle_v2, runningOpenLoopTpsTaperWithDashpot) {
|
||||||
|
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
|
||||||
|
IdleController dut;
|
||||||
|
|
||||||
|
// Zero out base tempco table
|
||||||
|
setArrayValues(config->cltIdleCorr, 0.0f);
|
||||||
|
|
||||||
|
// Add 50% idle position
|
||||||
|
engineConfiguration->iacByTpsTaper = 50;
|
||||||
|
// At 10% TPS
|
||||||
|
engineConfiguration->idlePidDeactivationTpsThreshold = 10;
|
||||||
|
|
||||||
|
// set hold and decay time
|
||||||
|
engineConfiguration->iacByTpsHoldTime = 10; // 10 secs
|
||||||
|
engineConfiguration->iacByTpsDecayTime = 10; // 10 secs
|
||||||
|
|
||||||
|
// save the lastTimeRunningUs time - let it be the start of the hold phase
|
||||||
|
timeNowUs += 5'000'000;
|
||||||
|
// full throttle = max.iac
|
||||||
|
EXPECT_FLOAT_EQ(50, dut.getRunningOpenLoop(ICP::Running, 0, 0, 100));
|
||||||
|
|
||||||
|
// jump to the end of the 'hold' phase of dashpot
|
||||||
|
timeNowUs += 10'000'000;
|
||||||
|
|
||||||
|
// change the state to idle (release the pedal) - but still 100% max.iac!
|
||||||
|
EXPECT_FLOAT_EQ(50, dut.getRunningOpenLoop(ICP::Idling, 0, 0, 0));
|
||||||
|
// now we're in the middle of decay
|
||||||
|
timeNowUs += 5'000'000;
|
||||||
|
// 50% decay (50% of 50 is 25)
|
||||||
|
EXPECT_FLOAT_EQ(25, dut.getRunningOpenLoop(ICP::Idling, 0, 0, 0));
|
||||||
|
// now the decay is finished
|
||||||
|
timeNowUs += 5'000'000;
|
||||||
|
// no correction
|
||||||
|
EXPECT_FLOAT_EQ(0, dut.getRunningOpenLoop(ICP::Idling, 0, 0, 0));
|
||||||
|
// still react to the pedal
|
||||||
|
EXPECT_FLOAT_EQ(50, dut.getRunningOpenLoop(ICP::Idling, 0, 0, 10));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(idle_v2, runningOpenLoopRpmTaper) {
|
TEST(idle_v2, runningOpenLoopRpmTaper) {
|
||||||
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
|
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
|
||||||
IdleController dut;
|
IdleController dut;
|
||||||
|
@ -251,8 +291,8 @@ TEST(idle_v2, openLoopRunningTaper) {
|
||||||
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
|
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
|
||||||
StrictMock<MockOpenLoopIdler> dut;
|
StrictMock<MockOpenLoopIdler> dut;
|
||||||
|
|
||||||
EXPECT_CALL(dut, getRunningOpenLoop(IIdleController::Phase::CrankToIdleTaper, 0, 30, SensorResult(0))).WillRepeatedly(Return(25));
|
EXPECT_CALL(dut, getRunningOpenLoop(ICP::CrankToIdleTaper, 0, 30, SensorResult(0))).WillRepeatedly(Return(25));
|
||||||
EXPECT_CALL(dut, getRunningOpenLoop(IIdleController::Phase::Running, 0, 30, SensorResult(0))).WillRepeatedly(Return(25));
|
EXPECT_CALL(dut, getRunningOpenLoop(ICP::Running, 0, 30, SensorResult(0))).WillRepeatedly(Return(25));
|
||||||
EXPECT_CALL(dut, getCrankingOpenLoop(30)).WillRepeatedly(Return(75));
|
EXPECT_CALL(dut, getCrankingOpenLoop(30)).WillRepeatedly(Return(75));
|
||||||
|
|
||||||
// 0 cycles - no taper yet, pure cranking value
|
// 0 cycles - no taper yet, pure cranking value
|
||||||
|
|
Loading…
Reference in New Issue