| Line | Branch | Decision | Exec | Source |
|---|---|---|---|---|
| 1 | /** | |||
| 2 | * @author Andrey Belomutskiy, (c) 2012-2020 | |||
| 3 | * | |||
| 4 | * EGO Exhaust Gas Oxygen, also known as AFR Air/Fuel Ratio :) connectet over analog input | |||
| 5 | * | |||
| 6 | */ | |||
| 7 | #include "pch.h" | |||
| 8 | ||||
| 9 | StoredValueSensor smoothedLambda1Sensor(SensorType::SmoothedLambda1, MS2NT(500)); | |||
| 10 | StoredValueSensor smoothedLambda2Sensor(SensorType::SmoothedLambda2, MS2NT(500)); | |||
| 11 | ||||
| 12 | ExpAverage expAverageLambda1; | |||
| 13 | ExpAverage expAverageLambda2; | |||
| 14 | ||||
| 15 | #include "cyclic_buffer.h" | |||
| 16 | ||||
| 17 | ✗ | bool hasAfrSensor() { | ||
| 18 | ✗ | if (engineConfiguration->enableAemXSeries) { | ||
| 19 | ✗ | return true; | ||
| 20 | } | |||
| 21 | ||||
| 22 | ✗ | return isAdcChannelValid(engineConfiguration->afr.hwChannel); | ||
| 23 | } | |||
| 24 | ||||
| 25 | ✗ | float getAfr(SensorType type) { | ||
| 26 | ✗ | afr_sensor_s * sensor = &engineConfiguration->afr; | ||
| 27 | ||||
| 28 | ✗ | if (!isAdcChannelValid(type == SensorType::Lambda1 ? engineConfiguration->afr.hwChannel : engineConfiguration->afr.hwChannel2)) { | ||
| 29 | ✗ | return 0; | ||
| 30 | } | |||
| 31 | ||||
| 32 | ✗ | auto volts = adcGetScaledVoltage("ego", type == SensorType::Lambda1 ? sensor->hwChannel : sensor->hwChannel2); | ||
| 33 | ||||
| 34 | ✗ | float interpolatedAfr = interpolateMsg("AFR", sensor->v1, sensor->value1, sensor->v2, sensor->value2, volts.value_or(0)); | ||
| 35 | ||||
| 36 | ✗ | switch (type) { | ||
| 37 | ✗ | case SensorType::Lambda1: { | ||
| 38 | ✗ | expAverageLambda1.setSmoothingFactor(engineConfiguration->afrExpAverageAlpha); | ||
| 39 | ✗ | smoothedLambda1Sensor.setValidValue(expAverageLambda1.initOrAverage(interpolatedAfr), getTimeNowNt()); | ||
| 40 | ✗ | break; | ||
| 41 | } | |||
| 42 | ✗ | case SensorType::Lambda2: { | ||
| 43 | ✗ | expAverageLambda2.setSmoothingFactor(engineConfiguration->afrExpAverageAlpha); | ||
| 44 | ✗ | smoothedLambda2Sensor.setValidValue(expAverageLambda2.initOrAverage(interpolatedAfr), getTimeNowNt()); | ||
| 45 | ✗ | break; | ||
| 46 | } | |||
| 47 | ✗ | default: | ||
| 48 | ✗ | break; | ||
| 49 | } | |||
| 50 | ||||
| 51 | ✗ | return interpolateMsg("AFR", sensor->v1, sensor->value1, sensor->v2, sensor->value2, volts.value_or(0)) | ||
| 52 | ✗ | + engineConfiguration->egoValueShift; | ||
| 53 | } | |||
| 54 | ||||
| 55 | // this method is only used for canned tunes now! User-facing selection is defined in tunerstudio.template.ini using settingSelector | |||
| 56 | 596 | static void initEgoSensor(afr_sensor_s *sensor, ego_sensor_e type) { | ||
| 57 | ||||
| 58 |
2/6✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 593 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
596 | switch (type) { | |
| 59 | ✗ | case ES_BPSX_D1: | ||
| 60 | /** | |||
| 61 | * This decodes BPSX D1 Wideband Controller analog signal | |||
| 62 | */ | |||
| 63 | ✗ | sensor->v1 = 0; | ||
| 64 | ✗ | sensor->value1 = 9; | ||
| 65 | ✗ | sensor->v2 = 5; | ||
| 66 | ✗ | sensor->value2 = 19; | ||
| 67 | ✗ | break; | ||
| 68 | ||||
| 69 | ✗ | case ES_Innovate_MTX_L: | ||
| 70 | ✗ | sensor->v1 = 0; | ||
| 71 | ✗ | sensor->value1 = 7.35; | ||
| 72 | ✗ | sensor->v2 = 5; | ||
| 73 | ✗ | sensor->value2 = 22.39; | ||
| 74 | ✗ | break; | ||
| 75 |
1/1✓ Decision 'true' taken 593 times.
|
593 | case ES_14Point7_Free: | |
| 76 | 593 | sensor->v1 = 0; | ||
| 77 | 593 | sensor->value1 = 9.996; | ||
| 78 | 593 | sensor->v2 = 5; | ||
| 79 | 593 | sensor->value2 = 19.992; | ||
| 80 | 593 | break; | ||
| 81 | // technically 14Point7 and PLX use the same scale | |||
| 82 |
1/1✓ Decision 'true' taken 3 times.
|
3 | case ES_PLX: | |
| 83 | 3 | sensor->v1 = 0; | ||
| 84 | 3 | sensor->value1 = 10; | ||
| 85 | 3 | sensor->v2 = 5; | ||
| 86 | 3 | sensor->value2 = 20; | ||
| 87 | 3 | break; | ||
| 88 | ✗ | case ES_AEM: | ||
| 89 | ✗ | sensor->v1 = 0.5; | ||
| 90 | ✗ | sensor->value1 = 8.5; | ||
| 91 | ✗ | sensor->v2 = 4.5; | ||
| 92 | ✗ | sensor->value2 = 18; | ||
| 93 | ✗ | break; | ||
| 94 | ✗ | default: | ||
| 95 | ✗ | firmwareError(ObdCode::CUSTOM_EGO_TYPE, "Unexpected EGO %d", type); | ||
| 96 | ✗ | break; | ||
| 97 | } | |||
| 98 | 596 | } | ||
| 99 | ||||
| 100 | 596 | void setEgoSensor(ego_sensor_e type) { | ||
| 101 | 596 | engineConfiguration->afr_type = type; | ||
| 102 | 596 | initEgoSensor(&engineConfiguration->afr, type); | ||
| 103 | 596 | } | ||
| 104 |