alternator uses closed loop controller

This commit is contained in:
Matthew Kennedy 2023-11-12 20:48:55 -08:00
parent 62980837b8
commit 793532cea5
4 changed files with 37 additions and 25 deletions

View File

@ -48,36 +48,39 @@ void AlternatorController::onFastCallback() {
alternatorPid.postState(engine->outputChannels.alternatorStatus);
#endif /* EFI_TUNER_STUDIO */
update();
}
expected<float> AlternatorController::getSetpoint() {
bool alternatorShouldBeEnabledAtCurrentRpm = Sensor::getOrZero(SensorType::Rpm) > engineConfiguration->cranking.rpm;
if (!engineConfiguration->isAlternatorControlEnabled || !alternatorShouldBeEnabledAtCurrentRpm) {
// we need to avoid accumulating iTerm while engine is not running
pidReset();
// Shut off output if not needed
alternatorControl.setSimplePwmDutyCycle(0);
return;
return unexpected;
}
auto vBatt = Sensor::get(SensorType::BatteryVoltage);
float targetVoltage = engineConfiguration->targetVBatt;
return engineConfiguration->targetVBatt;
}
if (!vBatt) {
// Somehow battery voltage isn't valid, disable alternator control
expected<float> AlternatorController::observePlant() const {
return Sensor::get(SensorType::BatteryVoltage);
}
expected<percent_t> AlternatorController::getOpenLoop(float /*target*/) {
// see "idle air Bump for AC" comment
return engine->module<AcController>().unmock().acButtonState ? engineConfiguration->acRelayAlternatorDutyAdder : 0;
}
expected<percent_t> AlternatorController::getClosedLoop(float setpoint, float observation) {
return alternatorPid.getOutput(setpoint, observation, FAST_CALLBACK_PERIOD_MS / 1000.0f);
}
void AlternatorController::setOutput(expected<percent_t> outputValue) {
if (outputValue) {
alternatorControl.setSimplePwmDutyCycle(PERCENT_TO_DUTY(outputValue.Value));
} else {
// turn off in case of fault and reset
alternatorPid.reset();
alternatorControl.setSimplePwmDutyCycle(0);
} else {
currentAltDuty = alternatorPid.getOutput(targetVoltage, vBatt.Value, FAST_CALLBACK_PERIOD_MS / 1000.0f);
// see "idle air Bump for AC" comment
int acDutyBump = engine->module<AcController>().unmock().acButtonState ? engineConfiguration->acRelayAlternatorDutyAdder : 0;
currentAltDuty += acDutyBump;
if (engineConfiguration->isVerboseAlternator) {
efiPrintf("alt duty: %.2f/vbatt=%.2f/p=%.2f/i=%.2f/d=%.2f int=%.2f", currentAltDuty, vBatt.Value,
alternatorPid.getP(), alternatorPid.getI(), alternatorPid.getD(), alternatorPid.getIntegration());
}
alternatorControl.setSimplePwmDutyCycle(PERCENT_TO_DUTY(currentAltDuty));
}
}

View File

@ -10,10 +10,20 @@
#pragma once
#include "engine_module.h"
#include "closed_loop_controller.h"
void initAlternatorCtrl();
class AlternatorController : public EngineModule {
class AlternatorController : public EngineModule, public ClosedLoopController<float, percent_t> {
public:
void onFastCallback() override;
void onConfigurationChange(engine_configuration_s const* previousConfiguration) override;
protected:
expected<float> observePlant() const override;
expected<float> getSetpoint() override;
expected<percent_t> getOpenLoop(float target) override;
expected<percent_t> getClosedLoop(float setpoint, float observation) override;
void setOutput(expected<percent_t> outputValue) override;
};

View File

@ -697,7 +697,7 @@ bit is_enabled_spi_2
bit is_enabled_spi_3
bit isSdCardEnabled;enable sd/disable sd
bit rusefiVerbose29b,"29 bit","11 bit";Use 11 bit (standard) or 29 bit (extended) IDs for FOME verbose CAN format.
bit isVerboseAlternator
bit unused644b5
bit useStepperIdle;This setting should only be used if you have a stepper motor idle valve and a stepper motor driver installed.
bit enabledStep1Limiter

View File

@ -3586,7 +3586,6 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_
field = "PWM frequency", alternatorPwmFrequency, {isAlternatorControlEnabled == 1}
field = "Off Above TPS", alternatorOffAboveTps, {isAlternatorControlEnabled == 1}
field = "A/C duty adder", acRelayAlternatorDutyAdder, {isAlternatorControlEnabled == 1}
field = "Detailed status in console", isVerboseAlternator, {isAlternatorControlEnabled == 1}
field = "#PID control"
field = "offset", alternatorControl_offset, {isAlternatorControlEnabled == 1}
field = "P factor", alternatorControl_pFactor, {isAlternatorControlEnabled == 1}