Knock fuel trim and deacceleration (#7024)

* - knock fuel trim
- knock disable suppression then deceleration

* - knock disable suppression then deceleration syntax fix

* - knock disable suppression for test reapply

* - knock disable suppression for test reapply fix

* - knock fuel trim tests

---------

Co-authored-by: 3er0.1ive <3er0.1ive@veeroute.com>
This commit is contained in:
3eR01ive 2024-11-01 16:28:07 +03:00 committed by GitHub
parent 1829e1cec6
commit 691fb3f3db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 92 additions and 8 deletions

View File

@ -66,20 +66,23 @@ void KnockControllerBase::onKnockSenseCompleted(uint8_t cylinderNumber, float db
auto retardFraction = engineConfiguration->knockRetardAggression * 0.01f;
auto retardAmount = distToMinimum * retardFraction;
// TODO: remove magic 30% m_maximumFuelTrim?
auto maximumFuelTrim = 0.3f;
auto trimFuelFraction = engineConfiguration->knockFuelTrimAggression * 0.01f;
float trimFuelPersent = clampF(0.0, (float)engineConfiguration->knockFuelTrim, 30.0);
float trimFuelCoeff = (trimFuelPersent / 100.f);
float trimFuelAmount = trimFuelCoeff * trimFuelFraction;
float trimFuelPercent = clampF(0.f, (float)engineConfiguration->knockFuelTrim, maximumFuelTrim * 100.f);
float trimFuelAmountPercent = trimFuelPercent * trimFuelFraction;
float trimFuelAmount = trimFuelAmountPercent / 100.f;
{
// Adjust knock retard under lock
chibios_rt::CriticalSectionLocker csl;
auto newRetard = m_knockRetard + retardAmount;
m_knockRetard = clampF(0, newRetard, m_maximumRetard);
m_knockRetard = clampF(0.f, newRetard, m_maximumRetard);
auto newFuelTrim = m_knockFuelTrimMultiplier + trimFuelAmount;
m_knockFuelTrimMultiplier = clampF(0.0, newFuelTrim, 0.3); // TODO: remove magic 30%
m_knockFuelTrimMultiplier = clampF(0.f, newFuelTrim, maximumFuelTrim);
}
}
}
@ -103,7 +106,7 @@ void KnockControllerBase::onFastCallback() {
constexpr auto callbackPeriodSeconds = FAST_CALLBACK_PERIOD_MS / 1000.0f;
auto applyRetardAmount = engineConfiguration->knockRetardReapplyRate * callbackPeriodSeconds;
auto applyFuelAmount = engineConfiguration->knockFuelTrimReapplyRate * callbackPeriodSeconds;
auto applyFuelAmount = engineConfiguration->knockFuelTrimReapplyRate * 0.01f * callbackPeriodSeconds;
// disable knock suppression then deceleration
auto TPSValue = Sensor::getOrZero(SensorType::Tps1);
@ -132,7 +135,7 @@ void KnockControllerBase::onFastCallback() {
// Reduce fuel trim at the requested rate
float newTrim = m_knockFuelTrimMultiplier - applyFuelAmount;
// don't allow retard to go negative
// don't allow trim to go negative
if (newTrim < 0) {
m_knockFuelTrimMultiplier = 0;
} else {

View File

@ -1723,7 +1723,7 @@ linear_sensor_s auxLinear4
uint8_t autoscale knockSuppressMinTps;Below TPS value all knock suppression will be disabled.;"%", 1, 0, 0, 100, 1
uint8_t autoscale knockFuelTrimAggression;Fuel to odd when a knock event occurs. Advice: 5% (mild), 10% (turbo/high comp.), 15% (high knock, e.g. GDI), 20% (spicy lump),;"%", 0.1, 0, 0, 20, 1
uint8_t autoscale knockFuelTrimReapplyRate;After a knock event, reapply fuel at this rate.;"deg/s", 0.1, 0, 0, 10, 1
uint8_t autoscale knockFuelTrimReapplyRate;After a knock event, reapply fuel at this rate.;"1%/s", 0.1, 0, 0, 10, 1
uint8_t autoscale knockFuelTrim;Fuel trim when knock, max 30%;"%", 1, 0, 0, 30, 1
float knockSpectrumSensitivity;;"sense", 1, 0, 0, 1, 2

View File

@ -92,3 +92,84 @@ TEST(Knock, Reapply) {
// Should have no knock retard
EXPECT_FLOAT_EQ(dut.getKnockRetard(), 0);
}
TEST(Knock, FuelTrim) {
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
// Aggression of 10%
engineConfiguration->knockFuelTrimAggression = 10;
engineConfiguration->knockFuelTrim = 30;
MockKnockController dut;
dut.onFastCallback();
// No trim unless we knock
ASSERT_FLOAT_EQ(dut.getFuelTrimMultiplier(), 1.0);
// Send some weak knocks, should yield no response
for (size_t i = 0; i < 10; i++) {
dut.onKnockSenseCompleted(0, 10, 0);
}
EXPECT_FLOAT_EQ(dut.getFuelTrimMultiplier(), 1.0);
// Send a strong knock!
dut.onKnockSenseCompleted(0, 30, 0);
// Should retard 10% of the distance between current timing and "maximum"
EXPECT_FLOAT_EQ(dut.getFuelTrimMultiplier(), 1.03);
// Send tons of strong knocks, make sure we don't go over the configured limit
for (size_t i = 0; i < 100; i++) {
dut.onKnockSenseCompleted(0, 30, 0);
}
EXPECT_FLOAT_EQ(dut.getFuelTrimMultiplier(), 1.3);
}
TEST(Knock, FuelTrimReapply) {
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
MockKnockController dut;
dut.onFastCallback();
// Aggression of 100%
engineConfiguration->knockFuelTrimAggression = 10;
// Apply 1%/second
engineConfiguration->knockFuelTrimReapplyRate = 1;
// fuel trim 30%
engineConfiguration->knockFuelTrim = 30;
// disable suppress for test
engineConfiguration->knockSuppressMinTps = 0;
// Send a strong knock!
dut.onKnockSenseCompleted(0, 30, 0);
// 100% trim
float trim = 1.03;
// Should retard 100% of the distance between current timing and "maximum"
EXPECT_FLOAT_EQ(dut.getFuelTrimMultiplier(), trim);
constexpr auto fastPeriodSec = FAST_CALLBACK_PERIOD_MS / 1000.0f;
// call the fast callback, should reapply 1% trim * callback period
dut.onFastCallback();
EXPECT_FLOAT_EQ(dut.getFuelTrimMultiplier(), trim - 0.01f * fastPeriodSec);
// 10 updates total
for (size_t i = 0; i < 9; i++) {
dut.onFastCallback();
}
EXPECT_FLOAT_EQ(dut.getFuelTrimMultiplier(), trim - 10 * 0.01f * fastPeriodSec);
// Spend a long time without knock
for (size_t i = 0; i < 2000; i++) {
dut.onFastCallback();
}
// Should have no knock retard
EXPECT_FLOAT_EQ(dut.getFuelTrimMultiplier(), 1.0);
}