2019-01-04 21:32:56 -08:00
|
|
|
/*
|
|
|
|
* engine2.cpp
|
|
|
|
*
|
|
|
|
* @date Jan 5, 2019
|
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2019
|
|
|
|
*/
|
|
|
|
|
|
|
|
// todo: move this code to more proper locations
|
|
|
|
|
|
|
|
#include "engine.h"
|
|
|
|
#include "thermistors.h"
|
|
|
|
#include "speed_density.h"
|
|
|
|
#include "allsensors.h"
|
|
|
|
#include "fuel_math.h"
|
|
|
|
#include "engine_math.h"
|
|
|
|
#include "advance_map.h"
|
|
|
|
#include "aux_valves.h"
|
2019-01-11 16:08:15 -08:00
|
|
|
#if EFI_PROD_CODE
|
|
|
|
#include "svnversion.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if ! EFI_UNIT_TEST
|
|
|
|
#include "status_loop.h"
|
|
|
|
#endif
|
2019-01-04 21:32:56 -08:00
|
|
|
|
|
|
|
extern fuel_Map3D_t veMap;
|
|
|
|
extern afr_Map3D_t afrMap;
|
|
|
|
|
|
|
|
EXTERN_ENGINE
|
|
|
|
;
|
|
|
|
|
|
|
|
// this does not look exactly right
|
|
|
|
extern LoggingWithStorage engineLogger;
|
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_TUNER_STUDIO
|
2019-01-04 21:32:56 -08:00
|
|
|
extern TunerStudioOutputChannels tsOutputChannels;
|
|
|
|
#endif /* EFI_TUNER_STUDIO */
|
|
|
|
|
2019-01-11 06:58:48 -08:00
|
|
|
WarningCodeState::WarningCodeState() {
|
2019-01-12 05:34:38 -08:00
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void WarningCodeState::clear() {
|
2019-01-11 06:58:48 -08:00
|
|
|
warningCounter = 0;
|
|
|
|
lastErrorCode = 0;
|
|
|
|
timeOfPreviousWarning = -10;
|
2019-01-12 18:36:50 -08:00
|
|
|
recentWarnings.clear();
|
2019-01-11 06:58:48 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void WarningCodeState::addWarningCode(obd_code_e code) {
|
|
|
|
warningCounter++;
|
|
|
|
lastErrorCode = code;
|
2019-01-12 18:36:50 -08:00
|
|
|
if (!recentWarnings.contains(code)) {
|
|
|
|
recentWarnings.add((int)code);
|
2019-01-12 11:19:21 -08:00
|
|
|
}
|
2019-01-11 06:58:48 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param forIndicator if we want to retrieving value for TS indicator, this case a minimal period is applued
|
|
|
|
*/
|
2019-01-15 17:24:36 -08:00
|
|
|
bool WarningCodeState::isWarningNow(efitimesec_t now, bool forIndicator DECLARE_ENGINE_PARAMETER_SUFFIX) const {
|
2019-01-11 06:58:48 -08:00
|
|
|
int period = forIndicator ? maxI(3, engineConfiguration->warningPeriod) : engineConfiguration->warningPeriod;
|
|
|
|
return absI(now - timeOfPreviousWarning) < period;
|
|
|
|
}
|
2019-01-04 21:32:56 -08:00
|
|
|
|
|
|
|
MockAdcState::MockAdcState() {
|
|
|
|
memset(hasMockAdc, 0, sizeof(hasMockAdc));
|
|
|
|
}
|
|
|
|
|
|
|
|
#if EFI_ENABLE_MOCK_ADC || EFI_SIMULATOR
|
|
|
|
void MockAdcState::setMockVoltage(int hwChannel, float voltage) {
|
|
|
|
scheduleMsg(&engineLogger, "fake voltage: channel %d value %.2f", hwChannel, voltage);
|
|
|
|
|
|
|
|
fakeAdcValues[hwChannel] = voltsToAdc(voltage);
|
|
|
|
hasMockAdc[hwChannel] = true;
|
|
|
|
}
|
|
|
|
#endif /* EFI_ENABLE_MOCK_ADC */
|
|
|
|
|
|
|
|
FuelConsumptionState::FuelConsumptionState() {
|
|
|
|
accumulatedSecondPrevNt = accumulatedMinutePrevNt = getTimeNowNt();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FuelConsumptionState::addData(float durationMs) {
|
|
|
|
if (durationMs > 0.0f) {
|
|
|
|
perSecondAccumulator += durationMs;
|
|
|
|
perMinuteAccumulator += durationMs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FuelConsumptionState::update(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
|
|
|
efitick_t deltaNt = nowNt - accumulatedSecondPrevNt;
|
|
|
|
if (deltaNt >= US2NT(US_PER_SECOND_LL)) {
|
|
|
|
perSecondConsumption = getFuelRate(perSecondAccumulator, deltaNt PASS_ENGINE_PARAMETER_SUFFIX);
|
|
|
|
perSecondAccumulator = 0;
|
|
|
|
accumulatedSecondPrevNt = nowNt;
|
|
|
|
}
|
|
|
|
|
|
|
|
deltaNt = nowNt - accumulatedMinutePrevNt;
|
|
|
|
if (deltaNt >= US2NT(US_PER_SECOND_LL * 60)) {
|
|
|
|
perMinuteConsumption = getFuelRate(perMinuteAccumulator, deltaNt PASS_ENGINE_PARAMETER_SUFFIX);
|
|
|
|
perMinuteAccumulator = 0;
|
|
|
|
accumulatedMinutePrevNt = nowNt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TransmissionState::TransmissionState() {
|
|
|
|
}
|
|
|
|
|
|
|
|
EngineState::EngineState() {
|
|
|
|
timeSinceLastTChargeK = getTimeNowNt();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EngineState::updateSlowSensors(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|
|
|
engine->sensors.iat = getIntakeAirTemperature(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
engine->sensors.clt = getCoolantTemperature(PASS_ENGINE_PARAMETER_SIGNATURE);
|
2019-05-09 16:39:21 -07:00
|
|
|
|
|
|
|
// todo: reduce code duplication with 'getCoolantTemperature'
|
|
|
|
if (engineConfiguration->auxTempSensor1.adcChannel != EFI_ADC_NONE) {
|
|
|
|
engine->sensors.auxTemp1 = getTemperatureC(&engineConfiguration->auxTempSensor1,
|
|
|
|
&engine->engineState.auxTemp1Curve,
|
|
|
|
false);
|
|
|
|
}
|
|
|
|
if (engineConfiguration->auxTempSensor2.adcChannel != EFI_ADC_NONE) {
|
|
|
|
engine->sensors.auxTemp2 = getTemperatureC(&engineConfiguration->auxTempSensor2,
|
|
|
|
&engine->engineState.auxTemp2Curve,
|
|
|
|
false);
|
|
|
|
}
|
|
|
|
|
2019-01-19 19:09:37 -08:00
|
|
|
#if EFI_UNIT_TEST
|
|
|
|
if (!cisnan(engine->sensors.mockClt)) {
|
|
|
|
engine->sensors.clt = engine->sensors.mockClt;
|
|
|
|
}
|
|
|
|
#endif
|
2019-01-04 21:32:56 -08:00
|
|
|
engine->sensors.oilPressure = getOilPressure(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
|
|
|
|
warmupTargetAfr = interpolate2d("warm", engine->sensors.clt, engineConfiguration->warmupTargetAfrBins,
|
|
|
|
engineConfiguration->warmupTargetAfr, WARMUP_TARGET_AFR_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EngineState::periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_ENGINE_CONTROL
|
2019-01-14 05:57:08 -08:00
|
|
|
if (!engine->slowCallBackWasInvoked) {
|
2019-01-14 08:30:41 -08:00
|
|
|
warning(CUSTOM_ERR_6696, "Slow not invoked yet");
|
2019-01-14 05:57:08 -08:00
|
|
|
}
|
2019-01-04 21:32:56 -08:00
|
|
|
efitick_t nowNt = getTimeNowNt();
|
|
|
|
if (ENGINE(rpmCalculator).isCranking(PASS_ENGINE_PARAMETER_SIGNATURE)) {
|
|
|
|
crankingTime = nowNt;
|
|
|
|
timeSinceCranking = 0.0f;
|
|
|
|
} else {
|
|
|
|
timeSinceCranking = nowNt - crankingTime;
|
|
|
|
}
|
|
|
|
updateAuxValves(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
|
|
|
|
int rpm = ENGINE(rpmCalculator).getRpm(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
sparkDwell = getSparkDwell(rpm PASS_ENGINE_PARAMETER_SUFFIX);
|
|
|
|
dwellAngle = cisnan(rpm) ? NAN : sparkDwell / getOneDegreeTimeMs(rpm);
|
|
|
|
if (hasAfrSensor(PASS_ENGINE_PARAMETER_SIGNATURE)) {
|
|
|
|
engine->sensors.currentAfr = getAfr(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// todo: move this into slow callback, no reason for IAT corr to be here
|
|
|
|
iatFuelCorrection = getIatFuelCorrection(engine->sensors.iat PASS_ENGINE_PARAMETER_SUFFIX);
|
|
|
|
// todo: move this into slow callback, no reason for CLT corr to be here
|
2019-01-09 18:31:59 -08:00
|
|
|
if (CONFIGB(useWarmupPidAfr) && engine->sensors.clt < engineConfiguration->warmupAfrThreshold) {
|
2019-01-04 21:32:56 -08:00
|
|
|
if (rpm < 200) {
|
|
|
|
cltFuelCorrection = 1;
|
|
|
|
warmupAfrPid.reset();
|
|
|
|
} else {
|
2019-04-25 18:31:33 -07:00
|
|
|
cltFuelCorrection = warmupAfrPid.getOutput(warmupTargetAfr, engine->sensors.currentAfr, MS2SEC(FAST_CALLBACK_PERIOD_MS));
|
2019-01-04 21:32:56 -08:00
|
|
|
}
|
|
|
|
if (engineConfiguration->debugMode == DBG_WARMUP_ENRICH) {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_TUNER_STUDIO
|
2019-01-04 21:32:56 -08:00
|
|
|
tsOutputChannels.debugFloatField1 = warmupTargetAfr;
|
|
|
|
warmupAfrPid.postState(&tsOutputChannels);
|
|
|
|
#endif /* EFI_TUNER_STUDIO */
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cltFuelCorrection = getCltFuelCorrection(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// update fuel consumption states
|
|
|
|
fuelConsumption.update(nowNt PASS_ENGINE_PARAMETER_SUFFIX);
|
|
|
|
|
|
|
|
// Fuel cut-off isn't just 0 or 1, it can be tapered
|
|
|
|
fuelCutoffCorrection = getFuelCutOffCorrection(nowNt, rpm PASS_ENGINE_PARAMETER_SUFFIX);
|
|
|
|
|
|
|
|
// post-cranking fuel enrichment.
|
|
|
|
// for compatibility reasons, apply only if the factor is greater than zero (0.01 margin used)
|
|
|
|
if (engineConfiguration->postCrankingFactor > 0.01f) {
|
|
|
|
// convert to microsecs and then to seconds
|
|
|
|
float timeSinceCrankingInSecs = NT2US(timeSinceCranking) / 1000000.0f;
|
|
|
|
// use interpolation for correction taper
|
|
|
|
postCrankingFuelCorrection = interpolateClamped(0.0f, engineConfiguration->postCrankingFactor,
|
|
|
|
engineConfiguration->postCrankingDurationSec, 1.0f, timeSinceCrankingInSecs);
|
|
|
|
} else {
|
|
|
|
postCrankingFuelCorrection = 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
cltTimingCorrection = getCltTimingCorrection(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
|
|
|
|
engineNoiseHipLevel = interpolate2d("knock", rpm, engineConfiguration->knockNoiseRpmBins,
|
|
|
|
engineConfiguration->knockNoise, ENGINE_NOISE_CURVE_SIZE);
|
|
|
|
|
|
|
|
baroCorrection = getBaroCorrection(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
|
|
|
|
injectionOffset = getInjectionOffset(rpm PASS_ENGINE_PARAMETER_SUFFIX);
|
|
|
|
float engineLoad = getEngineLoadT(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
timingAdvance = getAdvance(rpm, engineLoad PASS_ENGINE_PARAMETER_SUFFIX);
|
|
|
|
|
|
|
|
if (engineConfiguration->fuelAlgorithm == LM_SPEED_DENSITY) {
|
|
|
|
float tps = getTPS(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
updateTChargeK(rpm, tps PASS_ENGINE_PARAMETER_SUFFIX);
|
|
|
|
float map = getMap();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* *0.01 because of https://sourceforge.net/p/rusefi/tickets/153/
|
|
|
|
*/
|
2019-03-22 19:55:51 -07:00
|
|
|
float rawVe = veMap.getValue(rpm, CONFIGB(useTPSBasedVeTable) ? tps : map);
|
2019-01-04 21:32:56 -08:00
|
|
|
// get VE from the separate table for Idle
|
|
|
|
if (CONFIG(useSeparateVeForIdle)) {
|
|
|
|
float idleVe = interpolate2d("idleVe", rpm, config->idleVeBins, config->idleVe, IDLE_VE_CURVE_SIZE);
|
|
|
|
// interpolate between idle table and normal (running) table using TPS threshold
|
2019-01-09 18:31:59 -08:00
|
|
|
rawVe = interpolateClamped(0.0f, idleVe, CONFIGB(idlePidDeactivationTpsThreshold), rawVe, tps);
|
2019-01-04 21:32:56 -08:00
|
|
|
}
|
|
|
|
currentVE = baroCorrection * rawVe * 0.01;
|
|
|
|
targetAFR = afrMap.getValue(rpm, map);
|
|
|
|
} else {
|
|
|
|
baseTableFuel = getBaseTableFuel(rpm, engineLoad);
|
|
|
|
}
|
2019-01-31 08:57:15 -08:00
|
|
|
#endif
|
2019-01-04 21:32:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void EngineState::updateTChargeK(int rpm, float tps DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_ENGINE_CONTROL
|
2019-01-04 21:32:56 -08:00
|
|
|
float coolantC = ENGINE(sensors.clt);
|
|
|
|
float intakeC = ENGINE(sensors.iat);
|
|
|
|
float newTCharge = getTCharge(rpm, tps, coolantC, intakeC PASS_ENGINE_PARAMETER_SUFFIX);
|
|
|
|
// convert to microsecs and then to seconds
|
|
|
|
efitick_t curTime = getTimeNowNt();
|
|
|
|
float secsPassed = (float)NT2US(curTime - timeSinceLastTChargeK) / 1000000.0f;
|
|
|
|
if (!cisnan(newTCharge)) {
|
|
|
|
// control the rate of change or just fill with the initial value
|
|
|
|
tCharge = (tChargeK == 0) ? newTCharge : limitRateOfChange(newTCharge, tCharge, CONFIG(tChargeAirIncrLimit), CONFIG(tChargeAirDecrLimit), secsPassed);
|
|
|
|
tChargeK = convertCelsiusToKelvin(tCharge);
|
|
|
|
timeSinceLastTChargeK = curTime;
|
|
|
|
}
|
2019-01-31 08:57:15 -08:00
|
|
|
#endif
|
2019-01-04 21:32:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
SensorsState::SensorsState() {
|
|
|
|
}
|
|
|
|
|
2019-01-15 17:24:36 -08:00
|
|
|
int MockAdcState::getMockAdcValue(int hwChannel) const {
|
2019-01-04 21:32:56 -08:00
|
|
|
return fakeAdcValues[hwChannel];
|
|
|
|
}
|
|
|
|
|
|
|
|
StartupFuelPumping::StartupFuelPumping() {
|
|
|
|
isTpsAbove50 = false;
|
|
|
|
pumpsCounter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StartupFuelPumping::setPumpsCounter(int newValue) {
|
|
|
|
if (pumpsCounter != newValue) {
|
|
|
|
pumpsCounter = newValue;
|
|
|
|
|
|
|
|
if (pumpsCounter == PUMPS_TO_PRIME) {
|
|
|
|
scheduleMsg(&engineLogger, "let's squirt prime pulse %.2f", pumpsCounter);
|
|
|
|
pumpsCounter = 0;
|
|
|
|
} else {
|
|
|
|
scheduleMsg(&engineLogger, "setPumpsCounter %d", pumpsCounter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StartupFuelPumping::update(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2019-01-21 18:48:58 -08:00
|
|
|
if (GET_RPM() == 0) {
|
2019-01-04 21:32:56 -08:00
|
|
|
bool isTpsAbove50 = getTPS(PASS_ENGINE_PARAMETER_SIGNATURE) >= 50;
|
|
|
|
|
|
|
|
if (this->isTpsAbove50 != isTpsAbove50) {
|
|
|
|
setPumpsCounter(pumpsCounter + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/**
|
|
|
|
* Engine is not stopped - not priming pumping mode
|
|
|
|
*/
|
|
|
|
setPumpsCounter(0);
|
|
|
|
isTpsAbove50 = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-11 16:08:15 -08:00
|
|
|
#if EFI_SIMULATOR
|
|
|
|
#define VCS_VERSION "123"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void printCurrentState(Logging *logging, int seconds, const char *name) {
|
|
|
|
logging->appendPrintf("%s%s%d@%s %s %d%s", RUS_EFI_VERSION_TAG, DELIMETER,
|
|
|
|
getRusEfiVersion(), VCS_VERSION,
|
|
|
|
name,
|
|
|
|
seconds,
|
|
|
|
DELIMETER);
|
|
|
|
}
|
2019-01-04 21:32:56 -08:00
|
|
|
|