Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | #include "pch.h" | |||
2 | ||||
3 | #include "lambda_monitor.h" | |||
4 | ||||
5 | #if EFI_SHAFT_POSITION_INPUT | |||
6 | ||||
7 | ✗ | float LambdaMonitor::getMaxAllowedLambda(float rpm, float load) const { | ||
8 | return | |||
9 | ✗ | engine->fuelComputer.targetLambda | ||
10 | ✗ | + interpolate3d( | ||
11 | ✗ | config->lambdaMaxDeviationTable, | ||
12 | ✗ | config->lambdaMaxDeviationLoadBins, load, | ||
13 | ✗ | config->lambdaMaxDeviationRpmBins, rpm | ||
14 | ✗ | ); | ||
15 | } | |||
16 | ||||
17 | 1120 | float LambdaMonitor::getTimeout() const { | ||
18 | 1120 | return engineConfiguration->lambdaProtectionTimeout; | ||
19 | } | |||
20 | ||||
21 | 1171 | bool LambdaMonitorBase::isCut() const { | ||
22 | 1171 | return lambdaMonitorCut; | ||
23 | } | |||
24 | ||||
25 | 1126 | void LambdaMonitorBase::update(float rpm, float load) { | ||
26 | 1126 | bool isGood = isCurrentlyGood(rpm, load); | ||
27 | 1126 | lambdaCurrentlyGood = isGood; | ||
28 |
2/2✓ Branch 0 taken 1123 times.
✓ Branch 1 taken 3 times.
|
2/2✓ Decision 'true' taken 1123 times.
✓ Decision 'false' taken 3 times.
|
1126 | if (isGood) { |
29 | 1123 | m_timeSinceGoodLambda.reset(); | ||
30 | } | |||
31 | ||||
32 |
1/1✓ Branch 2 taken 1126 times.
|
1126 | lambdaTimeSinceGood = m_timeSinceGoodLambda.getElapsedSeconds(); | |
33 | ||||
34 |
2/2✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1125 times.
|
2/2✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 1125 times.
|
1126 | if (m_timeSinceGoodLambda.hasElapsedSec(getTimeout())) { |
35 | // Things have been bad long enough, cut! | |||
36 | 1 | lambdaMonitorCut = true; | ||
37 | } | |||
38 | ||||
39 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1123 times.
|
2/2✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 1123 times.
|
1126 | if (lambdaMonitorCut) { |
40 | // If things are back to normal, cancel the cut and force a reset | |||
41 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
|
2/2✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 2 times.
|
3 | if (restoreConditionsMet(rpm, load)) { |
42 | 1 | lambdaMonitorCut = false; | ||
43 | 1 | m_timeSinceGoodLambda.reset(); | ||
44 | } | |||
45 | } | |||
46 | 1126 | } | ||
47 | ||||
48 | 1120 | bool LambdaMonitorBase::isCurrentlyGood(float rpm, float load) const { | ||
49 | // Lambda is always good if disabled | |||
50 |
1/2✓ Branch 0 taken 1120 times.
✗ Branch 1 not taken.
|
1/2✓ Decision 'true' taken 1120 times.
✗ Decision 'false' not taken.
|
1120 | if (!engineConfiguration->lambdaProtectionEnable) { |
51 | 1120 | return true; | ||
52 | } | |||
53 | ||||
54 | // Below min RPM, don't check | |||
55 | ✗ | if (rpm < engineConfiguration->lambdaProtectionMinRpm) { | ||
56 | ✗ | return true; | ||
57 | } | |||
58 | ||||
59 | // Below min load, don't check | |||
60 | ✗ | if (load < engineConfiguration->lambdaProtectionMinLoad) { | ||
61 | ✗ | return true; | ||
62 | } | |||
63 | ||||
64 | // Below min TPS, don't check | |||
65 | ✗ | if (Sensor::getOrZero(SensorType::Tps1) <= engineConfiguration->lambdaProtectionMinTps) { | ||
66 | ✗ | return true; | ||
67 | } | |||
68 | ||||
69 | // Pause checking if DFCO was active recently | |||
70 | ✗ | auto timeSinceDfco = engine->module<DfcoController>()->getTimeSinceCut(); | ||
71 | ✗ | if (timeSinceDfco < engineConfiguration->noFuelTrimAfterDfcoTime) { | ||
72 | ✗ | return true; | ||
73 | } | |||
74 | ||||
75 | // Pause checking if some other cut was active recently | |||
76 | ✗ | auto timeSinceFuelCut = engine->module<LimpManager>()->getTimeSinceAnyCut(); | ||
77 | // TODO: should this duration be configurable? | |||
78 | ✗ | if (timeSinceFuelCut < 2) { | ||
79 | ✗ | return true; | ||
80 | } | |||
81 | ||||
82 | // TODO: multiple banks | |||
83 | ✗ | if (auto lambda = Sensor::get(SensorType::Lambda1)) { | ||
84 | ✗ | if (lambda.Value < getMaxAllowedLambda(rpm, load)) { | ||
85 | // Lambda is OK, we're good. | |||
86 | ✗ | return true; | ||
87 | } | |||
88 | } else { | |||
89 | // Broken lambda sensor doesn't imply bad lambda | |||
90 | ||||
91 | // TODO: can/should we be smarter here? | |||
92 | ✗ | return true; | ||
93 | } | |||
94 | ||||
95 | // All checks failed, lambda is currently bad. | |||
96 | ✗ | return false; | ||
97 | } | |||
98 | ||||
99 | ✗ | bool LambdaMonitorBase::restoreConditionsMet(float rpm, float load) const { | ||
100 | ✗ | if (rpm > engineConfiguration->lambdaProtectionRestoreRpm) { | ||
101 | ✗ | return false; | ||
102 | } | |||
103 | ||||
104 | ✗ | if (load > engineConfiguration->lambdaProtectionRestoreLoad) { | ||
105 | ✗ | return false; | ||
106 | } | |||
107 | ||||
108 | ✗ | if (Sensor::getOrZero(SensorType::Tps1) > engineConfiguration->lambdaProtectionRestoreTps) { | ||
109 | ✗ | return false; | ||
110 | } | |||
111 | ||||
112 | ✗ | return true; | ||
113 | } | |||
114 | #endif // EFI_SHAFT_POSITION_INPUT | |||
115 |