Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | #include "pch.h" | |||
2 | ||||
3 | #include "maf_airmass.h" | |||
4 | #include "maf.h" | |||
5 | #include "fuel_math.h" | |||
6 | ||||
7 | ✗ | float MafAirmass::getMaf() const { | ||
8 | ✗ | auto maf = Sensor::get(SensorType::Maf); | ||
9 | ||||
10 | ✗ | if (Sensor::hasSensor(SensorType::Maf2)) { | ||
11 | ✗ | auto maf2 = Sensor::get(SensorType::Maf2); | ||
12 | ||||
13 | ✗ | if (maf && maf2) { | ||
14 | // Both MAFs work, return the sum | |||
15 | ✗ | return maf.Value + maf2.Value; | ||
16 | ✗ | } else if (maf) { | ||
17 | // MAF 1 works, but not MAF 2, so double the value from #1 | |||
18 | ✗ | return 2 * maf.Value; | ||
19 | ✗ | } else if (maf2) { | ||
20 | // MAF 2 works, but not MAF 1, so double the value from #2 | |||
21 | ✗ | return 2 * maf2.Value; | ||
22 | } else { | |||
23 | // Both MAFs are broken, give up. | |||
24 | ✗ | return 0; | ||
25 | } | |||
26 | } else { | |||
27 | ✗ | return maf.value_or(0); | ||
28 | } | |||
29 | } | |||
30 | ||||
31 | ✗ | AirmassResult MafAirmass::getAirmass(float rpm, bool postState) { | ||
32 | ✗ | float maf = getMaf(); | ||
33 | ||||
34 | ✗ | return getAirmassImpl(maf, rpm, postState); | ||
35 | } | |||
36 | ||||
37 | /** | |||
38 | * Function block now works to create a standardised load from the cylinder filling as well as tune fuel via VE table. | |||
39 | * @return total duration of fuel injection per engine cycle, in milliseconds | |||
40 | */ | |||
41 | 1 | AirmassResult MafAirmass::getAirmassImpl(float massAirFlow, float rpm, bool postState) const { | ||
42 | // If the engine is stopped, MAF is meaningless | |||
43 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1 time.
|
1 | if (rpm == 0) { |
44 | ✗ | return {}; | ||
45 | } | |||
46 | ||||
47 | // kg/hr -> g/s | |||
48 | 1 | float gramPerSecond = massAirFlow * 1000 / 3600; | ||
49 | ||||
50 | // 1/min -> 1/s | |||
51 | 1 | float revsPerSecond = rpm / 60.0f; | ||
52 | 1 | mass_t airPerRevolution = gramPerSecond / revsPerSecond; | ||
53 | ||||
54 | // Now we have to divide among cylinders - on a 4 stroke, half of the cylinders happen every revolution | |||
55 | // This math is floating point to work properly on engines with odd cylinder count | |||
56 | 1 | float halfCylCount = engineConfiguration->cylindersCount / 2.0f; | ||
57 | ||||
58 | 1 | mass_t cylinderAirmass = airPerRevolution / halfCylCount; | ||
59 | ||||
60 | //Create % load for fuel table using relative naturally aspirated cylinder filling | |||
61 | 1 | float airChargeLoad = 100 * cylinderAirmass / getStandardAirCharge(); | ||
62 | ||||
63 | //Correct air mass by VE table | |||
64 | 1 | mass_t correctedAirmass = cylinderAirmass * getVe(rpm, airChargeLoad, postState); | ||
65 | ||||
66 | return { | |||
67 | correctedAirmass, | |||
68 | airChargeLoad, // AFR/VE/ignition table Y axis | |||
69 | 1 | }; | ||
70 | } | |||
71 |