flex fuel AFR interpolation (#2190)

* config

* implement flex

* secondary fuel default

* test

* test works

* rename

Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
Matthew Kennedy 2021-01-05 13:27:23 -08:00 committed by GitHub
parent 9578dfa269
commit eabb5c7366
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 7 deletions

View File

@ -792,6 +792,7 @@ static void setDefaultEngineConfiguration(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
setLambdaMap(config->lambdaTable, 1.0f);
engineConfiguration->stoichRatioPrimary = 14.7f * PACK_MULT_AFR_CFG;
engineConfiguration->stoichRatioSecondary = 9.0f * PACK_MULT_AFR_CFG;
setDefaultVETable(PASS_ENGINE_PARAMETER_SIGNATURE);

View File

@ -22,14 +22,33 @@ FuelComputer::FuelComputer(const ValueProvider3D& lambdaTable) : m_lambdaTable(&
float FuelComputer::getStoichiometricRatio() const {
// TODO: vary this with ethanol content/configured setting/whatever
float rawConfig = (float)CONFIG(stoichRatioPrimary) / PACK_MULT_AFR_CFG;
float primary = (float)CONFIG(stoichRatioPrimary) / PACK_MULT_AFR_CFG;
// Config compatibility: this field may be zero on ECUs with old defaults
if (rawConfig < 5) {
return 14.7f;
if (primary < 5) {
// 14.7 = E0 gasoline AFR
primary = 14.7f;
}
return rawConfig;
// Without an ethanol/flex sensor, return primary configured stoich ratio
if (!Sensor::hasSensor(SensorType::FuelEthanolPercent)) {
return primary;
}
float secondary = (float)CONFIG(stoichRatioSecondary) / PACK_MULT_AFR_CFG;
// Config compatibility: this field may be zero on ECUs with old defaults
if (secondary < 5) {
// 9.0 = E100 ethanol AFR
secondary = 9.0f;
}
auto flex = Sensor::get(SensorType::FuelEthanolPercent);
// TODO: what do do if flex sensor fails?
// Linear interpolate between primary and secondary stoich ratios
return interpolateClamped(0, primary, 100, secondary, flex.Value);
}
float FuelComputer::getTargetLambda(int rpm, float load) const {

View File

@ -1421,11 +1421,12 @@ tChargeMode_e tChargeMode;
int16_t idlerpmpid_iTermMin;iTerm min value;"", 1, 0, -30000, 30000.0, 0
spi_device_e tle6240spiDevice;
uint8_t stoichRatioPrimary;+Stoichiometric ratio for your primary fuel.;":1", {1/@@PACK_MULT_AFR_CFG@@},0, 5, 25.0, 1
uint8_t stoichRatioPrimary;+Stoichiometric ratio for your primary fuel. When Flex Fuel is enabled, this value is used when the Flex Fuel sensor indicates E0.;":1", {1/@@PACK_MULT_AFR_CFG@@},0, 5, 25.0, 1
int16_t idlerpmpid_iTermMax;iTerm max value;"", 1, 0, -30000, 30000.0, 0
spi_device_e mc33972spiDevice;
uint8_t[3] unusedSpiPadding8;;"units", 1, 0, -20, 100, 0
uint8_t stoichRatioSecondary;+Stoichiometric ratio for your secondary fuel. This value is used when the Flex Fuel sensor indicates E100.;":1", {1/@@PACK_MULT_AFR_CFG@@},0, 5, 25.0, 1
uint8_t[2] unusedSpiPadding8;;"units", 1, 0, -20, 100, 0
float etbIdleThrottleRange; ETB idle authority; "%", 1, 0, 0, 15, 0

View File

@ -1807,7 +1807,8 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00"
field = "Injector reference pressure", fuelReferencePressure, { isInjectionEnabled && injectorCompensationMode != 0 }
dialog = fuelParams, "Fuel characteristics", yAxis
field = "Stoichiometric ratio", stoichRatioPrimary, {isInjectionEnabled == 1}
field = "Stoichiometric ratio", stoichRatioPrimary, {isInjectionEnabled == 1}
field = "E100 stoichiometric ratio", stoichRatioSecondary, {isInjectionEnabled == 1 && flexSensorPin != 0 }
dialog = injectorOutputSettings, "Injector Outputs", yAxis
field = "Use only first half of pins for batch mode"

View File

@ -42,3 +42,39 @@ TEST(FuelComputer, LambdaLookup) {
EXPECT_FLOAT_EQ(dut.getTargetLambda(1500, 0.7f), 0.85f);
}
TEST(FuelComputer, FlexFuel) {
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
MockVp3d lambdaTable;
FuelComputer dut(lambdaTable);
INJECT_ENGINE_REFERENCE(&dut);
// easier values for testing
engineConfiguration->stoichRatioPrimary = 150;
engineConfiguration->stoichRatioSecondary = 100;
// No sensor -> returns primary
Sensor::resetMockValue(SensorType::FuelEthanolPercent);
EXPECT_FLOAT_EQ(15.0f, dut.getStoichiometricRatio());
// E0 -> primary afr
Sensor::setMockValue(SensorType::FuelEthanolPercent, 0);
EXPECT_FLOAT_EQ(15.0f, dut.getStoichiometricRatio());
// E50 -> half way between
Sensor::setMockValue(SensorType::FuelEthanolPercent, 50);
EXPECT_FLOAT_EQ(12.5f, dut.getStoichiometricRatio());
// E100 -> secondary afr
Sensor::setMockValue(SensorType::FuelEthanolPercent, 100);
EXPECT_FLOAT_EQ(10.0f, dut.getStoichiometricRatio());
// E(-10) -> clamp to primary
Sensor::setMockValue(SensorType::FuelEthanolPercent, -10);
EXPECT_FLOAT_EQ(15.0f, dut.getStoichiometricRatio());
// E110 -> clamp to secondary
Sensor::setMockValue(SensorType::FuelEthanolPercent, 110);
EXPECT_FLOAT_EQ(10.0f, dut.getStoichiometricRatio());
}