| Line | Branch | Decision | Exec | Source |
|---|---|---|---|---|
| 1 | /** | |||
| 2 | * @file alternator_controller.cpp | |||
| 3 | * @brief alternator controller - some newer vehicles control alternator with ECU | |||
| 4 | * | |||
| 5 | * @date Apr 6, 2014 | |||
| 6 | * @author Dmitry Sidin | |||
| 7 | * @author Andrey Belomutskiy, (c) 2012-2020 | |||
| 8 | */ | |||
| 9 | ||||
| 10 | #include "pch.h" | |||
| 11 | ||||
| 12 | #if EFI_ALTERNATOR_CONTROL | |||
| 13 | #include "alternator_controller.h" | |||
| 14 | #include "efi_pid.h" | |||
| 15 | #include "local_version_holder.h" | |||
| 16 | #include "periodic_task.h" | |||
| 17 | ||||
| 18 | #if defined(HAS_OS_ACCESS) | |||
| 19 | #error "Unexpected OS ACCESS HERE" | |||
| 20 | #endif /* HAS_OS_ACCESS */ | |||
| 21 | ||||
| 22 | static SimplePwm alternatorControl("alt"); | |||
| 23 | ||||
| 24 | 681 | AlternatorController::AlternatorController() { | ||
| 25 | 681 | alternatorPid.initPidClass(&engineConfiguration->alternatorControl); | ||
| 26 | 681 | } | ||
| 27 | ||||
| 28 | 1101 | void AlternatorController::onFastCallback() { | ||
| 29 |
1/2✓ Branch 1 taken 1101 times.
✗ Branch 2 not taken.
|
1/2✓ Decision 'true' taken 1101 times.
✗ Decision 'false' not taken.
|
1101 | if (!isBrainPinValid(engineConfiguration->alternatorControlPin)) { |
| 30 | 1101 | return; | ||
| 31 | } | |||
| 32 | ||||
| 33 | // this block could be executed even in on/off alternator control mode | |||
| 34 | // but at least we would reflect latest state | |||
| 35 | #if EFI_TUNER_STUDIO | |||
| 36 | ✗ | alternatorPid.postState(engine->outputChannels.alternatorStatus); | ||
| 37 | #endif /* EFI_TUNER_STUDIO */ | |||
| 38 | ||||
| 39 | ✗ | update(); | ||
| 40 | } | |||
| 41 | ||||
| 42 | 25 | expected<float> AlternatorController::getSetpoint() { | ||
| 43 | 25 | const float rpm = Sensor::getOrZero(SensorType::Rpm); | ||
| 44 | 25 | bool alternatorShouldBeEnabledAtCurrentRpm = rpm > engineConfiguration->cranking.rpm; | ||
| 45 | ||||
| 46 |
4/4✓ Branch 0 taken 23 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 22 times.
|
2/2✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 22 times.
|
25 | if (!engineConfiguration->isAlternatorControlEnabled || !alternatorShouldBeEnabledAtCurrentRpm) { |
| 47 | 3 | return unexpected; | ||
| 48 | } | |||
| 49 | ||||
| 50 | 22 | const float load = getEngineState()->fuelingLoad; | ||
| 51 | return interpolate3d( | |||
| 52 | 22 | config->alternatorVoltageTargetTable, | ||
| 53 | 22 | config->alternatorVoltageTargetLoadBins, load, | ||
| 54 | 22 | config->alternatorVoltageTargetRpmBins, rpm | ||
| 55 |
1/1✓ Branch 2 taken 22 times.
|
22 | ); | |
| 56 | } | |||
| 57 | ||||
| 58 | 1 | expected<float> AlternatorController::observePlant() { | ||
| 59 | 1 | return Sensor::get(SensorType::BatteryVoltage); | ||
| 60 | } | |||
| 61 | ||||
| 62 | 2 | expected<percent_t> AlternatorController::getOpenLoop(float /*target*/) { | ||
| 63 | // see "idle air Bump for AC" comment | |||
| 64 |
3/3✓ Branch 2 taken 2 times.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 1 time.
|
2 | return engine->module<AcController>().unmock().acButtonState ? engineConfiguration->acRelayAlternatorDutyAdder : 0; | |
| 65 | } | |||
| 66 | ||||
| 67 | 1 | expected<percent_t> AlternatorController::getClosedLoop(float setpoint, float observation) { | ||
| 68 | 1 | alternatorPid.iTermMin = engineConfiguration->alternator_iTermMin; | ||
| 69 | 1 | alternatorPid.iTermMax = engineConfiguration->alternator_iTermMax; | ||
| 70 |
1/1✓ Branch 3 taken 1 time.
|
1 | return alternatorPid.getOutput(setpoint, observation, FAST_CALLBACK_PERIOD_MS / 1000.0f); | |
| 71 | } | |||
| 72 | ||||
| 73 | 1 | void AlternatorController::setOutput(expected<percent_t> outputValue) { | ||
| 74 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1 time.
|
1 | if (outputValue) { |
| 75 | ✗ | alternatorControl.setSimplePwmDutyCycle(PERCENT_TO_DUTY(outputValue.Value)); | ||
| 76 | } else { | |||
| 77 | // Shut off output if not needed | |||
| 78 | 1 | alternatorPid.reset(); | ||
| 79 | 1 | alternatorControl.setSimplePwmDutyCycle(0); | ||
| 80 | } | |||
| 81 | 1 | } | ||
| 82 | ||||
| 83 | 221 | void AlternatorController::onConfigurationChange(engine_configuration_s const * previousConfiguration) { | ||
| 84 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 221 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 221 times.
|
221 | if(!alternatorPid.isSame(&previousConfiguration->alternatorControl)) { |
| 85 | ✗ | alternatorPid.reset(); | ||
| 86 | } | |||
| 87 | 221 | } | ||
| 88 | ||||
| 89 | 585 | void initAlternatorCtrl() { | ||
| 90 |
1/2✓ Branch 1 taken 585 times.
✗ Branch 2 not taken.
|
1/2✓ Decision 'true' taken 585 times.
✗ Decision 'false' not taken.
|
585 | if (!isBrainPinValid(engineConfiguration->alternatorControlPin)) |
| 91 | 585 | return; | ||
| 92 | ||||
| 93 | ✗ | startSimplePwm(&alternatorControl, | ||
| 94 | "Alternator control", | |||
| 95 | &engine->scheduler, | |||
| 96 | &enginePins.alternatorPin, | |||
| 97 | ✗ | engineConfiguration->alternatorPwmFrequency, 0); | ||
| 98 | } | |||
| 99 | ||||
| 100 | #endif /* EFI_ALTERNATOR_CONTROL */ | |||
| 101 |