mirror of https://github.com/FOME-Tech/fome-fw.git
Add cranking taper duration multiplier based on CLT (#370)
* Add Cranking taper duration multiplier based on CLT * Fixed same merge error in TS config * Fixed existing unit test for getCrankingTaperFraction, and added a new one to test multiplier table for cranking taper duration. * Fixed existing header file for unit test getCrankingTaperFraction * Changed naming * changed logic * Forgot to update name here too * Forgot to update name here too, second time
This commit is contained in:
parent
b26d5ba475
commit
4c65992017
|
@ -79,8 +79,14 @@ IIdleController::Phase IdleController::determinePhase(int rpm, int targetRpm, Se
|
|||
return Phase::Idling;
|
||||
}
|
||||
|
||||
float IdleController::getCrankingTaperFraction() const {
|
||||
return (float)engine->rpmCalculator.getRevolutionCounterSinceStart() / engineConfiguration->afterCrankingIACtaperDuration;
|
||||
float IdleController::getCrankingTaperFraction(float clt) const {
|
||||
float taperDuration = engineConfiguration->afterCrankingIACtaperDuration;
|
||||
|
||||
if (engineConfiguration->useCrankingIdleTaperTableSetting) {
|
||||
taperDuration *= interpolate2d(clt, config->cltCrankingTaperCorrBins, config->cltCrankingTaperCorr);
|
||||
}
|
||||
|
||||
return (float)engine->rpmCalculator.getRevolutionCounterSinceStart() / taperDuration;
|
||||
}
|
||||
|
||||
float IdleController::getCrankingOpenLoop(float clt) const {
|
||||
|
@ -309,7 +315,7 @@ float IdleController::getIdlePosition(float rpm) {
|
|||
m_lastTargetRpm = targetRpm;
|
||||
|
||||
// Determine cranking taper
|
||||
float crankingTaper = getCrankingTaperFraction();
|
||||
float crankingTaper = getCrankingTaperFraction(clt);
|
||||
|
||||
// Determine what operation phase we're in - idling or not
|
||||
float vehicleSpeed = Sensor::getOrZero(SensorType::VehicleSpeed);
|
||||
|
|
|
@ -30,7 +30,7 @@ struct IIdleController {
|
|||
virtual float getRunningOpenLoop(float rpm, float clt, SensorResult tps) = 0;
|
||||
virtual float getOpenLoop(Phase phase, float rpm, float clt, SensorResult tps, float crankingTaperFraction) = 0;
|
||||
virtual float getClosedLoop(Phase phase, float tps, int rpm, int target) = 0;
|
||||
virtual float getCrankingTaperFraction() const = 0;
|
||||
virtual float getCrankingTaperFraction(float clt) const = 0;
|
||||
virtual bool isIdlingOrTaper() const = 0;
|
||||
virtual float getIdleTimingAdjustment(int rpm) = 0;
|
||||
};
|
||||
|
@ -49,7 +49,7 @@ public:
|
|||
|
||||
// PHASE DETERMINATION: what is the driver trying to do right now?
|
||||
Phase determinePhase(int rpm, int targetRpm, SensorResult tps, float vss, float crankingTaperFraction) override;
|
||||
float getCrankingTaperFraction() const override;
|
||||
float getCrankingTaperFraction(float clt) const override;
|
||||
|
||||
// OPEN LOOP CORRECTIONS
|
||||
percent_t getCrankingOpenLoop(float clt) const override;
|
||||
|
|
|
@ -981,6 +981,7 @@ bit skippedWheelOnCam,"On camshaft","On crankshaft";Where is your primary skippe
|
|||
bit complexWallModel,"Advanced (tables)","Basic (constants)";Should we use tables to vary tau/beta based on CLT/MAP, or just with fixed values?
|
||||
bit alwaysInstantRpm
|
||||
bit isMapAveragingEnabled
|
||||
bit useCrankingIdleTaperTableSetting; If enabled, use separate temperature multiplier table for cranking taper duration.
|
||||
bit overrideCrankingIacSetting;If enabled, use separate temperature multiplier table for cranking idle position.\nIf disabled, use normal running multiplier table applied to the cranking base position.
|
||||
bit useSeparateAdvanceForIdle;This activates a separate ignition timing table for idle conditions, this can help idle stability by using ignition retard and advance either side of the desired idle speed. Extra retard at low idle speeds will prevent stalling and extra advance at high idle speeds can help reduce engine power and slow the idle speed.
|
||||
bit isWaveAnalyzerEnabled
|
||||
|
@ -1556,6 +1557,9 @@ uint8_t[PEDAL_TO_TPS_SIZE] autoscale pedalToTpsRpmBins;;"RPM", 100, 0, 0, 25000,
|
|||
float[CLT_CRANKING_CURVE_SIZE] cltCrankingCorrBins;CLT-based cranking position multiplier for simple manual idle controller;"C", 1, 0, -100, 250, 2
|
||||
float[CLT_CRANKING_CURVE_SIZE] cltCrankingCorr ;CLT-based cranking position multiplier for simple manual idle controller;"%", 1, 0, 0, 500, 2
|
||||
|
||||
int8_t[CLT_CRANKING_CURVE_SIZE] cltCrankingTaperCorrBins;CLT-based taper duration multiplier for simple manual idle controller;"C", 1, 0, -100, 120, 2
|
||||
uint8_t[CLT_CRANKING_CURVE_SIZE] autoscale cltCrankingTaperCorr ;CLT-based taper duration multiplier for simple manual idle controller;"%", 0.02, 0, 0, 5, 2
|
||||
|
||||
uint8_t[IDLE_ADVANCE_CURVE_SIZE] autoscale idleAdvanceBins;Optional timing advance table for Idle (see useSeparateAdvanceForIdle);"RPM", 50, 0, 0, 12000, 0
|
||||
float[IDLE_ADVANCE_CURVE_SIZE] idleAdvance ;Optional timing advance table for Idle (see useSeparateAdvanceForIdle);"deg", 1, 0, -20, 90, 1
|
||||
uint8_t[IDLE_VE_SIZE] autoscale idleVeRpmBins;;"RPM", 10, 0, 0, 2500, 0
|
||||
|
|
|
@ -543,6 +543,14 @@ enable2ndByteCanID = false
|
|||
yBins = cltCrankingCorr
|
||||
gauge = CLTGauge
|
||||
|
||||
curve = cltCrankingTaperDurationCurve, "Cranking taper duration multiplier"
|
||||
columnLabel = "Coolant", "Multiplier"
|
||||
xAxis = -40, 120, 9
|
||||
yAxis = 0, 3, 10
|
||||
xBins = cltCrankingTaperCorrBins, coolant
|
||||
yBins = cltCrankingTaperCorr
|
||||
gauge = CLTGauge
|
||||
|
||||
curve = cltIdleRPMCurve, "Idle Target RPM"
|
||||
columnLabel = "Coolant", "RPM"
|
||||
xAxis = -40, 120, 9
|
||||
|
@ -1790,6 +1798,7 @@ menuDialog = main
|
|||
subMenu = std_separator
|
||||
|
||||
subMenu = cltCrankingCurve, "Cranking IAC CLT multiplier", 0, {overrideCrankingIacSetting == 1}
|
||||
subMenu = cltCrankingTaperDurationCurve, "Cranking taper duration multiplier", 0, {useCrankingIdleTaperTableSetting == 1}
|
||||
|
||||
menu = "&Idle"
|
||||
subMenu = idleSettings, "Idle settings"
|
||||
|
@ -3823,6 +3832,7 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_
|
|||
field = "Cranking base IAC position", crankingIACposition
|
||||
field = "After cranking IAC taper duration",afterCrankingIACtaperDuration
|
||||
field = "Override cranking IAC CLT multiplier", overrideCrankingIacSetting
|
||||
field = "Use cranking taper duration multiplier", useCrankingIdleTaperTableSetting
|
||||
|
||||
dialog = crankingIgnition, "Ignition"
|
||||
field = "Timing Advance mode", useSeparateAdvanceForCranking
|
||||
|
|
|
@ -130,7 +130,7 @@ class MockIdleController : public IIdleController {
|
|||
MOCK_METHOD(float, getRunningOpenLoop, (float rpm, float clt, SensorResult tps), (override));
|
||||
MOCK_METHOD(float, getOpenLoop, (IIdleController::Phase phase, float rpm, float clt, SensorResult tps, float crankingTaperFraction), (override));
|
||||
MOCK_METHOD(float, getClosedLoop, (IIdleController::Phase phase, float tps, int rpm, int target), (override));
|
||||
MOCK_METHOD(float, getCrankingTaperFraction, (), (const, override));
|
||||
MOCK_METHOD(float, getCrankingTaperFraction, (float clt), (const, override));
|
||||
MOCK_METHOD(bool, isIdlingOrTaper, (), (const, override));
|
||||
MOCK_METHOD(float, getIdleTimingAdjustment, (int rpm), (override));
|
||||
};
|
||||
|
|
|
@ -275,28 +275,78 @@ TEST(idle_v2, getCrankingTaperFraction) {
|
|||
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
|
||||
StrictMock<MockOpenLoopIdler> dut;
|
||||
|
||||
float expectedClt = 37;
|
||||
engineConfiguration->afterCrankingIACtaperDuration = 500;
|
||||
engineConfiguration->useCrankingIdleTaperTableSetting = false;
|
||||
|
||||
// 0 cycles - no taper yet, pure cranking value
|
||||
EXPECT_FLOAT_EQ(0, dut.getCrankingTaperFraction());
|
||||
EXPECT_FLOAT_EQ(0, dut.getCrankingTaperFraction(expectedClt));
|
||||
|
||||
// 250 cycles - half way, 50% each value -> outputs 50
|
||||
for (size_t i = 0; i < 250; i++) {
|
||||
engine->rpmCalculator.onNewEngineCycle();
|
||||
}
|
||||
EXPECT_FLOAT_EQ(0.5f, dut.getCrankingTaperFraction());
|
||||
EXPECT_FLOAT_EQ(0.5f, dut.getCrankingTaperFraction(expectedClt));
|
||||
|
||||
// 500 cycles - fully tapered, should be running value
|
||||
for (size_t i = 0; i < 250; i++) {
|
||||
engine->rpmCalculator.onNewEngineCycle();
|
||||
}
|
||||
EXPECT_FLOAT_EQ(1, dut.getCrankingTaperFraction());
|
||||
EXPECT_FLOAT_EQ(1, dut.getCrankingTaperFraction(expectedClt));
|
||||
|
||||
// 1000 cycles - still fully tapered, should be running value
|
||||
for (size_t i = 0; i < 500; i++) {
|
||||
engine->rpmCalculator.onNewEngineCycle();
|
||||
}
|
||||
EXPECT_FLOAT_EQ(2, dut.getCrankingTaperFraction());
|
||||
EXPECT_FLOAT_EQ(2, dut.getCrankingTaperFraction(expectedClt));
|
||||
}
|
||||
|
||||
TEST(idle_v2, getCrankingTaperFractionWithMultiplier) {
|
||||
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
|
||||
StrictMock<MockOpenLoopIdler> dut;
|
||||
|
||||
float expectedClt = 40;
|
||||
|
||||
engineConfiguration->afterCrankingIACtaperDuration = 200;
|
||||
engineConfiguration->useCrankingIdleTaperTableSetting = true;
|
||||
|
||||
float curve[CLT_CRANKING_CURVE_SIZE] = {
|
||||
1.0, // 0C
|
||||
1.0, // 10C
|
||||
1.0, // 20C
|
||||
0.5, // 30C
|
||||
0.4, // 40C
|
||||
0.3, // 50C
|
||||
0.2, // 60C
|
||||
0.1 // 70C
|
||||
};
|
||||
|
||||
for (int i = 0; i < CLT_CRANKING_CURVE_SIZE; i++) {
|
||||
config->cltCrankingTaperCorrBins[i] = i * 10;
|
||||
config->cltCrankingTaperCorr[i] = curve[i];
|
||||
}
|
||||
|
||||
// 0 cycles - no taper yet, pure cranking value
|
||||
EXPECT_FLOAT_EQ(0, dut.getCrankingTaperFraction(expectedClt));
|
||||
|
||||
// 50 cycles in - total taper duration should be 200 * 0.4 (40C) = 80 cyclyes instead of 200
|
||||
for (size_t i = 0; i < 50; i++) {
|
||||
engine->rpmCalculator.onNewEngineCycle();
|
||||
}
|
||||
// So 80*0.625 = 50 cycles
|
||||
EXPECT_FLOAT_EQ(0.625f, dut.getCrankingTaperFraction(expectedClt));
|
||||
// testing 20C colder, should use 1.0f so 200*0.25 = 50 cycles
|
||||
EXPECT_FLOAT_EQ(0.25f, dut.getCrankingTaperFraction(expectedClt - 20));
|
||||
|
||||
// 200 cycles in - total taper duration should be done by 40C
|
||||
for (size_t i = 0; i < 150; i++) {
|
||||
engine->rpmCalculator.onNewEngineCycle();
|
||||
}
|
||||
// Taper last only 80 cycles, so 2.5*80 = 200 cycles
|
||||
EXPECT_FLOAT_EQ(2.5f, dut.getCrankingTaperFraction(expectedClt));
|
||||
// Taper last full length
|
||||
EXPECT_FLOAT_EQ(1.0f, dut.getCrankingTaperFraction(expectedClt - 20));
|
||||
|
||||
}
|
||||
|
||||
TEST(idle_v2, openLoopCoastingTable) {
|
||||
|
@ -376,7 +426,7 @@ struct IntegrationIdleMock : public IdleController {
|
|||
MOCK_METHOD(ICP, determinePhase, (int rpm, int targetRpm, SensorResult tps, float vss, float crankingTaperFraction), (override));
|
||||
MOCK_METHOD(float, getOpenLoop, (ICP phase, float rpm, float clt, SensorResult tps, float crankingTaperFraction), (override));
|
||||
MOCK_METHOD(float, getClosedLoop, (ICP phase, float tps, int rpm, int target), (override));
|
||||
MOCK_METHOD(float, getCrankingTaperFraction, (), (const, override));
|
||||
MOCK_METHOD(float, getCrankingTaperFraction, (float clt), (const, override));
|
||||
};
|
||||
|
||||
TEST(idle_v2, IntegrationManual) {
|
||||
|
@ -394,7 +444,7 @@ TEST(idle_v2, IntegrationManual) {
|
|||
.WillOnce(Return(1000));
|
||||
|
||||
// 30% of the way through cranking taper
|
||||
EXPECT_CALL(dut, getCrankingTaperFraction())
|
||||
EXPECT_CALL(dut, getCrankingTaperFraction(expectedClt))
|
||||
.WillOnce(Return(0.3f));
|
||||
|
||||
// Determine phase will claim we're idling
|
||||
|
@ -427,7 +477,7 @@ TEST(idle_v2, IntegrationAutomatic) {
|
|||
.WillOnce(Return(1000));
|
||||
|
||||
// 40% of the way through cranking taper
|
||||
EXPECT_CALL(dut, getCrankingTaperFraction())
|
||||
EXPECT_CALL(dut, getCrankingTaperFraction(expectedClt))
|
||||
.WillOnce(Return(0.4f));
|
||||
|
||||
// Determine phase will claim we're idling
|
||||
|
@ -463,7 +513,7 @@ TEST(idle_v2, IntegrationClamping) {
|
|||
.WillOnce(Return(1000));
|
||||
|
||||
// 50% of the way through cranking taper
|
||||
EXPECT_CALL(dut, getCrankingTaperFraction())
|
||||
EXPECT_CALL(dut, getCrankingTaperFraction(expectedClt))
|
||||
.WillOnce(Return(0.5f));
|
||||
|
||||
// Determine phase will claim we're idling
|
||||
|
|
Loading…
Reference in New Issue