rusefi/firmware/controllers/algo/accel_enrichment.cpp

248 lines
7.0 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file accel_enrichment.cpp
* @brief Acceleration enrichment calculator
*
2015-08-21 12:01:36 -07:00
* In this file we have three strategies for acceleration/deceleration fuel correction
*
* 1) MAP rate-of-change correction
* 2) TPS rate-of-change correction
* 3) fuel film/wal wetting correction
* AWC Added to Wall Coefficient, %
* AWA Added to Wall Amount
* SOC Sucked Off wall Coefficient, %
* SOA Sucked Off wall amount
* WF current on-Wall Fuel amount
*
*
* http://rusefi.com/wiki/index.php?title=Manual:Software:Fuel_Control
2015-07-10 06:01:56 -07:00
* @date Apr 21, 2014
* @author Dmitry Sidin
2020-01-13 18:57:43 -08:00
* @author Andrey Belomutskiy, (c) 2012-2020
* @author Matthew Kennedy
2015-07-10 06:01:56 -07:00
*/
#include "pch.h"
2015-07-10 06:01:56 -07:00
#include "accel_enrichment.h"
static tps_tps_Map3D_t tpsTpsMap;
2016-03-11 08:03:18 -08:00
floatms_t TpsAccelEnrichment::getTpsEnrichment() {
2019-10-13 13:14:08 -07:00
ScopePerf perf(PE::GetTpsEnrichment);
if (engineConfiguration->tpsAccelLookback == 0) {
// If disabled, return 0.
return 0;
}
int rpm = Sensor::getOrZero(SensorType::Rpm);
if (rpm == 0) {
return 0;
}
2016-03-11 08:03:18 -08:00
if (isAboveAccelThreshold) {
valueFromTable = tpsTpsMap.getValue(tpsFrom, tpsTo);
2016-09-17 16:02:34 -07:00
extraFuel = valueFromTable;
} else if (isBelowDecelThreshold) {
2019-03-16 08:14:52 -07:00
extraFuel = deltaTps * engineConfiguration->tpsDecelEnleanmentMultiplier;
2016-03-11 11:03:23 -08:00
} else {
2016-03-12 17:03:40 -08:00
extraFuel = 0;
2016-03-11 11:03:23 -08:00
}
// Fractional enrichment (fuel portions are accumulated and split between several engine cycles.
// This is a crude imitation of carburetor's acceleration pump.
isFractionalEnrichment = engineConfiguration->tpsAccelFractionPeriod > 1 || engineConfiguration->tpsAccelFractionDivisor > 1.0f;
if (isFractionalEnrichment) {
// make sure both values are non-zero
float periodF = (float)maxI(engineConfiguration->tpsAccelFractionPeriod, 1);
float divisor = maxF(engineConfiguration->tpsAccelFractionDivisor, 1.0f);
// if current extra fuel portion is not "strong" enough, then we keep up the "pump pressure" with the accumulated portion
floatms_t maxExtraFuel = maxF(extraFuel, accumulatedValue);
// use only a fixed fraction of the accumulated portion
fractionalInjFuel = maxExtraFuel / divisor;
// update max counters
maxExtraPerCycle = maxF(extraFuel, maxExtraPerCycle);
maxInjectedPerPeriod = maxF(fractionalInjFuel, maxInjectedPerPeriod);
// evenly split it between several engine cycles
extraFuel = fractionalInjFuel / periodF;
} else {
resetFractionValues();
}
2019-04-12 19:07:03 -07:00
#if EFI_TUNER_STUDIO
if (engineConfiguration->debugMode == DBG_TPS_ACCEL) {
engine->outputChannels.debugFloatField1 = tpsFrom;
engine->outputChannels.debugFloatField2 = tpsTo;
engine->outputChannels.debugFloatField3 = valueFromTable;
engine->outputChannels.debugFloatField4 = extraFuel;
engine->outputChannels.debugFloatField5 = accumulatedValue;
engine->outputChannels.debugFloatField6 = maxExtraPerPeriod;
engine->outputChannels.debugFloatField7 = maxInjectedPerPeriod;
engine->outputChannels.debugIntField1 = cycleCnt;
2016-03-11 08:03:18 -08:00
}
#endif /* EFI_TUNER_STUDIO */
2016-03-11 11:03:23 -08:00
float mult = interpolate2d(rpm, config->tpsTspCorrValuesBins,
config->tpsTspCorrValues);
if (mult != 0 && (mult < 0.01 || mult > 100)) {
mult = 1;
}
return extraFuel * mult;
2015-07-10 06:01:56 -07:00
}
void TpsAccelEnrichment::onEngineCycleTps() {
// we update values in handleFuel() directly by calling onNewValue()
2019-10-16 19:10:38 -07:00
onUpdateInvocationCounter++;
// we used some extra fuel during the current cycle, so we "charge" our "acceleration pump" with it
accumulatedValue -= maxExtraPerPeriod;
maxExtraPerPeriod = maxF(maxExtraPerCycle, maxExtraPerPeriod);
maxExtraPerCycle = 0;
accumulatedValue += maxExtraPerPeriod;
// update the accumulated value every 'Period' engine cycles
isTimeToResetAccumulator = --cycleCnt <= 0;
if (isTimeToResetAccumulator) {
maxExtraPerPeriod = 0;
// we've injected this portion during the cycle, so we set what's left for the next cycle
accumulatedValue -= maxInjectedPerPeriod;
maxInjectedPerPeriod = 0;
// it's an infinitely convergent series, so we set a limit at some point
// (also make sure that accumulatedValue is positive, for safety)
static const floatms_t smallEpsilon = 0.001f;
belowEpsilon = accumulatedValue < smallEpsilon;
if (belowEpsilon) {
accumulatedValue = 0;
}
// reset the counter
cycleCnt = engineConfiguration->tpsAccelFractionPeriod;
}
2015-07-10 06:01:56 -07:00
}
2021-12-07 15:49:21 -08:00
int TpsAccelEnrichment::getMaxDeltaIndex() {
2021-10-31 09:07:44 -07:00
int len = minI(cb.getSize(), cb.getCount());
2022-01-02 10:57:58 -08:00
tooShort = len < 2;
if (tooShort)
2021-10-31 09:07:44 -07:00
return 0;
int ci = cb.currentIndex - 1;
float maxValue = cb.get(ci) - cb.get(ci - 1);
int resultIndex = ci;
// todo: 'get' method is maybe a bit heavy because of the branching
// todo: this could be optimized with some careful magic
for (int i = 1; i<len - 1;i++) {
float v = cb.get(ci - i) - cb.get(ci - i - 1);
if (v > maxValue) {
maxValue = v;
resultIndex = ci - i;
}
}
return resultIndex;
}
2021-12-07 15:49:21 -08:00
float TpsAccelEnrichment::getMaxDelta() {
int index = getMaxDeltaIndex();
2021-10-31 09:07:44 -07:00
return (cb.get(index) - (cb.get(index - 1)));
}
void TpsAccelEnrichment::resetAE() {
2021-12-07 15:49:21 -08:00
cb.clear();
2021-10-31 09:07:44 -07:00
resetFractionValues();
}
void TpsAccelEnrichment::resetFractionValues() {
accumulatedValue = 0;
maxExtraPerCycle = 0;
maxExtraPerPeriod = 0;
maxInjectedPerPeriod = 0;
cycleCnt = 0;
}
2021-12-07 15:49:21 -08:00
void TpsAccelEnrichment::setLength(int length) {
2021-10-31 09:07:44 -07:00
cb.setSize(length);
}
2021-12-07 15:49:21 -08:00
void TpsAccelEnrichment::onNewValue(float currentValue) {
// Push new value in to the history buffer
2021-10-31 09:07:44 -07:00
cb.add(currentValue);
// Update deltas
int maxDeltaIndex = getMaxDeltaIndex();
tpsFrom = cb.get(maxDeltaIndex - 1);
tpsTo = cb.get(maxDeltaIndex);
deltaTps = tpsTo - tpsFrom;
// Update threshold detection
isAboveAccelThreshold = deltaTps > engineConfiguration->tpsAccelEnrichmentThreshold;
// TODO: can deltaTps actually be negative? Will this ever trigger?
isBelowDecelThreshold = deltaTps < -engineConfiguration->tpsDecelEnleanmentThreshold;
2021-10-31 09:07:44 -07:00
}
2021-12-07 15:49:21 -08:00
TpsAccelEnrichment::TpsAccelEnrichment() {
resetAE();
2015-07-10 06:01:56 -07:00
cb.setSize(4);
}
2019-04-12 19:07:03 -07:00
#if ! EFI_UNIT_TEST
2015-07-10 06:01:56 -07:00
static void accelInfo() {
// efiPrintf("TPS accel length=%d", tpsInstance.cb.getSize());
efiPrintf("TPS accel th=%.2f/mult=%.2f", engineConfiguration->tpsAccelEnrichmentThreshold, -1);
2015-08-23 22:01:28 -07:00
efiPrintf("beta=%.2f/tau=%.2f", engineConfiguration->wwaeBeta, engineConfiguration->wwaeTau);
2015-07-10 06:01:56 -07:00
}
2017-01-06 07:04:41 -08:00
void setTpsAccelThr(float value) {
2015-07-10 06:01:56 -07:00
engineConfiguration->tpsAccelEnrichmentThreshold = value;
accelInfo();
}
2017-01-06 07:04:41 -08:00
void setTpsDecelThr(float value) {
2015-12-31 15:02:17 -08:00
engineConfiguration->tpsDecelEnleanmentThreshold = value;
accelInfo();
}
2017-01-06 07:04:41 -08:00
void setTpsDecelMult(float value) {
2015-12-31 15:02:17 -08:00
engineConfiguration->tpsDecelEnleanmentMultiplier = value;
accelInfo();
}
2017-01-06 07:04:41 -08:00
void setTpsAccelLen(int length) {
2016-03-09 20:02:39 -08:00
if (length < 1) {
2023-07-04 07:19:33 -07:00
efiPrintf("setTpsAccelLen: Length should be positive [%d]", length);
2015-07-10 06:01:56 -07:00
return;
}
2016-03-09 20:02:39 -08:00
engine->tpsAccelEnrichment.setLength(length);
2015-07-10 06:01:56 -07:00
accelInfo();
}
2016-01-31 12:01:41 -08:00
void updateAccelParameters() {
constexpr float slowCallbackPeriodSecond = SLOW_CALLBACK_PERIOD_MS / 1000.0f;
setTpsAccelLen(engineConfiguration->tpsAccelLookback / slowCallbackPeriodSecond);
2016-01-31 12:01:41 -08:00
}
2016-03-11 08:03:18 -08:00
#endif /* ! EFI_UNIT_TEST */
void initAccelEnrichment() {
2024-03-04 14:58:24 -08:00
tpsTpsMap.initTable(config->tpsTpsAccelTable, config->tpsTpsAccelToRpmBins, config->tpsTpsAccelFromRpmBins);
2016-03-11 08:03:18 -08:00
2019-04-12 19:07:03 -07:00
#if ! EFI_UNIT_TEST
2017-01-06 13:03:41 -08:00
2015-07-10 06:01:56 -07:00
addConsoleAction("accelinfo", accelInfo);
2016-01-31 12:01:41 -08:00
updateAccelParameters();
2015-07-10 06:01:56 -07:00
#endif /* ! EFI_UNIT_TEST */
2016-03-11 08:03:18 -08:00
}