table for tcharge interpolation (#3855)
* extract getTChargeCoefficient * new table
This commit is contained in:
parent
05e8aab201
commit
eab4c50f77
|
@ -534,6 +534,7 @@ typedef enum {
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TCHARGE_MODE_RPM_TPS = 0,
|
TCHARGE_MODE_RPM_TPS = 0,
|
||||||
TCHARGE_MODE_AIR_INTERP = 1,
|
TCHARGE_MODE_AIR_INTERP = 1,
|
||||||
|
TCHARGE_MODE_AIR_INTERP_TABLE = 2,
|
||||||
Force_4bytes_size_tChargeMode_e = ENUM_32_BITS,
|
Force_4bytes_size_tChargeMode_e = ENUM_32_BITS,
|
||||||
} tChargeMode_e;
|
} tChargeMode_e;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,48 @@ lambda_Map3D_t lambdaMap;
|
||||||
|
|
||||||
#define tpMin 0
|
#define tpMin 0
|
||||||
#define tpMax 100
|
#define tpMax 100
|
||||||
|
|
||||||
|
static float getTChargeCoefficient(int rpm, float tps) {
|
||||||
|
engine->engineState.sd.isTChargeAirModel = engineConfiguration->tChargeMode == TCHARGE_MODE_AIR_INTERP;
|
||||||
|
|
||||||
|
// First, do TPS mode since it doesn't need any of the airflow math.
|
||||||
|
if (engineConfiguration->tChargeMode == TCHARGE_MODE_RPM_TPS) {
|
||||||
|
float minRpmKcurrentTPS = interpolateMsg("minRpm", tpMin,
|
||||||
|
engineConfiguration->tChargeMinRpmMinTps, tpMax,
|
||||||
|
engineConfiguration->tChargeMinRpmMaxTps, tps);
|
||||||
|
float maxRpmKcurrentTPS = interpolateMsg("maxRpm", tpMin,
|
||||||
|
engineConfiguration->tChargeMaxRpmMinTps, tpMax,
|
||||||
|
engineConfiguration->tChargeMaxRpmMaxTps, tps);
|
||||||
|
|
||||||
|
return interpolateMsg("Kcurr", rpmMin, minRpmKcurrentTPS, rpmMax, maxRpmKcurrentTPS, rpm);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr floatms_t gramsPerMsToKgPerHour = (3600.0f * 1000.0f) / 1000.0f;
|
||||||
|
// We're actually using an 'old' airMass calculated for the previous cycle, but it's ok, we're not having any self-excitaton issues
|
||||||
|
floatms_t airMassForEngine = engine->engineState.sd.airMassInOneCylinder * engineConfiguration->specs.cylindersCount;
|
||||||
|
// airMass is in grams per 1 cycle for 1 cyl. Convert it to airFlow in kg/h for the engine.
|
||||||
|
// And if the engine is stopped (0 rpm), then airFlow is also zero (avoiding NaN division)
|
||||||
|
floatms_t airFlow = (rpm == 0) ? 0 : airMassForEngine * gramsPerMsToKgPerHour / getEngineCycleDuration(rpm);
|
||||||
|
|
||||||
|
if (engineConfiguration->tChargeMode == TCHARGE_MODE_AIR_INTERP) {
|
||||||
|
// just interpolate between user-specified min and max coefs, based on the max airFlow value
|
||||||
|
return interpolateClamped(
|
||||||
|
0.0, engineConfiguration->tChargeAirCoefMin,
|
||||||
|
engineConfiguration->tChargeAirFlowMax, engineConfiguration->tChargeAirCoefMax,
|
||||||
|
airFlow
|
||||||
|
);
|
||||||
|
} else if (engineConfiguration->tChargeMode == TCHARGE_MODE_AIR_INTERP_TABLE) {
|
||||||
|
return interpolate2d(
|
||||||
|
airFlow,
|
||||||
|
engineConfiguration->tchargeBins,
|
||||||
|
engineConfiguration->tchargeValues
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
firmwareError(OBD_PCM_Processor_Fault, "Unexpected tChargeMode: %d", engineConfiguration->tChargeMode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// http://rusefi.com/math/t_charge.html
|
// http://rusefi.com/math/t_charge.html
|
||||||
/***panel:Charge Temperature*/
|
/***panel:Charge Temperature*/
|
||||||
temperature_t getTCharge(int rpm, float tps) {
|
temperature_t getTCharge(int rpm, float tps) {
|
||||||
|
@ -47,37 +89,18 @@ temperature_t getTCharge(int rpm, float tps) {
|
||||||
|
|
||||||
float coolantTemp = clt.Value;
|
float coolantTemp = clt.Value;
|
||||||
|
|
||||||
if ((engine->engineState.sd.isTChargeAirModel = (engineConfiguration->tChargeMode == TCHARGE_MODE_AIR_INTERP))) {
|
auto coefficient = getTChargeCoefficient(rpm, tps);
|
||||||
const floatms_t gramsPerMsToKgPerHour = (3600.0f * 1000.0f) / 1000.0f;
|
engine->engineState.sd.Tcharge_coff = coefficient;
|
||||||
// We're actually using an 'old' airMass calculated for the previous cycle, but it's ok, we're not having any self-excitaton issues
|
|
||||||
floatms_t airMassForEngine = engine->engineState.sd.airMassInOneCylinder * engineConfiguration->specs.cylindersCount;
|
|
||||||
// airMass is in grams per 1 cycle for 1 cyl. Convert it to airFlow in kg/h for the engine.
|
|
||||||
// And if the engine is stopped (0 rpm), then airFlow is also zero (avoiding NaN division)
|
|
||||||
floatms_t airFlow = (rpm == 0) ? 0 : airMassForEngine * gramsPerMsToKgPerHour / getEngineCycleDuration(rpm);
|
|
||||||
// just interpolate between user-specified min and max coefs, based on the max airFlow value
|
|
||||||
engine->engineState.sd.Tcharge_coff = interpolateClamped(0.0,
|
|
||||||
engineConfiguration->tChargeAirCoefMin,
|
|
||||||
engineConfiguration->tChargeAirFlowMax,
|
|
||||||
engineConfiguration->tChargeAirCoefMax, airFlow);
|
|
||||||
// save it for console output (instead of MAF massAirFlow)
|
|
||||||
} else {
|
|
||||||
float minRpmKcurrentTPS = interpolateMsg("minRpm", tpMin,
|
|
||||||
engineConfiguration->tChargeMinRpmMinTps, tpMax,
|
|
||||||
engineConfiguration->tChargeMinRpmMaxTps, tps);
|
|
||||||
float maxRpmKcurrentTPS = interpolateMsg("maxRpm", tpMin,
|
|
||||||
engineConfiguration->tChargeMaxRpmMinTps, tpMax,
|
|
||||||
engineConfiguration->tChargeMaxRpmMaxTps, tps);
|
|
||||||
|
|
||||||
engine->engineState.sd.Tcharge_coff = interpolateMsg("Kcurr", rpmMin, minRpmKcurrentTPS, rpmMax, maxRpmKcurrentTPS, rpm);
|
if (cisnan(coefficient)) {
|
||||||
}
|
|
||||||
|
|
||||||
if (cisnan(engine->engineState.sd.Tcharge_coff)) {
|
|
||||||
warning(CUSTOM_ERR_T2_CHARGE, "t2-getTCharge NaN");
|
warning(CUSTOM_ERR_T2_CHARGE, "t2-getTCharge NaN");
|
||||||
return coolantTemp;
|
return coolantTemp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use a robust interp. function for proper tcharge_coff clamping.
|
// Interpolate between CLT and IAT:
|
||||||
float Tcharge = interpolateClamped(0.0f, coolantTemp, 1.0f, airTemp, engine->engineState.sd.Tcharge_coff);
|
// 0.0 coefficient -> use CLT (full heat transfer)
|
||||||
|
// 1.0 coefficient -> use IAT (no heat transfer)
|
||||||
|
float Tcharge = interpolateClamped(0.0f, coolantTemp, 1.0f, airTemp, coefficient);
|
||||||
|
|
||||||
if (cisnan(Tcharge)) {
|
if (cisnan(Tcharge)) {
|
||||||
// we can probably end up here while resetting engine state - interpolation would fail
|
// we can probably end up here while resetting engine state - interpolation would fail
|
||||||
|
|
|
@ -1237,7 +1237,10 @@ int16_t tps2Max;Full throttle#2. tpsMax value as 10 bit ADC value. Not Voltage!\
|
||||||
|
|
||||||
float boostCutPressure;+MAP value above which fuel is cut in case of overboost.\nSet to 0 to disable overboost cut.;"kPa (absolute)", 1, 0, 0, 500, 0
|
float boostCutPressure;+MAP value above which fuel is cut in case of overboost.\nSet to 0 to disable overboost cut.;"kPa (absolute)", 1, 0, 0, 500, 0
|
||||||
|
|
||||||
float[16] unusedMapAccelTaperBins;;"counter", 1, 0, 0, 300, 0
|
uint8_t[16] tchargeBins;;"kg/h", 5, 0, 0, 1200, 0
|
||||||
|
uint8_t[16] tchargeValues;;"ratio", 0.01, 0, 0, 1, 2
|
||||||
|
|
||||||
|
float[8] unusedMapAccelTaperBins;;"counter", 1, 0, 0, 300, 0
|
||||||
|
|
||||||
float fixedTiming;Fixed timing, useful for TDC testing;"deg", 1, 0, -720, 720, 2
|
float fixedTiming;Fixed timing, useful for TDC testing;"deg", 1, 0, -720, 720, 2
|
||||||
float mapLowValueVoltage;MAP voltage for low point;"v", 1, 0, 0, 10, 2
|
float mapLowValueVoltage;MAP voltage for low point;"v", 1, 0, 0, 10, 2
|
||||||
|
@ -1388,8 +1391,8 @@ float tChargeAirFlowMax;High flow point for heat transfer estimation.\nSet this
|
||||||
float tChargeAirIncrLimit;Maximum allowed rate of increase allowed for the estimated charge temperature;"deg/sec", 1, 0, 0, 100, 1
|
float tChargeAirIncrLimit;Maximum allowed rate of increase allowed for the estimated charge temperature;"deg/sec", 1, 0, 0, 100, 1
|
||||||
float tChargeAirDecrLimit;Maximum allowed rate of decrease allowed for the estimated charge temperature;"deg/sec", 1, 0, 0, 100, 1
|
float tChargeAirDecrLimit;Maximum allowed rate of decrease allowed for the estimated charge temperature;"deg/sec", 1, 0, 0, 100, 1
|
||||||
|
|
||||||
#define tChargeMode_e_enum "RPM+TPS (Default)", "Air Mass Interpolation"
|
#define tChargeMode_e_enum "RPM+TPS (Default)", "Air Mass Interpolation", "Table"
|
||||||
custom tChargeMode_e 4 bits, U32, @OFFSET@, [0:0], @@tChargeMode_e_enum@@
|
custom tChargeMode_e 4 bits, U32, @OFFSET@, [0:1], @@tChargeMode_e_enum@@
|
||||||
tChargeMode_e tChargeMode;
|
tChargeMode_e tChargeMode;
|
||||||
|
|
||||||
float[ETB_BIAS_CURVE_LENGTH] etbBiasBins;target TPS value, 0 to 100%\nTODO: use int8 data date once we template interpolation method;"target TPS position", 1, 0, 0, 100, 0
|
float[ETB_BIAS_CURVE_LENGTH] etbBiasBins;target TPS value, 0 to 100%\nTODO: use int8 data date once we template interpolation method;"target TPS position", 1, 0, 0, 100, 0
|
||||||
|
|
|
@ -644,6 +644,14 @@ enable2ndByteCanID = false
|
||||||
yBins = wwBetaMapValues
|
yBins = wwBetaMapValues
|
||||||
gauge = MAPGauge
|
gauge = MAPGauge
|
||||||
|
|
||||||
|
curve = tchargeCurve, "Charge temperature estimation coefficient"
|
||||||
|
columnLabel = "flow", "coefficient"
|
||||||
|
xAxis = 0, 500, 6
|
||||||
|
yAxis = 0, 100, 5
|
||||||
|
xBins = tchargeBins, mafEstimate
|
||||||
|
yBins = tchargeValues
|
||||||
|
gauge = tChargeGauge
|
||||||
|
|
||||||
[TableEditor]
|
[TableEditor]
|
||||||
; table_id, map3d_id, "title", page
|
; table_id, map3d_id, "title", page
|
||||||
|
|
||||||
|
@ -1829,6 +1837,7 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00"
|
||||||
panel = tChargeGeneralSettings
|
panel = tChargeGeneralSettings
|
||||||
panel = tChargeRpmTpsSettings, { tChargeMode == 0}
|
panel = tChargeRpmTpsSettings, { tChargeMode == 0}
|
||||||
panel = tChargeAirInterpSettings, { tChargeMode == 1}
|
panel = tChargeAirInterpSettings, { tChargeMode == 1}
|
||||||
|
panel = tchargeCurve, { tChargeMode == 2 }
|
||||||
|
|
||||||
dialog = baseInjection, "General"
|
dialog = baseInjection, "General"
|
||||||
field = "Enabled", isInjectionEnabled
|
field = "Enabled", isInjectionEnabled
|
||||||
|
|
Loading…
Reference in New Issue