Dashpot for return-to-idle from coasting

This commit is contained in:
rusefi 2023-06-12 14:58:11 -04:00 committed by rusefillc
parent ad29882308
commit 1a8cacf7c1
3 changed files with 61 additions and 3 deletions

View File

@ -111,12 +111,28 @@ if (engine->antilagController.isAntilagCondition) {
}
#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)
// nb: invalid tps will make no change, no explicit check required
iacByTpsTaper = interpolateClamped(
0, 0,
engineConfiguration->idlePidDeactivationTpsThreshold, engineConfiguration->iacByTpsTaper,
tps.value_or(0));
tpsForTaper);
running += iacByTpsTaper;

View File

@ -93,6 +93,8 @@ private:
Phase m_lastPhase = Phase::Cranking;
int m_lastTargetRpm = 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"
float m_lastAutomaticPosition = 0;

View File

@ -207,6 +207,46 @@ TEST(idle_v2, runningOpenLoopTpsTaper) {
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) {
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
IdleController dut;
@ -251,8 +291,8 @@ TEST(idle_v2, openLoopRunningTaper) {
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
StrictMock<MockOpenLoopIdler> dut;
EXPECT_CALL(dut, getRunningOpenLoop(IIdleController::Phase::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::CrankToIdleTaper, 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));
// 0 cycles - no taper yet, pure cranking value