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
|
2019-01-06 17:45:51 -08:00
|
|
|
* @author Matthew Kennedy
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
|
2021-07-25 22:05:17 -07:00
|
|
|
#include "pch.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
#include "accel_enrichment.h"
|
|
|
|
|
2024-05-03 19:13:30 -07:00
|
|
|
static tps_tps_Map3D_t tpsTpsMap{"tps"};
|
2016-03-11 08:03:18 -08:00
|
|
|
|
2024-06-09 15:15:34 -07:00
|
|
|
// on this level we do not distinguish between multiplier and 'ms adder' modes
|
|
|
|
float TpsAccelEnrichment::getTpsEnrichment() {
|
2019-10-13 13:14:08 -07:00
|
|
|
ScopePerf perf(PE::GetTpsEnrichment);
|
|
|
|
|
2022-01-23 12:31:39 -08:00
|
|
|
if (engineConfiguration->tpsAccelLookback == 0) {
|
|
|
|
// If disabled, return 0.
|
|
|
|
return 0;
|
|
|
|
}
|
2024-09-24 23:54:54 -07:00
|
|
|
float rpm = Sensor::getOrZero(SensorType::Rpm);
|
2022-12-14 16:57:07 -08:00
|
|
|
if (rpm == 0) {
|
2022-03-19 10:05:44 -07:00
|
|
|
return 0;
|
|
|
|
}
|
2016-03-11 08:03:18 -08:00
|
|
|
|
2021-10-30 19:03:19 -07:00
|
|
|
if (isAboveAccelThreshold) {
|
|
|
|
valueFromTable = tpsTpsMap.getValue(tpsFrom, tpsTo);
|
2016-09-17 16:02:34 -07:00
|
|
|
extraFuel = valueFromTable;
|
2021-10-30 19:03:19 -07:00
|
|
|
} 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
|
|
|
}
|
|
|
|
|
2019-03-28 19:47:20 -07:00
|
|
|
// Fractional enrichment (fuel portions are accumulated and split between several engine cycles.
|
|
|
|
// This is a crude imitation of carburetor's acceleration pump.
|
2021-11-17 00:54:21 -08:00
|
|
|
isFractionalEnrichment = engineConfiguration->tpsAccelFractionPeriod > 1 || engineConfiguration->tpsAccelFractionDivisor > 1.0f;
|
2021-10-30 19:03:19 -07:00
|
|
|
if (isFractionalEnrichment) {
|
2019-03-28 19:47:20 -07:00
|
|
|
// make sure both values are non-zero
|
2024-09-25 14:00:33 -07:00
|
|
|
float periodF = std::max<int>(engineConfiguration->tpsAccelFractionPeriod, 1);
|
|
|
|
float divisor = std::max(engineConfiguration->tpsAccelFractionDivisor, 1.0f);
|
2019-03-28 19:47:20 -07:00
|
|
|
|
|
|
|
// if current extra fuel portion is not "strong" enough, then we keep up the "pump pressure" with the accumulated portion
|
2024-09-25 14:00:33 -07:00
|
|
|
floatms_t maxExtraFuel = std::max(extraFuel, accumulatedValue);
|
2019-03-28 19:47:20 -07:00
|
|
|
// use only a fixed fraction of the accumulated portion
|
2021-10-30 19:03:19 -07:00
|
|
|
fractionalInjFuel = maxExtraFuel / divisor;
|
2019-03-28 19:47:20 -07:00
|
|
|
|
|
|
|
// update max counters
|
2024-09-25 14:00:33 -07:00
|
|
|
maxExtraPerCycle = std::max(extraFuel, maxExtraPerCycle);
|
|
|
|
maxInjectedPerPeriod = std::max(fractionalInjFuel, maxInjectedPerPeriod);
|
2019-03-28 19:47:20 -07:00
|
|
|
|
|
|
|
// evenly split it between several engine cycles
|
2021-10-30 19:03:19 -07:00
|
|
|
extraFuel = fractionalInjFuel / periodF;
|
2019-03-28 19:47:20 -07:00
|
|
|
} else {
|
|
|
|
resetFractionValues();
|
|
|
|
}
|
|
|
|
|
2024-03-17 12:06:14 -07:00
|
|
|
float mult = interpolate2d(rpm, config->tpsTspCorrValuesBins,
|
|
|
|
config->tpsTspCorrValues);
|
2022-12-14 16:57:07 -08:00
|
|
|
if (mult != 0 && (mult < 0.01 || mult > 100)) {
|
|
|
|
mult = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return extraFuel * mult;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2021-11-16 01:15:29 -08:00
|
|
|
void TpsAccelEnrichment::onEngineCycleTps() {
|
2020-04-05 06:11:25 -07:00
|
|
|
// we update values in handleFuel() directly by calling onNewValue()
|
2019-03-28 19:47:20 -07:00
|
|
|
|
2019-10-16 19:10:38 -07:00
|
|
|
onUpdateInvocationCounter++;
|
|
|
|
|
2019-03-28 19:47:20 -07:00
|
|
|
// we used some extra fuel during the current cycle, so we "charge" our "acceleration pump" with it
|
|
|
|
accumulatedValue -= maxExtraPerPeriod;
|
2024-09-25 14:00:33 -07:00
|
|
|
maxExtraPerPeriod = std::max(maxExtraPerCycle, maxExtraPerPeriod);
|
2019-03-28 19:47:20 -07:00
|
|
|
maxExtraPerCycle = 0;
|
|
|
|
accumulatedValue += maxExtraPerPeriod;
|
|
|
|
|
|
|
|
// update the accumulated value every 'Period' engine cycles
|
2021-10-30 19:20:29 -07:00
|
|
|
isTimeToResetAccumulator = --cycleCnt <= 0;
|
|
|
|
if (isTimeToResetAccumulator) {
|
2019-03-28 19:47:20 -07:00
|
|
|
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;
|
2021-10-30 19:24:43 -07:00
|
|
|
belowEpsilon = accumulatedValue < smallEpsilon;
|
2021-10-30 19:20:29 -07:00
|
|
|
if (belowEpsilon) {
|
2019-03-28 19:47:20 -07:00
|
|
|
accumulatedValue = 0;
|
2021-10-30 19:20:29 -07:00
|
|
|
}
|
2019-03-28 19:47:20 -07:00
|
|
|
|
|
|
|
// reset the counter
|
2021-11-17 00:54:21 -08:00
|
|
|
cycleCnt = engineConfiguration->tpsAccelFractionPeriod;
|
2019-03-28 19:47:20 -07:00
|
|
|
}
|
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() {
|
2021-11-16 01:15:29 -08:00
|
|
|
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) {
|
2022-01-23 12:31:39 -08:00
|
|
|
// Push new value in to the history buffer
|
2021-10-31 09:07:44 -07:00
|
|
|
cb.add(currentValue);
|
2022-01-23 12:31:39 -08:00
|
|
|
|
|
|
|
// 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() {
|
2019-07-12 20:15:52 -07:00
|
|
|
resetAE();
|
2015-07-10 06:01:56 -07:00
|
|
|
cb.setSize(4);
|
|
|
|
}
|
|
|
|
|
2024-08-01 21:45:54 -07:00
|
|
|
void TpsAccelEnrichment::onConfigurationChange(engine_configuration_s const* /*previousConfig*/) {
|
|
|
|
constexpr float slowCallbackPeriodSecond = SLOW_CALLBACK_PERIOD_MS / 1000.0f;
|
|
|
|
int length = engineConfiguration->tpsAccelLookback / slowCallbackPeriodSecond;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-08-01 21:45:54 -07:00
|
|
|
setLength(length);
|
2016-01-31 12:01:41 -08:00
|
|
|
}
|
|
|
|
|
2021-11-16 01:15:29 -08:00
|
|
|
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
|
|
|
|
2024-08-01 21:45:54 -07:00
|
|
|
engine->module<TpsAccelEnrichment>()->onConfigurationChange(nullptr);
|
2016-03-11 08:03:18 -08:00
|
|
|
}
|
|
|
|
|