GCC Code Coverage Report


Directory: ./
File: firmware/controllers/algo/wall_fuel.cpp
Date: 2025-11-16 14:52:24
Coverage Exec Excl Total
Lines: 47.8% 32 0 67
Functions: 83.3% 5 0 6
Branches: 50.0% 17 0 34
Decisions: 40.9% 9 - 22

Line Branch Decision Exec Source
1 /*
2 * @file wall_fuel.cpp
3 *
4 * @author Matthew Kennedy
5 */
6
7 #include "pch.h"
8 #include "wall_fuel.h"
9
10 void WallFuel::resetWF() {
11 wallFuel = 0;
12 }
13
14 9443 float WallFuel::adjust(float desiredMassGrams) {
15 9443 invocationCounter++;
16
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9443 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 9443 times.
9443 if (std::isnan(desiredMassGrams)) {
17 return desiredMassGrams;
18 }
19
20 9443 ScopePerf perf(PE::WallFuelAdjust);
21
22 /*
23 this math is based on
24 SAE 810494 by C. F. Aquino
25 SAE 1999-01-0553 by Peter J Maloney
26
27 M_cmd = commanded fuel mass (output of this function)
28 desiredMassGrams = desired fuel mass (input to this function)
29 fuelFilmMass = fuel film mass (how much is currently on the wall)
30
31 First we compute how much fuel to command, by accounting for
32 a) how much fuel will evaporate from the walls, entering the air
33 b) how much fuel from the injector will hit the walls, being deposited
34
35 Next, we compute how much fuel will be deposited on the walls. The net
36 effect of these two steps is computed (some leaves walls, some is deposited)
37 and stored back in fuelFilmMass.
38
39 alpha describes the amount of fuel that REMAINS on the wall per cycle.
40 It is computed as a function of the evaporation time constant (tau) and
41 the time the fuel spent on the wall this cycle, (recriprocal RPM).
42
43 beta describes the amount of fuel that hits the wall.
44 */
45
46 // If disabled, pass value through
47
4/4
✓ Branch 1 taken 9443 times.
✓ Branch 5 taken 9443 times.
✓ Branch 7 taken 9333 times.
✓ Branch 8 taken 110 times.
2/2
✓ Decision 'true' taken 9333 times.
✓ Decision 'false' taken 110 times.
9443 if (!engine->module<WallFuelController>()->getEnable()) {
48 9333 return desiredMassGrams;
49 }
50
51
2/2
✓ Branch 1 taken 110 times.
✓ Branch 5 taken 110 times.
110 float alpha = engine->module<WallFuelController>()->getAlpha();
52
2/2
✓ Branch 1 taken 110 times.
✓ Branch 5 taken 110 times.
110 float beta = engine->module<WallFuelController>()->getBeta();
53
54 110 float fuelFilmMass = wallFuel;
55 110 float M_cmd = (desiredMassGrams - (1 - alpha) * fuelFilmMass) / (1 - beta);
56
57 // We can't inject a negative amount of fuel
58 // If this goes below zero we will be over-fueling slightly,
59 // but that's ok.
60
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 110 times.
110 if (M_cmd <= 0) {
61 M_cmd = 0;
62 }
63
64 // remainder on walls from last time + new from this time
65 110 float fuelFilmMassNext = alpha * fuelFilmMass + beta * M_cmd;
66
67 110 wallFuel = fuelFilmMassNext;
68 110 wallFuelCorrection = M_cmd - desiredMassGrams;
69 110 return M_cmd;
70 }
71
72 531078 float WallFuel::getWallFuel() const {
73 531078 return wallFuel;
74 }
75
76 61316 float WallFuelController::computeTau() const {
77
1/2
✓ Branch 0 taken 61316 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 61316 times.
✗ Decision 'false' not taken.
61316 if (!engineConfiguration->complexWallModel) {
78 61316 return engineConfiguration->wwaeTau;
79 }
80
81 // Default to normal operating temperature in case of
82 // CLT failure, this is not critical to get perfect
83 float clt = Sensor::get(SensorType::Clt).value_or(90);
84
85 float tau = interpolate2d(
86 clt,
87 config->wwCltBins,
88 config->wwTauCltValues
89 );
90
91 // If you have a MAP sensor, apply MAP correction
92 if (Sensor::hasSensor(SensorType::Map)) {
93 auto map = Sensor::get(SensorType::Map).value_or(60);
94
95 tau *= interpolate2d(
96 map,
97 config->wwMapBins,
98 config->wwTauMapValues
99 );
100 }
101
102 return tau;
103 }
104
105 61316 float WallFuelController::computeBeta() const {
106
1/2
✓ Branch 0 taken 61316 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 61316 times.
✗ Decision 'false' not taken.
61316 if (!engineConfiguration->complexWallModel) {
107 61316 return engineConfiguration->wwaeBeta;
108 }
109
110 // Default to normal operating temperature in case of
111 // CLT failure, this is not critical to get perfect
112 float clt = Sensor::get(SensorType::Clt).value_or(90);
113
114 float beta = interpolate2d(
115 clt,
116 config->wwCltBins,
117 config->wwBetaCltValues
118 );
119
120 // If you have a MAP sensor, apply MAP correction
121 if (Sensor::hasSensor(SensorType::Map)) {
122 auto map = Sensor::get(SensorType::Map).value_or(60);
123
124 beta *= interpolate2d(
125 map,
126 config->wwMapBins,
127 config->wwBetaMapValues
128 );
129 }
130
131 // Clamp to 0..1 (you can't have more than 100% of the fuel hit the wall!)
132 return clampF(0, beta, 1);
133 }
134
135 90815 void WallFuelController::onFastCallback() {
136 // disable wall wetting cranking
137 // TODO: is this correct? Why not correct for cranking?
138
2/2
✓ Branch 1 taken 29499 times.
✓ Branch 2 taken 61316 times.
2/2
✓ Decision 'true' taken 29499 times.
✓ Decision 'false' taken 61316 times.
90815 if (engine->rpmCalculator.isCranking()) {
139 29499 m_enable = false;
140 29499 return;
141 }
142
143 61316 float tau = computeTau();
144 61316 float beta = computeBeta();
145
146 // if tau or beta is really small, we get div/0.
147 // you probably meant to disable wwae.
148
3/4
✓ Branch 0 taken 2861 times.
✓ Branch 1 taken 58455 times.
✓ Branch 2 taken 2861 times.
✗ Branch 3 not taken.
1/2
✓ Decision 'true' taken 61316 times.
✗ Decision 'false' not taken.
61316 if (tau < 0.01f || beta < 0.01f) {
149 61316 m_enable = false;
150 61316 return;
151 }
152
153 auto rpm = Sensor::getOrZero(SensorType::Rpm);
154
155 // Ignore low RPM
156 if (rpm < 100) {
157 m_enable = false;
158 return;
159 }
160
161 float alpha = expf_taylor(-120 / (rpm * tau));
162
163 // If beta is larger than alpha, the system is underdamped.
164 // For reasonable values {tau, beta}, this should only be possible
165 // at extremely low engine speeds (<300rpm ish)
166 // Clamp beta to less than alpha.
167 if (beta > alpha) {
168 beta = alpha;
169 }
170
171 // Store parameters so the model can read them
172 m_alpha = alpha;
173 m_beta = beta;
174 m_enable = true;
175 }
176