| 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 |