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 | 680 | AlternatorController::AlternatorController() { | ||
25 | 680 | alternatorPid.initPidClass(&engineConfiguration->alternatorControl); | ||
26 | 680 | } | ||
27 | ||||
28 | 1120 | void AlternatorController::onFastCallback() { | ||
29 |
1/2✓ Branch 1 taken 1120 times.
✗ Branch 2 not taken.
|
1/2✓ Decision 'true' taken 1120 times.
✗ Decision 'false' not taken.
|
1120 | if (!isBrainPinValid(engineConfiguration->alternatorControlPin)) { |
30 | 1120 | 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 | 219 | void AlternatorController::onConfigurationChange(engine_configuration_s const * previousConfiguration) { | ||
84 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 219 times.
|
219 | if(!alternatorPid.isSame(&previousConfiguration->alternatorControl)) { |
85 | ✗ | alternatorPid.reset(); | ||
86 | } | |||
87 | 219 | } | ||
88 | ||||
89 | 584 | void initAlternatorCtrl() { | ||
90 |
1/2✓ Branch 1 taken 584 times.
✗ Branch 2 not taken.
|
1/2✓ Decision 'true' taken 584 times.
✗ Decision 'false' not taken.
|
584 | if (!isBrainPinValid(engineConfiguration->alternatorControlPin)) |
91 | 584 | 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 |