* [DRAFT] RPM soft limit and hysteresis #5214, #5224 * fix m_timingRetard * fix rpmHardLimitHyst * unit-tests for #5214, #5224
This commit is contained in:
parent
0316460f27
commit
919ed2d934
|
@ -137,6 +137,8 @@ float getRunningFuel(float baseFuel) {
|
|||
correction *= engine->launchController.getFuelCoefficient();
|
||||
#endif
|
||||
|
||||
correction *= getLimpManager()->getLimitingFuelCorrection();
|
||||
|
||||
engine->fuelComputer.totalFuelCorrection = correction;
|
||||
|
||||
float runningFuel = baseFuel * correction;
|
||||
|
|
|
@ -104,7 +104,9 @@ static void prepareCylinderIgnitionSchedule(angle_t dwellAngleDuration, floatms_
|
|||
// Offset by this cylinder's position in the cycle
|
||||
+ getCylinderAngle(event->cylinderIndex, event->cylinderNumber)
|
||||
// Pull any extra timing for knock retard
|
||||
+ engine->module<KnockController>()->getKnockRetard();
|
||||
+ engine->module<KnockController>()->getKnockRetard()
|
||||
// Degrees of timing REMOVED from actual timing during soft RPM limit window
|
||||
+ getLimpManager()->getLimitingTimingRetard();
|
||||
|
||||
efiAssertVoid(CUSTOM_SPARK_ANGLE_1, !cisnan(sparkAngle), "sparkAngle#1");
|
||||
|
||||
|
|
|
@ -60,8 +60,9 @@ void LimpManager::updateState(int rpm, efitick_t nowNt) {
|
|||
? interpolate2d(Sensor::getOrZero(SensorType::Clt), engineConfiguration->cltRevLimitRpmBins, engineConfiguration->cltRevLimitRpm)
|
||||
: (float)engineConfiguration->rpmHardLimit;
|
||||
|
||||
// Require 50 rpm drop before resuming
|
||||
if (m_revLimitHysteresis.test(rpm, revLimit, revLimit - 50)) {
|
||||
// Require configurable rpm drop before resuming
|
||||
float revLimitLow = revLimit - engineConfiguration->rpmHardLimitHyst;
|
||||
if (m_revLimitHysteresis.test(rpm, revLimit, revLimitLow)) {
|
||||
if (engineConfiguration->cutFuelOnHardLimit) {
|
||||
allowFuel.clear(ClearReason::HardLimit);
|
||||
}
|
||||
|
@ -70,6 +71,10 @@ void LimpManager::updateState(int rpm, efitick_t nowNt) {
|
|||
allowSpark.clear(ClearReason::HardLimit);
|
||||
}
|
||||
}
|
||||
|
||||
m_timingRetard = interpolateClamped(revLimitLow, 0, revLimit, engineConfiguration->rpmSoftLimitTimingRetard, rpm);
|
||||
percent_t fuelAdded = interpolateClamped(revLimitLow, 0, revLimit, engineConfiguration->rpmSoftLimitFuelAdded, rpm);
|
||||
m_fuelCorrection = 1.0f + fuelAdded / 100;
|
||||
}
|
||||
|
||||
#if EFI_SHAFT_POSITION_INPUT
|
||||
|
@ -227,3 +232,15 @@ LimpState LimpManager::allowIgnition() const {
|
|||
}
|
||||
return {true, ClearReason::None};
|
||||
}
|
||||
|
||||
angle_t LimpManager::getLimitingTimingRetard() const {
|
||||
if (!engineConfiguration->cutSparkOnHardLimit)
|
||||
return 0;
|
||||
return m_timingRetard;
|
||||
}
|
||||
|
||||
float LimpManager::getLimitingFuelCorrection() const {
|
||||
if (!engineConfiguration->cutFuelOnHardLimit)
|
||||
return 1.0f; // no correction
|
||||
return m_fuelCorrection;
|
||||
}
|
||||
|
|
|
@ -113,6 +113,9 @@ public:
|
|||
|
||||
bool allowTriggerInput() const;
|
||||
|
||||
angle_t getLimitingTimingRetard() const;
|
||||
float getLimitingFuelCorrection() const;
|
||||
|
||||
// Other subsystems call these APIs to indicate a problem has occurred
|
||||
void reportEtbProblem();
|
||||
void fatalError();
|
||||
|
@ -139,6 +142,9 @@ private:
|
|||
|
||||
// Ignition switch state
|
||||
bool m_ignitionOn = false;
|
||||
|
||||
angle_t m_timingRetard = 0;
|
||||
float m_fuelCorrection = 1.0f;
|
||||
};
|
||||
|
||||
LimpManager * getLimpManager();
|
||||
|
|
|
@ -3677,10 +3677,16 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_
|
|||
field = "Cut fuel on RPM limit", cutFuelOnHardLimit
|
||||
field = "Cut spark on RPM limit", cutSparkOnHardLimit
|
||||
field = "Use CLT-based RPM limit curve", useCltBasedRpmLimit, { cutFuelOnHardLimit || cutSparkOnHardLimit }
|
||||
field = "RPM hard limit", rpmHardLimit, { (cutFuelOnHardLimit || cutSparkOnHardLimit) && !useCltBasedRpmLimit }
|
||||
field = "RPM hard limit", rpmHardLimit, { (cutFuelOnHardLimit || cutSparkOnHardLimit) && !useCltBasedRpmLimit }
|
||||
field = "RPM limit hysteresis", rpmHardLimitHyst
|
||||
field = "Boost cut pressure", boostCutPressure
|
||||
field = "Minimum oil pressure after start", minOilPressureAfterStart
|
||||
|
||||
dialog = softRpmLimitSettings, "Soft RPM Limit"
|
||||
field = "Window size", rpmSoftLimitWindowSize
|
||||
field = "Timing retard", rpmSoftLimitTimingRetard, { cutSparkOnHardLimit }
|
||||
field = "Fuel added", rpmSoftLimitFuelAdded, { cutFuelOnHardLimit }
|
||||
|
||||
dialog = etbLimits, "Electronic Throttle Limiting"
|
||||
field = "Smoothly close the throttle to limit RPM."
|
||||
field = "Soft limiter start", etbRevLimitStart
|
||||
|
@ -3692,6 +3698,7 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_
|
|||
|
||||
dialog = limitsAndFallbackLeft
|
||||
panel = limitsSettings
|
||||
panel = softRpmLimitSettings, West, { (cutFuelOnHardLimit || cutSparkOnHardLimit) && !useCltBasedRpmLimit }
|
||||
panel = etbLimits
|
||||
panel = fallbacks
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "pch.h"
|
||||
|
||||
#include "fuel_math.h"
|
||||
#include "limp_manager.h"
|
||||
|
||||
TEST(limp, testFatalError) {
|
||||
|
@ -93,6 +94,76 @@ TEST(limp, revLimitCltBased) {
|
|||
EXPECT_TRUE(dut.allowInjection());
|
||||
}
|
||||
|
||||
TEST(limp, revHardLimitHyst) {
|
||||
EngineTestHelper eth(TEST_ENGINE);
|
||||
|
||||
engineConfiguration->rpmHardLimit = 2500;
|
||||
engineConfiguration->rpmHardLimitHyst = 200;
|
||||
|
||||
LimpManager dut;
|
||||
|
||||
// Under rev limit, inj/ign allowed
|
||||
dut.updateState(2500, 0);
|
||||
EXPECT_TRUE(dut.allowIgnition());
|
||||
EXPECT_TRUE(dut.allowInjection());
|
||||
|
||||
// Over rev limit, no injection or ignition
|
||||
dut.updateState(2501, 0);
|
||||
EXPECT_FALSE(dut.allowIgnition());
|
||||
EXPECT_FALSE(dut.allowInjection());
|
||||
|
||||
// Now set back inside the limit window - still not allowed
|
||||
dut.updateState(2300, 0);
|
||||
EXPECT_FALSE(dut.allowIgnition());
|
||||
EXPECT_FALSE(dut.allowInjection());
|
||||
|
||||
// Now recover back to under lower limit
|
||||
dut.updateState(2299, 0);
|
||||
EXPECT_TRUE(dut.allowIgnition());
|
||||
EXPECT_TRUE(dut.allowInjection());
|
||||
}
|
||||
|
||||
TEST(limp, revSoftLimit) {
|
||||
EngineTestHelper eth(FORD_ASPIRE_1996);
|
||||
|
||||
engineConfiguration->rpmHardLimit = 2500;
|
||||
engineConfiguration->rpmHardLimitHyst = 200;
|
||||
engineConfiguration->rpmSoftLimitTimingRetard = 10; // 10 deg
|
||||
engineConfiguration->rpmSoftLimitFuelAdded = 20; // 20%
|
||||
|
||||
eth.engine.updateSlowSensors();
|
||||
Sensor::setMockValue(SensorType::Clt, 36.605f);
|
||||
Sensor::setMockValue(SensorType::Iat, 30.0f);
|
||||
|
||||
// this is 5ms base fuel with some default CLT/IAT corrections
|
||||
static const float baseFuel = 5.0f;
|
||||
static const float normalRunningFuel = 5.3679f;
|
||||
|
||||
// Under rev limit, no inj/ign corrections
|
||||
Sensor::setMockValue(SensorType::Rpm, 2300);
|
||||
eth.engine.periodicFastCallback();
|
||||
|
||||
EXPECT_FLOAT_EQ(0, getLimpManager()->getLimitingTimingRetard());
|
||||
EXPECT_FLOAT_EQ(1, getLimpManager()->getLimitingFuelCorrection());
|
||||
// this is normal injection mode, no limiting fuel corrections
|
||||
ASSERT_NEAR(normalRunningFuel, getRunningFuel(baseFuel), EPS4D) << "base fuel";
|
||||
|
||||
// For upper rev limit, we expect maximum inj/ign corrections
|
||||
Sensor::setMockValue(SensorType::Rpm, 2500);
|
||||
eth.engine.periodicFastCallback();
|
||||
|
||||
EXPECT_FLOAT_EQ(10, getLimpManager()->getLimitingTimingRetard()); // 10 deg
|
||||
EXPECT_FLOAT_EQ(1.2f, getLimpManager()->getLimitingFuelCorrection()); // 20%
|
||||
ASSERT_NEAR(normalRunningFuel * 1.2f, getRunningFuel(baseFuel), EPS4D) << "base fuel"; // 20%
|
||||
|
||||
// In the middle of the limit window, we expect 50% interpolated inj/ign corrections
|
||||
Sensor::setMockValue(SensorType::Rpm, 2400);
|
||||
eth.engine.periodicFastCallback();
|
||||
EXPECT_FLOAT_EQ(5, getLimpManager()->getLimitingTimingRetard()); // 5 deg
|
||||
EXPECT_FLOAT_EQ(1.1f, getLimpManager()->getLimitingFuelCorrection()); // 10%
|
||||
ASSERT_NEAR(normalRunningFuel * 1.1f, getRunningFuel(baseFuel), EPS4D) << "base fuel"; // 10%
|
||||
}
|
||||
|
||||
TEST(limp, boostCut) {
|
||||
EngineTestHelper eth(TEST_ENGINE);
|
||||
|
||||
|
|
Loading…
Reference in New Issue