mirror of https://github.com/rusefi/rusefi-1.git
145 lines
4.3 KiB
C++
145 lines
4.3 KiB
C++
/**
|
|
* @file alternator_controller.cpp
|
|
* @brief alternator controller - some newer vehicles control alternator with ECU
|
|
*
|
|
* @date Apr 6, 2014
|
|
* @author Dmitry Sidin
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
|
*/
|
|
|
|
#include "pch.h"
|
|
|
|
#if EFI_ALTERNATOR_CONTROL
|
|
#include "alternator_controller.h"
|
|
#include "efi_pid.h"
|
|
#include "local_version_holder.h"
|
|
#include "periodic_task.h"
|
|
|
|
#if defined(HAS_OS_ACCESS)
|
|
#error "Unexpected OS ACCESS HERE"
|
|
#endif /* HAS_OS_ACCESS */
|
|
|
|
static SimplePwm alternatorControl("alt");
|
|
static Pid alternatorPid(&persistentState.persistentConfiguration.engineConfiguration.alternatorControl);
|
|
|
|
static percent_t currentAltDuty;
|
|
|
|
static bool currentPlainOnOffState = false;
|
|
static bool shouldResetPid = false;
|
|
|
|
static void pidReset() {
|
|
alternatorPid.reset();
|
|
}
|
|
|
|
void AlternatorController::onFastCallback() {
|
|
if (!isBrainPinValid(engineConfiguration->alternatorControlPin)) {
|
|
return;
|
|
}
|
|
|
|
#if ! EFI_UNIT_TEST
|
|
if (shouldResetPid) {
|
|
pidReset();
|
|
shouldResetPid = false;
|
|
}
|
|
#endif
|
|
|
|
// 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 */
|
|
|
|
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;
|
|
}
|
|
|
|
auto vBatt = Sensor::get(SensorType::BatteryVoltage);
|
|
float targetVoltage = engineConfiguration->targetVBatt;
|
|
|
|
// todo: I am not aware of a SINGLE person to use this onOffAlternatorLogic
|
|
if (engineConfiguration->onOffAlternatorLogic) {
|
|
if (!vBatt) {
|
|
// Somehow battery voltage isn't valid, disable alternator control
|
|
enginePins.alternatorPin.setValue(false);
|
|
}
|
|
|
|
float h = 0.1;
|
|
bool newState = (vBatt.Value < targetVoltage - h) || (currentPlainOnOffState && vBatt.Value < targetVoltage);
|
|
enginePins.alternatorPin.setValue(newState);
|
|
currentPlainOnOffState = newState;
|
|
#if EFI_TUNER_STUDIO
|
|
engine->outputChannels.alternatorOnOff = newState;
|
|
#endif /* EFI_TUNER_STUDIO */
|
|
|
|
return;
|
|
}
|
|
|
|
if (!vBatt) {
|
|
// Somehow battery voltage isn't valid, disable alternator control
|
|
alternatorPid.reset();
|
|
alternatorControl.setSimplePwmDutyCycle(0);
|
|
} else {
|
|
currentAltDuty = alternatorPid.getOutput(targetVoltage, vBatt.Value, FAST_CALLBACK_PERIOD_MS / 1000.0f);
|
|
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));
|
|
}
|
|
}
|
|
|
|
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);
|
|
pidReset();
|
|
showAltInfo();
|
|
}
|
|
|
|
void onConfigurationChangeAlternatorCallback(engine_configuration_s *previousConfiguration) {
|
|
shouldResetPid = !alternatorPid.isSame(&previousConfiguration->alternatorControl);
|
|
}
|
|
|
|
void initAlternatorCtrl() {
|
|
addConsoleAction("altinfo", showAltInfo);
|
|
if (!isBrainPinValid(engineConfiguration->alternatorControlPin))
|
|
return;
|
|
|
|
if (!engineConfiguration->onOffAlternatorLogic) {
|
|
startSimplePwm(&alternatorControl,
|
|
"Alternator control",
|
|
&engine->executor,
|
|
&enginePins.alternatorPin,
|
|
engineConfiguration->alternatorPwmFrequency, 0);
|
|
}
|
|
}
|
|
|
|
// todo: start invoking this method like 'startVvtControlPins'
|
|
void startAlternatorPin(void) {
|
|
|
|
}
|
|
|
|
void stopAlternatorPin(void) {
|
|
// todo: implementation!
|
|
}
|
|
|
|
#endif /* EFI_ALTERNATOR_CONTROL */
|