| Line | Branch | Decision | Exec | Source |
|---|---|---|---|---|
| 1 | #include "pch.h" | |||
| 2 | ||||
| 3 | #include "ac_control.h" | |||
| 4 | #include "deadband.h" | |||
| 5 | #include "max_limit_with_hysteresis.h" | |||
| 6 | ||||
| 7 | namespace { | |||
| 8 | // Deadbands to prevent rapid switching on/off of AC | |||
| 9 | Deadband<200> maxRpmDeadband; | |||
| 10 | Deadband<5> maxCltDeadband; | |||
| 11 | Deadband<5> maxTpsDeadband; | |||
| 12 | Deadband<AcController::PRESSURE_DEADBAND_WIDTH> minPressureDeadband; | |||
| 13 | MaxLimitWithHysteresis acPressureEnableHysteresis; | |||
| 14 | } | |||
| 15 | ||||
| 16 | 1086 | bool AcController::getAcState() { | ||
| 17 |
1/1✓ Branch 1 taken 1086 times.
|
1086 | auto rpm = Sensor::getOrZero(SensorType::Rpm); | |
| 18 | ||||
| 19 | 1086 | engineTooSlow = rpm < 500; | ||
| 20 | ||||
| 21 |
2/2✓ Branch 0 taken 922 times.
✓ Branch 1 taken 164 times.
|
2/2✓ Decision 'true' taken 922 times.
✓ Decision 'false' taken 164 times.
|
1086 | if (engineTooSlow) { |
| 22 | 922 | return false; | ||
| 23 | } | |||
| 24 | ||||
| 25 | 164 | auto maxRpm = engineConfiguration->maxAcRpm; | ||
| 26 |
3/4✓ Branch 1 taken 164 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 48 times.
✓ Branch 6 taken 116 times.
|
164 | engineTooFast = maxRpm != 0 && maxRpmDeadband.gt(rpm, maxRpm); | |
| 27 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 116 times.
|
2/2✓ Decision 'true' taken 48 times.
✓ Decision 'false' taken 116 times.
|
164 | if (engineTooFast) { |
| 28 | 48 | return false; | ||
| 29 | } | |||
| 30 | ||||
| 31 |
1/1✓ Branch 2 taken 116 times.
|
116 | auto clt = Sensor::get(SensorType::Clt); | |
| 32 | ||||
| 33 | 116 | noClt = !clt; | ||
| 34 | // No AC with failed CLT | |||
| 35 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 116 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 116 times.
|
116 | if (noClt) { |
| 36 | ✗ | return false; | ||
| 37 | } | |||
| 38 | ||||
| 39 | // Engine too hot, disable | |||
| 40 | 116 | auto maxClt = engineConfiguration->maxAcClt; | ||
| 41 |
2/4✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 116 times.
|
116 | engineTooHot = (maxClt != 0) && maxCltDeadband.gt(clt.Value, maxClt); | |
| 42 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 116 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 116 times.
|
116 | if (engineTooHot) { |
| 43 | ✗ | return false; | ||
| 44 | } | |||
| 45 | ||||
| 46 | // TPS too high, disable | |||
| 47 | 116 | auto maxTps = engineConfiguration->maxAcTps; | ||
| 48 |
4/5✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 116 times.
✓ Branch 6 taken 51 times.
✓ Branch 7 taken 65 times.
|
116 | tpsTooHigh = maxTps != 0 && maxTpsDeadband.gt(Sensor::getOrZero(SensorType::Tps1), maxTps); | |
| 49 |
2/2✓ Branch 0 taken 51 times.
✓ Branch 1 taken 65 times.
|
2/2✓ Decision 'true' taken 51 times.
✓ Decision 'false' taken 65 times.
|
116 | if (tpsTooHigh) { |
| 50 | 51 | return false; | ||
| 51 | } | |||
| 52 | ||||
| 53 |
1/1✓ Branch 1 taken 65 times.
|
65 | const auto acPressure= Sensor::get(SensorType::AcPressure); | |
| 54 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 38 times.
|
2/2✓ Decision 'true' taken 27 times.
✓ Decision 'false' taken 38 times.
|
65 | if (acPressure.Valid) { |
| 55 | 27 | const auto minAcPressure = static_cast<float>(engineConfiguration->minAcPressure); | ||
| 56 | 27 | acPressureTooLow = minPressureDeadband.lt(acPressure.Value, minAcPressure); | ||
| 57 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 21 times.
|
2/2✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 21 times.
|
27 | if (acPressureTooLow) { |
| 58 | 6 | return false; | ||
| 59 | } | |||
| 60 | ||||
| 61 | 21 | const auto maxAcPressure = static_cast<float>(engineConfiguration->maxAcPressure); | ||
| 62 | 63 | acPressureTooHigh = acPressureEnableHysteresis.checkIfLimitIsExceeded( | ||
| 63 |
1/1✓ Branch 1 taken 21 times.
|
21 | acPressure.Value, | |
| 64 | maxAcPressure, | |||
| 65 | 21 | engineConfiguration->acPressureEnableHyst | ||
| 66 | ); | |||
| 67 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 15 times.
|
2/2✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 15 times.
|
21 | if (acPressureTooHigh) { |
| 68 | 6 | return false; | ||
| 69 | } | |||
| 70 | } | |||
| 71 | ||||
| 72 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 53 times.
|
53 | if (isDisabledByLua) { |
| 73 | ✗ | return false; | ||
| 74 | } | |||
| 75 | ||||
| 76 | // All conditions allow AC, simply pass thru switch | |||
| 77 | 53 | return acButtonState; | ||
| 78 | } | |||
| 79 | ||||
| 80 | 1086 | void AcController::onSlowCallback() { | ||
| 81 | 1086 | bool isEnabled = getAcState(); | ||
| 82 | ||||
| 83 | 1086 | m_acEnabled = isEnabled; | ||
| 84 | ||||
| 85 |
2/2✓ Branch 0 taken 1071 times.
✓ Branch 1 taken 15 times.
|
2/2✓ Decision 'true' taken 1071 times.
✓ Decision 'false' taken 15 times.
|
1086 | if (!isEnabled) { |
| 86 | // reset the timer if AC is off | |||
| 87 | 1071 | m_timeSinceNoAc.reset(); | ||
| 88 | } | |||
| 89 | ||||
| 90 | 1086 | float acDelay = engineConfiguration->acDelay; | ||
| 91 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 1059 times.
|
2/2✓ Decision 'true' taken 27 times.
✓ Decision 'false' taken 1059 times.
|
1086 | if (acDelay == 0) { |
| 92 | // Without delay configured, enable immediately | |||
| 93 | 27 | acCompressorState = isEnabled; | ||
| 94 | } else { | |||
| 95 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1059 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1059 | acCompressorState = isEnabled && m_timeSinceNoAc.hasElapsedSec(acDelay); | |
| 96 | } | |||
| 97 | ||||
| 98 | 1086 | enginePins.acRelay.setValue(acCompressorState); | ||
| 99 | 1086 | } | ||
| 100 | ||||
| 101 | 2199 | bool AcController::isAcEnabled() const { | ||
| 102 | 2199 | return m_acEnabled; | ||
| 103 | } | |||
| 104 |