mirror of https://github.com/rusefi/rusefi.git
alternator uses closed loop controller
This commit is contained in:
parent
02f1295688
commit
e15f9257ff
|
@ -20,25 +20,23 @@
|
|||
#endif /* HAS_OS_ACCESS */
|
||||
|
||||
static SimplePwm alternatorControl("alt");
|
||||
static Pid alternatorPid(&persistentState.persistentConfiguration.engineConfiguration.alternatorControl);
|
||||
|
||||
static percent_t currentAltDuty;
|
||||
void AlternatorController::onFastCallback() {
|
||||
if (!isBrainPinValid(engineConfiguration->alternatorControlPin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
static bool shouldResetPid = false;
|
||||
// this block could be executed even in on/off alternator control mode
|
||||
// but at least we would reflect latest state
|
||||
#if EFI_TUNER_STUDIO
|
||||
alternatorPid.postState(engine->outputChannels.alternatorStatus);
|
||||
#endif /* EFI_TUNER_STUDIO */
|
||||
|
||||
AlternatorController::AlternatorController() {
|
||||
alternatorPid.initPidClass(&engineConfiguration->alternatorControl);
|
||||
}
|
||||
|
||||
expected<float> AlternatorController::observePlant() {
|
||||
auto vBatt = Sensor::get(SensorType::BatteryVoltage);
|
||||
// if somehow battery voltage isn't valid
|
||||
if (!vBatt)
|
||||
return unexpected;
|
||||
return vBatt.Value;
|
||||
update();
|
||||
}
|
||||
|
||||
expected<float> AlternatorController::getSetpoint() {
|
||||
// check if the engine is not running
|
||||
bool alternatorShouldBeEnabledAtCurrentRpm = Sensor::getOrZero(SensorType::Rpm) > engineConfiguration->cranking.rpm;
|
||||
|
||||
if (!engineConfiguration->isAlternatorControlEnabled || !alternatorShouldBeEnabledAtCurrentRpm) {
|
||||
|
@ -48,80 +46,36 @@ expected<float> AlternatorController::getSetpoint() {
|
|||
return engineConfiguration->targetVBatt;
|
||||
}
|
||||
|
||||
expected<percent_t> AlternatorController::getOpenLoop(float target) {
|
||||
UNUSED(target);
|
||||
return 0;
|
||||
expected<float> AlternatorController::observePlant() {
|
||||
return Sensor::get(SensorType::BatteryVoltage);
|
||||
}
|
||||
|
||||
expected<percent_t> AlternatorController::getClosedLoop(float targetVoltage, float vBattVoltage) {
|
||||
percent_t altDuty = alternatorPid.getOutput(targetVoltage, vBattVoltage, FAST_CALLBACK_PERIOD_MS / 1000.0f);
|
||||
expected<percent_t> AlternatorController::getOpenLoop(float /*target*/) {
|
||||
// see "idle air Bump for AC" comment
|
||||
return engine->module<AcController>().unmock().acButtonState ? engineConfiguration->acRelayAlternatorDutyAdder : 0;
|
||||
}
|
||||
|
||||
// this block could be executed even in on/off alternator control mode
|
||||
// but at least we would reflect latest state
|
||||
#if EFI_TUNER_STUDIO
|
||||
alternatorPid.postState(engine->outputChannels.alternatorStatus);
|
||||
#endif /* EFI_TUNER_STUDIO */
|
||||
|
||||
// see "idle air Bump for AC" comment
|
||||
int acDutyBump = engine->module<AcController>().unmock().acButtonState ? engineConfiguration->acRelayAlternatorDutyAdder : 0;
|
||||
altDuty += acDutyBump;
|
||||
return altDuty;
|
||||
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) {
|
||||
currentAltDuty = outputValue.Value;
|
||||
alternatorControl.setSimplePwmDutyCycle(PERCENT_TO_DUTY(outputValue.Value));
|
||||
} else {
|
||||
// Shut off output if not needed
|
||||
// turn off in case of fault and reset
|
||||
alternatorPid.reset();
|
||||
alternatorControl.setSimplePwmDutyCycle(0);
|
||||
// we need to avoid accumulating iTerm while the alternator is not working
|
||||
pidReset();
|
||||
}
|
||||
}
|
||||
|
||||
void AlternatorController::pidReset() {
|
||||
alternatorPid.reset();
|
||||
}
|
||||
|
||||
void AlternatorController::onFastCallback() {
|
||||
if (!isBrainPinValid(engineConfiguration->alternatorControlPin)) {
|
||||
return;
|
||||
}
|
||||
#if ! EFI_UNIT_TEST
|
||||
if (shouldResetPid) {
|
||||
pidReset();
|
||||
shouldResetPid = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
ClosedLoopController::update();
|
||||
}
|
||||
|
||||
|
||||
void showAltInfo(void) {
|
||||
efiPrintf("alt=%s @%s t=%dms", boolToString(engineConfiguration->isAlternatorControlEnabled),
|
||||
hwPortname(engineConfiguration->alternatorControlPin),
|
||||
engineConfiguration->alternatorControl.periodMs);
|
||||
efiPrintf("p=%.2f/i=%.2f/d=%.2f offset=%.2f", engineConfiguration->alternatorControl.pFactor,
|
||||
0, 0, engineConfiguration->alternatorControl.offset); // todo: i & d
|
||||
efiPrintf("vbatt=%.2f/duty=%.2f/target=%.2f", Sensor::getOrZero(SensorType::BatteryVoltage), currentAltDuty,
|
||||
engineConfiguration->targetVBatt);
|
||||
}
|
||||
|
||||
void setAltPFactor(float p) {
|
||||
engineConfiguration->alternatorControl.pFactor = p;
|
||||
efiPrintf("setAltPid: %.2f", p);
|
||||
engine->module<AlternatorController>()->pidReset();
|
||||
showAltInfo();
|
||||
}
|
||||
|
||||
void AlternatorController::onConfigurationChange(engine_configuration_s const * previousConfiguration) {
|
||||
shouldResetPid = !alternatorPid.isSame(&previousConfiguration->alternatorControl);
|
||||
if(!alternatorPid.isSame(&previousConfiguration->alternatorControl)) {
|
||||
alternatorPid.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void initAlternatorCtrl() {
|
||||
addConsoleAction("altinfo", showAltInfo);
|
||||
if (!isBrainPinValid(engineConfiguration->alternatorControlPin))
|
||||
return;
|
||||
|
||||
|
|
|
@ -10,31 +10,21 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
void initAlternatorCtrl();
|
||||
#include "engine_module.h"
|
||||
#include "closed_loop_controller.h"
|
||||
|
||||
void setAltPFactor(float p);
|
||||
void setAltIFactor(float p);
|
||||
void setAltDFactor(float p);
|
||||
void showAltInfo(void);
|
||||
void initAlternatorCtrl();
|
||||
|
||||
class AlternatorController : public EngineModule, public ClosedLoopController<float, percent_t> {
|
||||
public:
|
||||
AlternatorController();
|
||||
|
||||
void pidReset();
|
||||
|
||||
// EngineModule implementation
|
||||
void onFastCallback() override;
|
||||
void onConfigurationChange(engine_configuration_s const * previousConfiguration) override;
|
||||
void onConfigurationChange(engine_configuration_s const* previousConfiguration) override;
|
||||
|
||||
// ClosedLoopController implementation
|
||||
expected<float> getSetpoint() override;
|
||||
protected:
|
||||
expected<float> observePlant() override;
|
||||
expected<percent_t> getOpenLoop(float setpoint) override;
|
||||
expected<percent_t> getClosedLoop(float targetVoltage, float vBattVoltage) 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;
|
||||
|
||||
private:
|
||||
Pid alternatorPid;
|
||||
};
|
||||
|
||||
|
|
|
@ -785,29 +785,13 @@ static void setValue(const char *paramStr, const char *valueStr) {
|
|||
currentI++;
|
||||
}
|
||||
|
||||
#if EFI_ALTERNATOR_CONTROL
|
||||
if (strEqualCaseInsensitive(paramStr, "alt_t")) {
|
||||
if (valueI > 10) {
|
||||
engineConfiguration->alternatorControl.periodMs = valueI;
|
||||
}
|
||||
showAltInfo();
|
||||
} else if (strEqualCaseInsensitive(paramStr, "alt_offset")) {
|
||||
engineConfiguration->alternatorControl.offset = valueI;
|
||||
} else if (strEqualCaseInsensitive(paramStr, "alt_p")) {
|
||||
setAltPFactor(valueF);
|
||||
} else
|
||||
#endif // EFI_ALTERNATOR_CONTROL
|
||||
|
||||
if (strEqualCaseInsensitive(paramStr, "warning_period")) {
|
||||
engineConfiguration->warningPeriod = valueI;
|
||||
} else if (strEqualCaseInsensitive(paramStr, "dwell")) {
|
||||
setConstantDwell(valueF);
|
||||
} else if (strEqualCaseInsensitive(paramStr, CMD_ENGINESNIFFERRPMTHRESHOLD)) {
|
||||
engineConfiguration->engineSnifferRpmThreshold = valueI;
|
||||
// migrate to new laucnh fields?
|
||||
// } else if (strEqualCaseInsensitive(paramStr, "step1rpm")) {
|
||||
// engineConfiguration->step1rpm = valueI;
|
||||
// } else if (strEqualCaseInsensitive(paramStr, "step1timing")) {
|
||||
// engineConfiguration->step1timing = valueI;
|
||||
} else if (strEqualCaseInsensitive(paramStr, "tps_max")) {
|
||||
engineConfiguration->tpsMax = valueI;
|
||||
} else if (strEqualCaseInsensitive(paramStr, "tps_min")) {
|
||||
|
|
Loading…
Reference in New Issue