rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
accel_enrichment.cpp
Go to the documentation of this file.
1/**
2 * @file accel_enrichment.cpp
3 * @brief Acceleration enrichment calculator
4 *
5 * In this file we have three strategies for acceleration/deceleration fuel correction
6 *
7 * 1) MAP rate-of-change correction
8 * 2) TPS rate-of-change correction
9 * 3) fuel film/wal wetting correction
10 * AWC Added to Wall Coefficient, %
11 * AWA Added to Wall Amount
12 * SOC Sucked Off wall Coefficient, %
13 * SOA Sucked Off wall amount
14 * WF current on-Wall Fuel amount
15 *
16 *
17 * http://rusefi.com/wiki/index.php?title=Manual:Software:Fuel_Control
18 * @date Apr 21, 2014
19 * @author Dmitry Sidin
20 * @author Andrey Belomutskiy, (c) 2012-2020
21 * @author Matthew Kennedy
22 */
23
24#include "pch.h"
25#include "accel_enrichment.h"
26#include "tunerstudio.h"
27
28
29// on this level we do not distinguish between multiplier and 'ms adder' modes
32
33 // If predictive MAP mode is active, the old "adder" logic is disabled.
34 if (engineConfiguration->accelEnrichmentMode == AE_MODE_PREDICTIVE_MAP) {
35 return 0;
36 }
37
39 // If disabled, return 0.
40 return 0;
41 }
42
43#if EFI_TUNER_STUDIO
44 if (isTuningVeNow()) {
45 return 0;
46 }
47#endif
48
50 if (rpm < engineConfiguration->cranking.rpm) {
51 return 0;
52 }
53
55 valueFromTable = interpolate3d(config->tpsTpsAccelTable,
59 m_timeSinceAccel.reset();
60 } else if (isBelowDecelThreshold) {
62 m_timeSinceAccel.reset();
63 } else {
64 extraFuel = 0;
65 }
66
67 // Fractional enrichment (fuel portions are accumulated and split between several engine cycles.
68 // This is a crude imitation of carburetor's acceleration pump.
71 // make sure both values are non-zero
72 float periodF = std::max<int>(engineConfiguration->tpsAccelFractionPeriod, 1);
73 float divisor = std::max(engineConfiguration->tpsAccelFractionDivisor, 1.0f);
74
75 // if current extra fuel portion is not "strong" enough, then we keep up the "pump pressure" with the accumulated portion
76 floatms_t maxExtraFuel = std::max(extraFuel, accumulatedValue);
77 // use only a fixed fraction of the accumulated portion
78 fractionalInjFuel = maxExtraFuel / divisor;
79
80 // update max counters
83
84 // evenly split it between several engine cycles
85 extraFuel = fractionalInjFuel / periodF;
86 } else {
88 }
89
90 float mult = interpolate2d(rpm, config->tpsTspCorrValuesBins,
92 if (mult != 0 && (mult < 0.01 || mult > 100)) {
93 mult = 1;
94 }
95
96 return extraFuel * mult;
97}
98
100 // we update values in handleFuel() directly by calling onNewValue()
101
103
104 // we used some extra fuel during the current cycle, so we "charge" our "acceleration pump" with it
109
110 // update the accumulated value every 'Period' engine cycles
114
115 // we've injected this portion during the cycle, so we set what's left for the next cycle
118
119 // it's an infinitely convergent series, so we set a limit at some point
120 // (also make sure that accumulatedValue is positive, for safety)
121 static const floatms_t smallEpsilon = 0.001f;
122 belowEpsilon = accumulatedValue < smallEpsilon;
123 if (belowEpsilon) {
125 }
126
127 // reset the counter
129 }
130}
131
133 int len = minI(cb.getSize(), cb.getCount());
134 tooShort = len < 2;
135 if (tooShort) {
136 return 0;
137 }
138 int ci = cb.currentIndex - 1;
139 float maxValue = cb.get(ci) - cb.get(ci - 1);
140 int resultIndex = ci;
141
142 // todo: 'get' method is maybe a bit heavy because of the branching
143 // todo: this could be optimized with some careful magic
144
145 for (int i = 1; i<len - 1;i++) {
146 float v = cb.get(ci - i) - cb.get(ci - i - 1);
147 if (v > maxValue) {
148 maxValue = v;
149 resultIndex = ci - i;
150 }
151 }
152
153 return resultIndex;
154}
155
157 int index = getMaxDeltaIndex();
158
159 return (cb.get(index) - (cb.get(index - 1)));
160}
161
163 cb.clear();
165}
166
174
176 cb.setSize(length);
177}
178
179void TpsAccelEnrichment::onNewValue(float currentValue) {
180 // Push new value in to the history buffer
181 cb.add(currentValue);
182
183 // Update deltas
184 int maxDeltaIndex = getMaxDeltaIndex();
185 tpsFrom = cb.get(maxDeltaIndex - 1);
186 tpsTo = cb.get(maxDeltaIndex);
188
189 // Update threshold detection
191
192 // If an acceleration event just happened, latch the flag so it can be read once.
195 }
196
197 // TODO: can deltaTps actually be negative? Will this ever trigger?
199}
200
202 // Read the flag
203 bool result = m_accelEventJustOccurred;
204 // Reset it so we only fire once per event
206 return result;
207}
208
210 resetAE();
211 cb.setSize(4);
212}
213
215 constexpr float slowCallbackPeriodSecond = SLOW_CALLBACK_PERIOD_MS / 1000.0f;
216 int length = engineConfiguration->tpsAccelLookback / slowCallbackPeriodSecond;
217
218 if (length < 1) {
219 efiPrintf("setTpsAccelLen: Length should be positive [%d]", length);
220 return;
221 }
222
223 setLength(length);
224}
225
227 return m_timeSinceAccel.getElapsedSeconds();
228}
229
231 engine->module<TpsAccelEnrichment>()->onConfigurationChange(nullptr);
232}
void initAccelEnrichment()
Acceleration enrichment calculator.
constexpr auto & module()
Definition engine.h:200
static float getOrZero(SensorType type)
Definition sensor.h:83
void onConfigurationChange(engine_configuration_s const *previousConfig) override
float getTimeSinceAcell() const
cyclic_buffer< float > cb
void onNewValue(float currentValue)
void setLength(int length)
static EngineAccessor engine
Definition engine.h:413
static constexpr persistent_config_s * config
static constexpr engine_configuration_s * engineConfiguration
@ GetTpsEnrichment
float tpsTpsAccelTable[TPS_TPS_ACCEL_TABLE][TPS_TPS_ACCEL_TABLE]
scaled_channel< uint8_t, 1, 50 > tpsTspCorrValuesBins[TPS_TPS_ACCEL_CLT_CORR_TABLE]
scaled_channel< uint8_t, 50, 1 > tpsTspCorrValues[TPS_TPS_ACCEL_CLT_CORR_TABLE]
bool isTuningVeNow()