rusefi-1/firmware/controllers/algo/fuel_math.cpp

173 lines
6.4 KiB
C++
Raw Normal View History

2014-08-29 07:52:33 -07:00
/**
* @file fuel_math.cpp
* @brief Fuel amount calculation logic
*
* While engine running, fuel amount is an interpolated value from the fuel map by getRpm() and getEngineLoad()
* On top of the value from the fuel map we also apply
* <BR>1) getInjectorLag() correction to account for fuel injector lag
* <BR>2) getCltCorrection() for warm-up
* <BR>3) getIatCorrection() to account for cold weather
*
* getCrankingFuel() depents only on getCoolantTemperature()
*
*
* @date May 27, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*
* This file is part of rusEfi - see http://rusefi.com
*
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "main.h"
#include "fuel_math.h"
#include "interpolation.h"
#include "engine_configuration.h"
#include "allsensors.h"
#include "engine_math.h"
#include "rpm_calculator.h"
#include "speed_density.h"
#if EFI_ACCEL_ENRICHMENT
#include "accel_enrichment.h"
#endif /* EFI_ACCEL_ENRICHMENT */
float getBaseFuel(Engine *engine, int rpm) {
if (engine->engineConfiguration->algorithm == LM_SPEED_DENSITY) {
return getSpeedDensityFuel(engine, rpm);
} else {
float engineLoad = getEngineLoadT(engine);
2014-10-02 11:03:28 -07:00
return getBaseTableFuel(engine->engineConfiguration, rpm, engineLoad);
2014-08-29 07:52:33 -07:00
}
}
2014-09-06 17:02:54 -07:00
/**
* Number of injections into each cylinder per engine cycle
*/
static int getNumberOfInjections(engine_configuration_s const *engineConfiguration, injection_mode_e mode) {
switch (mode) {
case IM_SIMULTANEOUS:
return engineConfiguration->cylindersCount;
case IM_SEQUENTIAL:
return 1;
case IM_BATCH:
return engineConfiguration->cylindersCount / 2;
default:
firmwareError("Unexpected getFuelMultiplier %d", mode);
return 1;
}
}
2014-08-29 07:52:33 -07:00
/**
* @returns Length of fuel injection, in milliseconds
*/
float getFuelMs(int rpm, Engine *engine) {
2014-10-02 12:02:57 -07:00
engine_configuration_s *engineConfiguration = engine->engineConfiguration;
float theoreticalInjectionLength;
2014-10-02 20:03:25 -07:00
if (isCrankingR(rpm)) {
2014-10-02 12:02:57 -07:00
theoreticalInjectionLength = getCrankingFuel(engine) / getNumberOfInjections(engineConfiguration, engineConfiguration->crankingInjectionMode);
2014-08-29 07:52:33 -07:00
} else {
float baseFuel = getBaseFuel(engine, rpm);
2014-09-06 17:02:54 -07:00
float fuelPerCycle = getRunningFuel(baseFuel, engine, rpm);
2014-10-02 12:02:57 -07:00
theoreticalInjectionLength = fuelPerCycle / getNumberOfInjections(engineConfiguration, engine->engineConfiguration->injectionMode);
2014-08-29 07:52:33 -07:00
}
2014-10-02 12:02:57 -07:00
float injectorLag = getInjectorLag(engineConfiguration, getVBatt());
return theoreticalInjectionLength + injectorLag;
2014-08-29 07:52:33 -07:00
}
2014-10-13 13:02:58 -07:00
float getRunningFuel(float baseFuelMs, Engine *engine, int rpm) {
2014-10-02 11:03:28 -07:00
engine_configuration_s *engineConfiguration = engine->engineConfiguration;
float iatCorrection = getIatCorrection(engineConfiguration, getIntakeAirTemperature(engine->engineConfiguration2));
float cltCorrection = getCltCorrection(engineConfiguration, getCoolantTemperature(engine->engineConfiguration2));
2014-08-29 07:52:33 -07:00
#if EFI_ACCEL_ENRICHMENT
float accelEnrichment = getAccelEnrichment();
// todo: accelEnrichment
#endif /* EFI_ACCEL_ENRICHMENT */
2014-10-13 13:02:58 -07:00
return baseFuelMs * cltCorrection * iatCorrection;
2014-08-29 07:52:33 -07:00
}
static Map3D1616 fuelMap;
/**
* @brief Injector lag correction
* @param vBatt Battery voltage.
* @return Time in ms for injection opening time based on current battery voltage
*/
2014-10-02 11:03:28 -07:00
float getInjectorLag(engine_configuration_s *engineConfiguration, float vBatt) {
2014-08-29 07:52:33 -07:00
if (cisnan(vBatt)) {
warning(OBD_System_Voltage_Malfunction, "vBatt=%f", vBatt);
return 0;
}
float vBattCorrection = interpolate2d(vBatt, engineConfiguration->battInjectorLagCorrBins,
engineConfiguration->battInjectorLagCorr, VBAT_INJECTOR_CURVE_SIZE);
return engineConfiguration->injectorLag + vBattCorrection;
}
/**
* @brief Initialize fuel map data structure
* @note this method has nothing to do with fuel map VALUES - it's job
* is to prepare the fuel map data structure for 3d interpolation
*/
2014-10-02 11:03:28 -07:00
void prepareFuelMap(engine_configuration_s *engineConfiguration) {
2014-08-29 07:52:33 -07:00
fuelMap.init(engineConfiguration->fuelTable);
}
/**
* @brief Engine warm-up fuel correction.
*/
2014-10-02 11:03:28 -07:00
float getCltCorrection(engine_configuration_s *engineConfiguration, float clt) {
2014-08-29 07:52:33 -07:00
if (cisnan(clt))
return 1; // this error should be already reported somewhere else, let's just handle it
return interpolate2d(clt, engineConfiguration->cltFuelCorrBins, engineConfiguration->cltFuelCorr, CLT_CURVE_SIZE);
}
2014-10-02 11:03:28 -07:00
float getIatCorrection(engine_configuration_s *engineConfiguration, float iat) {
2014-08-29 07:52:33 -07:00
if (cisnan(iat))
return 1; // this error should be already reported somewhere else, let's just handle it
return interpolate2d(iat, engineConfiguration->iatFuelCorrBins, engineConfiguration->iatFuelCorr, IAT_CURVE_SIZE);
}
2014-09-06 15:02:55 -07:00
/**
* @return Fuel injection duration injection as specified in the fuel map, in milliseconds
*/
2014-10-02 11:03:28 -07:00
float getBaseTableFuel(engine_configuration_s *engineConfiguration, int rpm, float engineLoad) {
2014-09-13 13:04:13 -07:00
if (cisnan(engineLoad)) {
warning(OBD_PCM_Processor_Fault, "NaN engine load");
return NAN;
}
2014-08-29 07:52:33 -07:00
return fuelMap.getValue(engineLoad, engineConfiguration->fuelLoadBins, rpm,
engineConfiguration->fuelRpmBins);
}
2014-09-06 15:02:55 -07:00
/**
* @return Duration of fuel injection while craning, in milliseconds
*/
2014-10-02 10:03:00 -07:00
float getCrankingFuel(Engine *engine) {
2014-10-02 11:03:28 -07:00
return getStartingFuel(engine->engineConfiguration,
getCoolantTemperature(engine->engineConfiguration2));
2014-08-29 07:52:33 -07:00
}
2014-10-02 11:03:28 -07:00
float getStartingFuel(engine_configuration_s *engineConfiguration, float coolantTemperature) {
2014-08-29 07:52:33 -07:00
// these magic constants are in Celsius
if (cisnan(coolantTemperature) || coolantTemperature < engineConfiguration->crankingSettings.coolantTempMinC)
return engineConfiguration->crankingSettings.fuelAtMinTempMs;
if (coolantTemperature > engineConfiguration->crankingSettings.coolantTempMaxC)
return engineConfiguration->crankingSettings.fuelAtMaxTempMs;
return interpolate(engineConfiguration->crankingSettings.coolantTempMinC,
engineConfiguration->crankingSettings.fuelAtMinTempMs,
engineConfiguration->crankingSettings.coolantTempMaxC,
engineConfiguration->crankingSettings.fuelAtMaxTempMs, coolantTemperature);
}