rusefi-1/firmware/controllers/math/speed_density.cpp

142 lines
5.1 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file speed_density.cpp
*
* See http://rusefi.com/wiki/index.php?title=Manual:Software:Fuel_Control#Speed_Density for details
*
* @date May 29, 2014
2020-01-13 18:57:43 -08:00
* @author Andrey Belomutskiy, (c) 2012-2020
2015-07-10 06:01:56 -07:00
*/
2018-09-16 19:26:57 -07:00
#include "global.h"
2015-07-10 06:01:56 -07:00
#include "speed_density.h"
2020-06-03 18:12:12 -07:00
#include "fuel_math.h"
2015-07-10 06:01:56 -07:00
#include "interpolation.h"
2019-01-27 22:25:23 -08:00
#include "engine.h"
2015-07-10 06:01:56 -07:00
#include "engine_math.h"
2019-10-13 13:14:08 -07:00
#include "perf_trace.h"
#include "sensor.h"
2020-07-22 13:11:07 -07:00
#include "map.h"
2015-07-10 06:01:56 -07:00
#if defined(HAS_OS_ACCESS)
#error "Unexpected OS ACCESS HERE"
#endif
2015-07-10 06:01:56 -07:00
#define rpmMin 500
#define rpmMax 8000
2016-10-11 18:03:00 -07:00
EXTERN_ENGINE;
2015-12-27 09:01:53 -08:00
fuel_Map3D_t veMap("VE");
fuel_Map3D_t ve2Map("VE2");
2016-07-01 20:01:22 -07:00
afr_Map3D_t afrMap("AFR", 1.0 / AFR_STORAGE_MULT);
2015-12-27 09:01:53 -08:00
baroCorr_Map3D_t baroCorrMap("baro");
2015-07-10 06:01:56 -07:00
#define tpMin 0
#define tpMax 100
// http://rusefi.com/math/t_charge.html
/***panel:Charge Temperature*/
temperature_t getTCharge(int rpm, float tps DECLARE_ENGINE_PARAMETER_SUFFIX) {
2020-04-19 12:02:40 -07:00
const auto clt = Sensor::get(SensorType::Clt);
const auto iat = Sensor::get(SensorType::Iat);
float airTemp = 0;
// Without either valid, return 0C. It's wrong, but it'll pretend to be nice and dense, so at least you won't go lean.
if (!iat && !clt) {
return 0;
} else if (!clt && iat) {
// Intake temperature will almost always be colder (richer) than CLT - use that
return airTemp;
2020-04-19 12:02:40 -07:00
} else if (!iat && clt) {
// Without valid intake temperature, assume intake temp is 0C, and interpolate anyway
airTemp = 0;
} else {
// All is well - use real air temp
airTemp = iat.Value;
2017-11-19 18:30:59 -08:00
}
2015-07-10 06:01:56 -07:00
2020-04-19 12:02:40 -07:00
float coolantTemp = clt.Value;
2019-09-01 10:56:46 -07:00
DISPLAY_STATE(Engine)
if ((engine->engineState.sd.DISPLAY_IF(isTChargeAirModel) = (CONFIG(tChargeMode) == TCHARGE_MODE_AIR_INTERP))) {
const 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./***display*/airMassInOneCylinder * CONFIG(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 PASS_ENGINE_PARAMETER_SUFFIX);
// just interpolate between user-specified min and max coefs, based on the max airFlow value
DISPLAY_TEXT(interpolate_Air_Flow)
engine->engineState.DISPLAY_FIELD(airFlow) = airFlow;
DISPLAY_TEXT(Between)
engine->engineState.sd.Tcharge_coff = interpolateClamped(0.0,
CONFIG(DISPLAY_CONFIG(tChargeAirCoefMin)),
CONFIG(DISPLAY_CONFIG(tChargeAirFlowMax)),
CONFIG(DISPLAY_CONFIG(tChargeAirCoefMax)), airFlow);
// save it for console output (instead of MAF massAirFlow)
} else/* DISPLAY_ELSE */ {
// TCHARGE_MODE_RPM_TPS
DISPLAY_TEXT(interpolate_3D)
DISPLAY_SENSOR(RPM)
DISPLAY_TEXT(and)
DISPLAY_SENSOR(TPS)
DISPLAY_TEXT(EOL)
DISPLAY_TEXT(Between)
float minRpmKcurrentTPS = interpolateMsg("minRpm", tpMin,
CONFIG(DISPLAY_CONFIG(tChargeMinRpmMinTps)), tpMax,
CONFIG(DISPLAY_CONFIG(tChargeMinRpmMaxTps)), tps);
DISPLAY_TEXT(EOL)
float maxRpmKcurrentTPS = interpolateMsg("maxRpm", tpMin,
CONFIG(DISPLAY_CONFIG(tChargeMaxRpmMinTps)), tpMax,
CONFIG(DISPLAY_CONFIG(tChargeMaxRpmMaxTps)), tps);
engine->engineState.sd.Tcharge_coff = interpolateMsg("Kcurr", rpmMin, minRpmKcurrentTPS, rpmMax, maxRpmKcurrentTPS, rpm);
/* DISPLAY_ENDIF */
}
if (cisnan(engine->engineState.sd.Tcharge_coff)) {
2018-09-10 19:00:13 -07:00
warning(CUSTOM_ERR_T2_CHARGE, "t2-getTCharge NaN");
2017-11-19 18:30:59 -08:00
return coolantTemp;
}
2015-07-10 06:01:56 -07:00
// We use a robust interp. function for proper tcharge_coff clamping.
float Tcharge = interpolateClamped(0.0f, coolantTemp, 1.0f, airTemp, engine->engineState.sd.Tcharge_coff);
2015-07-10 06:01:56 -07:00
2017-04-12 20:48:35 -07:00
if (cisnan(Tcharge)) {
// we can probably end up here while resetting engine state - interpolation would fail
2017-04-13 07:43:27 -07:00
warning(CUSTOM_ERR_TCHARGE_NOT_READY, "getTCharge NaN");
2017-04-12 20:48:35 -07:00
return coolantTemp;
}
2015-07-10 06:01:56 -07:00
return Tcharge;
}
2017-05-15 20:33:22 -07:00
void setDefaultVETable(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
2015-07-10 06:01:56 -07:00
setRpmTableBin(config->veRpmBins, FUEL_RPM_COUNT);
veMap.setAll(80);
// setRpmTableBin(engineConfiguration->ve2RpmBins, FUEL_RPM_COUNT);
// setLinearCurve(engineConfiguration->ve2LoadBins, 10, 300, 1);
2015-07-10 06:01:56 -07:00
// ve2Map.setAll(0.81);
setRpmTableBin(config->afrRpmBins, FUEL_RPM_COUNT);
afrMap.setAll(14.7);
setRpmTableBin(engineConfiguration->baroCorrRpmBins, BARO_CORR_SIZE);
setLinearCurve(engineConfiguration->baroCorrPressureBins, 75, 105, 1);
for (int i = 0; i < BARO_CORR_SIZE;i++) {
for (int j = 0; j < BARO_CORR_SIZE;j++) {
// Default baro table is all 1.0, we can't recommend a reasonable default here
engineConfiguration->baroCorrTable[i][j] = 1;
}
}
2015-07-10 06:01:56 -07:00
}
2017-05-15 20:33:22 -07:00
void initSpeedDensity(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
2015-07-10 06:01:56 -07:00
veMap.init(config->veTable, config->veLoadBins, config->veRpmBins);
// ve2Map.init(engineConfiguration->ve2Table, engineConfiguration->ve2LoadBins, engineConfiguration->ve2RpmBins);
afrMap.init(config->afrTable, config->afrLoadBins, config->afrRpmBins);
baroCorrMap.init(engineConfiguration->baroCorrTable, engineConfiguration->baroCorrPressureBins, engineConfiguration->baroCorrRpmBins);
}