diff --git a/firmware/controllers/algo/defaults/default_fuel.cpp b/firmware/controllers/algo/defaults/default_fuel.cpp index d562eb5560..a46d1e74c9 100644 --- a/firmware/controllers/algo/defaults/default_fuel.cpp +++ b/firmware/controllers/algo/defaults/default_fuel.cpp @@ -183,6 +183,40 @@ static void setDefaultLambdaTable() { } } +void setDefaultWallWetting() { +#if !EFI_UNIT_TEST + // todo: this is a reasonable default for what kinds of engines exactly? + engineConfiguration->wwaeTau = 0.3; + engineConfiguration->wwaeBeta = 0.3; +#endif // EFI_UNIT_TEST + + // linear reasonable bins + setLinearCurve(engineConfiguration->wwCltBins, -40, 100, 1); + setLinearCurve(engineConfiguration->wwMapBins, 10, 80, 1); + + // These values are derived from the GM factory tune for a gen3 LS engine + // Who knows if they're good for anything else, but at least they look nice? + static constexpr float tauClt[] = { + 1.45, 1.30, 1.17, 1.05, 0.90, 0.82, 0.75, 0.70 + }; + copyArray(engineConfiguration->wwTauCltValues, tauClt); + + static constexpr float tauMap[] = { + 0.38, 0.55, 0.69, 0.86, 0.90, 0.95, 0.97, 1.00 + }; + copyArray(engineConfiguration->wwTauMapValues, tauMap); + + static constexpr float betaClt[] = { + 0.73, 0.66, 0.57, 0.46, 0.38, 0.31, 0.24, 0.19 + }; + copyArray(engineConfiguration->wwBetaCltValues, betaClt); + + static constexpr float betaMap[] = { + 0.21, 0.40, 0.60, 0.79, 0.85, 0.90, 0.95, 1.00 + }; + copyArray(engineConfiguration->wwBetaMapValues, betaMap); +} + void setDefaultFuel() { // Base injection configuration engineConfiguration->isInjectionEnabled = true; @@ -233,11 +267,7 @@ void setDefaultFuel() { engineConfiguration->tpsAccelEnrichmentThreshold = 40; // TPS % change, per engine cycle -#if !EFI_UNIT_TEST - // todo: this is a reasonable default for what kinds of engines exactly? - engineConfiguration->wwaeTau = 0.3; - engineConfiguration->wwaeBeta = 0.3; -#endif // EFI_UNIT_TEST + setDefaultWallWetting(); // TPS/TPS AE curve setMazdaMiataNbTpsTps(); diff --git a/firmware/controllers/algo/wall_fuel.cpp b/firmware/controllers/algo/wall_fuel.cpp index d0ebdfa3a9..9e83d73947 100644 --- a/firmware/controllers/algo/wall_fuel.cpp +++ b/firmware/controllers/algo/wall_fuel.cpp @@ -86,23 +86,63 @@ float WallFuel::getWallFuel() const { return wallFuel; } -/* - TODO: these parameters, tau and beta vary with various engine parameters, - most notably manifold pressure (as a proxy for air speed), and coolant - temperature (as a proxy for the intake valve and runner temperature). - - TAU: decreases with increasing temperature. - decreases with decreasing manifold pressure. - - BETA: decreases with increasing temperature. - decreases with decreasing manifold pressure. -*/ float WallFuelController::computeTau() const { - return engineConfiguration->wwaeTau; + if (!engineConfiguration->complexWallModel) { + return engineConfiguration->wwaeTau; + } + + // Default to normal operating temperature in case of + // CLT failure, this is not critical to get perfect + float clt = Sensor::get(SensorType::Clt).value_or(90); + + float tau = interpolate2d( + clt, + engineConfiguration->wwCltBins, + engineConfiguration->wwTauCltValues + ); + + // If you have a MAP sensor, apply MAP correction + if (Sensor::hasSensor(SensorType::Map)) { + auto map = Sensor::get(SensorType::Map).value_or(60); + + tau *= interpolate2d( + map, + engineConfiguration->wwMapBins, + engineConfiguration->wwTauMapValues + ); + } + + return tau; } float WallFuelController::computeBeta() const { - return engineConfiguration->wwaeBeta; + if (!engineConfiguration->complexWallModel) { + return engineConfiguration->wwaeBeta; + } + + // Default to normal operating temperature in case of + // CLT failure, this is not critical to get perfect + float clt = Sensor::get(SensorType::Clt).value_or(90); + + float beta = interpolate2d( + clt, + engineConfiguration->wwCltBins, + engineConfiguration->wwBetaCltValues + ); + + // If you have a MAP sensor, apply MAP correction + if (Sensor::hasSensor(SensorType::Map)) { + auto map = Sensor::get(SensorType::Map).value_or(60); + + beta *= interpolate2d( + map, + engineConfiguration->wwMapBins, + engineConfiguration->wwBetaMapValues + ); + } + + // Clamp to 0..1 (you can't have more than 100% of the fuel hit the wall!) + return clampF(0, beta, 1); } void WallFuelController::onFastCallback() { diff --git a/firmware/integration/rusefi_config.txt b/firmware/integration/rusefi_config.txt index 7433f5e8e1..d30b6454e4 100644 --- a/firmware/integration/rusefi_config.txt +++ b/firmware/integration/rusefi_config.txt @@ -1049,7 +1049,7 @@ custom idle_mode_e 4 bits, U32, @OFFSET@, [0:0], "Open Loop + Closed Loop", "Ope bit isInjectionEnabled;+Enable fuel injection - This is default off for new projects as a safety feature, set to "true" to enable fuel injection and further injector settings. bit isIgnitionEnabled;+Enable ignition - This is default off for new projects as a safety feature, set to "true" to enable ignition and further ignition settings. bit isCylinderCleanupEnabled;+When enabled if TPS is held above 95% no fuel is injected while cranking to clear excess fuel from the cylinders. - bit unused1476b3 + 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 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. @@ -1504,7 +1504,17 @@ int8_t[MAX_CYLINDER_COUNT iterate] fuelTrim;;"Percent", @@PERCENT_TRIM_BYTE_PACK uint16_t vvtActivationDelayMs;We need to give engine time to build oil pressure without diverting it to VVT;"ms", 1, 0, 0, 65000, 0 uint16_t unusedShort;;"RPM", 1, 0, 0, 65000, 0 - int[94] mainUnusedEnd;;"units", 1, 0, 0, 1, 0 +#define WWAE_TABLE_SIZE 8 + +int8_t[WWAE_TABLE_SIZE] wwCltBins;;"deg C", 1, 0, -40, 120, 0 +uint8_t[WWAE_TABLE_SIZE] autoscale wwTauCltValues;;"", 0.01, 0, 0, 2.5, 2 +uint8_t[WWAE_TABLE_SIZE] autoscale wwBetaCltValues;;"", 0.01, 0, 0, 1, 2 + +int8_t[WWAE_TABLE_SIZE] wwMapBins;;"kPa", 1, 0, 0, 250, 0 +uint8_t[WWAE_TABLE_SIZE] autoscale wwTauMapValues;;"", 0.01, 0, 0, 2.5, 2 +uint8_t[WWAE_TABLE_SIZE] autoscale wwBetaMapValues;;"", 0.01, 0, 0, 2.5, 2 + +uint8_t[330] mainUnusedEnd;;"units", 1, 0, 0, 1, 0 ! end of engine_configuration_s end_struct diff --git a/firmware/tunerstudio/rusefi.input b/firmware/tunerstudio/rusefi.input index 4be5019036..0d2b24a4c5 100644 --- a/firmware/tunerstudio/rusefi.input +++ b/firmware/tunerstudio/rusefi.input @@ -619,6 +619,38 @@ enable2ndByteCanID = false xBins = hpfpDeadtimeVoltsBins yBins = hpfpDeadtimeMS + curve = wwTauCltCurve, "Evap time vs. CLT" + columnLabel = "coolant", "seconds" + xAxis = -40, 120, 9 + yAxis = 0, 2, 9 + xBins = wwCltBins, coolant + yBins = wwTauCltValues + gauge = CLTGauge + + curve = wwTauMapCurve, "Evap time vs. MAP" + columnLabel = "MAP", "mult" + xAxis = 0, 100, 5 + yAxis = 0, 2, 9 + xBins = wwMapBins, MAPValue + yBins = wwTauMapValues + gauge = MAPGauge + + curve = wwBetaCltCurve, "Impact fraction vs. CLT" + columnLabel = "coolant", "fraction" + xAxis = -40, 120, 9 + yAxis = 0, 2, 9 + xBins = wwCltBins, coolant + yBins = wwBetaCltValues + gauge = CLTGauge + + curve = wwBetaMapCurve, "Impact fraction vs. MAP" + columnLabel = "MAP", "mult" + xAxis = 0, 100, 5 + yAxis = 0, 2, 9 + xBins = wwMapBins, MAPValue + yBins = wwBetaMapValues + gauge = MAPGauge + [TableEditor] ; table_id, map3d_id, "title", page @@ -1354,6 +1386,9 @@ menuDialog = main subMenu = tpsTpsAccelTbl, "TPS/TPS acceleration extra fuel", 0, {isInjectionEnabled == 1} subMenu = mapAccelTaper, "Engine load AE taper", 0, {isInjectionEnabled == 1} + groupMenu = "Wall wetting AE" + groupChildMenu = wwTauCurves, "Evap time", 0, { complexWallModel != 0 } + groupChildMenu = wwBetaCurves, "Impact fraction", 0, { complexWallModel != 0 } menu = "Ignition" subMenu = ignitionSettings, "Ignition settings" @@ -3240,8 +3275,9 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00" field = "Fraction Divisor", tpsAccelFractionDivisor dialog = WallWettingAccelPanel, "Wall Wetting (alpha version)" - field = "evaporation time constant / tau", wwaeTau - field = "added to wall coef / beta", wwaeBeta + field = "Wall fueling model type", complexWallModel + field = "evaporation time constant / tau", wwaeTau, { complexWallModel == 0 } + field = "added to wall coef / beta", wwaeBeta, { complexWallModel == 0 } ; Tuning->AccelEnrichment @@ -3251,6 +3287,16 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00" field = "No accel after RPM hard limit", noAccelAfterHardLimitPeriodSecs + dialog = wwTauCurves, "Wall wetting AE evaporation time" + field = "#Set a base evaporation time based on coolant temperature, and a multiplier based on MAP." + panel = wwTauCltCurve + panel = wwTauMapCurve + + dialog = wwBetaCurves, "Wall wetting AE impact fraction" + field = "#Set a base impact fraction based on coolant temperature, and a multiplier based on MAP." + panel = wwBetaCltCurve + panel = wwBetaMapCurve + dialog = auxValvesIO, "Outputs" field = "aux valve #1", auxValves1 field = "aux valve #2", auxValves2