2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @file alternatorController.cpp
|
2016-02-25 14:01:37 -08:00
|
|
|
* @brief alternator controller - some newer vehicles control alternator with ECU
|
2015-07-10 06:01:56 -07:00
|
|
|
*
|
|
|
|
* @date Apr 6, 2014
|
|
|
|
* @author Dmitry Sidin
|
2018-01-20 17:55:31 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2018
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "engine.h"
|
|
|
|
#include "rpm_calculator.h"
|
|
|
|
#include "alternatorController.h"
|
|
|
|
#include "voltage.h"
|
|
|
|
#include "pid.h"
|
2016-01-22 10:02:51 -08:00
|
|
|
#include "LocalVersionHolder.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2016-01-20 20:03:03 -08:00
|
|
|
#if EFI_ALTERNATOR_CONTROL || defined(__DOXYGEN__)
|
2017-01-02 11:03:17 -08:00
|
|
|
#include "pwm_generator.h"
|
|
|
|
#include "pin_repository.h"
|
|
|
|
#include "tunerstudio_configuration.h"
|
2016-01-20 20:03:03 -08:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
EXTERN_ENGINE
|
|
|
|
;
|
|
|
|
|
|
|
|
static Logging *logger;
|
|
|
|
|
2019-01-09 05:50:51 -08:00
|
|
|
static SimplePwm alternatorControl("alt");
|
2016-01-20 20:03:03 -08:00
|
|
|
static pid_s *altPidS = &persistentState.persistentConfiguration.engineConfiguration.alternatorControl;
|
2017-05-29 20:15:07 -07:00
|
|
|
static Pid altPid(altPidS);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
static THD_WORKING_AREA(alternatorControlThreadStack, UTILITY_THREAD_STACK_SIZE);
|
|
|
|
|
2017-09-21 18:14:50 -07:00
|
|
|
static percent_t currentAltDuty;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2018-11-16 04:40:06 -08:00
|
|
|
#if EFI_TUNER_STUDIO || defined(__DOXYGEN__)
|
2016-01-22 10:02:51 -08:00
|
|
|
extern TunerStudioOutputChannels tsOutputChannels;
|
2018-11-16 04:40:06 -08:00
|
|
|
#endif /* EFI_TUNER_STUDIO */
|
2016-01-22 10:02:51 -08:00
|
|
|
|
2016-02-25 14:01:37 -08:00
|
|
|
static bool currentPlainOnOffState = false;
|
2016-09-15 20:01:48 -07:00
|
|
|
static bool shouldResetPid = false;
|
2016-02-25 14:01:37 -08:00
|
|
|
|
2017-04-10 19:07:51 -07:00
|
|
|
static void pidReset(void) {
|
|
|
|
altPid.reset();
|
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
static msg_t AltCtrlThread(int param) {
|
2016-01-22 10:02:51 -08:00
|
|
|
UNUSED(param);
|
2015-07-10 06:01:56 -07:00
|
|
|
chRegSetThreadName("AlternatorController");
|
|
|
|
while (true) {
|
2016-01-22 10:02:51 -08:00
|
|
|
#if ! EFI_UNIT_TEST || defined(__DOXYGEN__)
|
2016-09-15 20:01:48 -07:00
|
|
|
if (shouldResetPid) {
|
2017-04-10 19:07:51 -07:00
|
|
|
pidReset();
|
2017-02-12 17:05:02 -08:00
|
|
|
shouldResetPid = false;
|
2016-09-15 20:01:48 -07:00
|
|
|
}
|
2016-01-22 10:02:51 -08:00
|
|
|
#endif
|
|
|
|
|
2017-05-28 19:32:32 -07:00
|
|
|
altPid.sleep();
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2017-02-12 18:04:18 -08:00
|
|
|
if (engineConfiguration->debugMode == DBG_ALTERNATOR_PID) {
|
2017-02-12 17:05:02 -08:00
|
|
|
// this block could be executed even in on/off alternator control mode
|
|
|
|
// but at least we would reflect latest state
|
2018-11-16 04:40:06 -08:00
|
|
|
#if EFI_TUNER_STUDIO || defined(__DOXYGEN__)
|
2017-02-12 17:05:02 -08:00
|
|
|
altPid.postState(&tsOutputChannels);
|
2018-11-16 04:40:06 -08:00
|
|
|
#endif /* EFI_TUNER_STUDIO */
|
2017-02-12 17:05:02 -08:00
|
|
|
}
|
|
|
|
|
2016-01-31 16:01:34 -08:00
|
|
|
// todo: migrate this to FSIO
|
2019-01-21 17:33:21 -08:00
|
|
|
bool alternatorShouldBeEnabledAtCurrentRpm = GET_RPM_VALUE > engineConfiguration->cranking.rpm;
|
2016-01-31 16:01:34 -08:00
|
|
|
engine->isAlternatorControlEnabled = CONFIG(isAlternatorControlEnabled) && alternatorShouldBeEnabledAtCurrentRpm;
|
|
|
|
|
|
|
|
if (!engine->isAlternatorControlEnabled) {
|
2016-07-02 16:01:27 -07:00
|
|
|
// we need to avoid accumulating iTerm while engine is not running
|
2017-04-10 19:07:51 -07:00
|
|
|
pidReset();
|
2016-01-31 16:01:34 -08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-05-15 20:33:22 -07:00
|
|
|
float vBatt = getVBatt(PASS_ENGINE_PARAMETER_SIGNATURE);
|
2016-02-25 14:01:37 -08:00
|
|
|
float targetVoltage = engineConfiguration->targetVBatt;
|
|
|
|
|
2019-01-09 19:57:33 -08:00
|
|
|
if (CONFIGB(onOffAlternatorLogic)) {
|
2016-02-25 14:01:37 -08:00
|
|
|
float h = 0.1;
|
|
|
|
bool newState = (vBatt < targetVoltage - h) || (currentPlainOnOffState && vBatt < targetVoltage);
|
2016-09-13 21:03:14 -07:00
|
|
|
enginePins.alternatorPin.setValue(newState);
|
2016-02-25 14:01:37 -08:00
|
|
|
currentPlainOnOffState = newState;
|
2017-02-12 18:04:18 -08:00
|
|
|
if (engineConfiguration->debugMode == DBG_ALTERNATOR_PID) {
|
2018-11-16 04:40:06 -08:00
|
|
|
#if EFI_TUNER_STUDIO || defined(__DOXYGEN__)
|
2016-02-25 14:01:37 -08:00
|
|
|
tsOutputChannels.debugIntField1 = newState;
|
2018-11-16 04:40:06 -08:00
|
|
|
#endif /* EFI_TUNER_STUDIO */
|
2016-02-25 14:01:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-22 14:03:31 -08:00
|
|
|
currentAltDuty = altPid.getValue(targetVoltage, vBatt);
|
2019-01-09 19:57:33 -08:00
|
|
|
if (CONFIGB(isVerboseAlternator)) {
|
2018-01-23 09:05:14 -08:00
|
|
|
scheduleMsg(logger, "alt duty: %.2f/vbatt=%.2f/p=%.2f/i=%.2f/d=%.2f int=%.2f", currentAltDuty, vBatt,
|
2015-07-10 06:01:56 -07:00
|
|
|
altPid.getP(), altPid.getI(), altPid.getD(), altPid.getIntegration());
|
|
|
|
}
|
|
|
|
|
2016-01-22 10:02:51 -08:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
alternatorControl.setSimplePwmDutyCycle(currentAltDuty / 100);
|
|
|
|
}
|
|
|
|
#if defined __GNUC__
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void showAltInfo(void) {
|
|
|
|
scheduleMsg(logger, "alt=%s @%s t=%dms", boolToString(engineConfiguration->isAlternatorControlEnabled),
|
2019-01-09 19:57:33 -08:00
|
|
|
hwPortname(CONFIGB(alternatorControlPin)),
|
2017-05-28 19:32:32 -07:00
|
|
|
engineConfiguration->alternatorControl.period);
|
2018-01-23 09:05:14 -08:00
|
|
|
scheduleMsg(logger, "p=%.2f/i=%.2f/d=%.2f offset=%.2f", engineConfiguration->alternatorControl.pFactor,
|
2016-02-05 12:02:36 -08:00
|
|
|
0, 0, engineConfiguration->alternatorControl.offset); // todo: i & d
|
2018-01-23 09:05:14 -08:00
|
|
|
scheduleMsg(logger, "vbatt=%.2f/duty=%.2f/target=%.2f", getVBatt(PASS_ENGINE_PARAMETER_SIGNATURE), currentAltDuty,
|
2015-07-10 06:01:56 -07:00
|
|
|
engineConfiguration->targetVBatt);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setAltPFactor(float p) {
|
2015-11-11 20:01:18 -08:00
|
|
|
engineConfiguration->alternatorControl.pFactor = p;
|
2018-01-23 09:05:14 -08:00
|
|
|
scheduleMsg(logger, "setAltPid: %.2f", p);
|
2017-04-10 19:07:51 -07:00
|
|
|
pidReset();
|
2015-07-10 06:01:56 -07:00
|
|
|
showAltInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void applyAlternatorPinState(PwmConfig *state, int stateIndex) {
|
2018-07-25 20:03:04 -07:00
|
|
|
efiAssertVoid(CUSTOM_ERR_6643, stateIndex < PWM_PHASE_MAX_COUNT, "invalid stateIndex");
|
2018-09-10 19:10:55 -07:00
|
|
|
efiAssertVoid(CUSTOM_IDLE_WAVE_CNT, state->multiWave.waveCount == 1, "invalid idle waveCount");
|
2015-07-10 06:01:56 -07:00
|
|
|
OutputPin *output = state->outputPins[0];
|
2018-12-25 07:13:00 -08:00
|
|
|
int value = state->multiWave.getChannelState(/*channelIndex*/0, stateIndex);
|
2016-09-12 17:02:56 -07:00
|
|
|
/**
|
|
|
|
* 'engine->isAlternatorControlEnabled' would be false is RPM is too low
|
|
|
|
*/
|
2016-01-31 16:01:34 -08:00
|
|
|
if (!value || engine->isAlternatorControlEnabled)
|
2015-07-10 06:01:56 -07:00
|
|
|
output->setValue(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setDefaultAlternatorParameters(void) {
|
|
|
|
engineConfiguration->alternatorOffAboveTps = 120;
|
|
|
|
|
2019-01-09 19:57:33 -08:00
|
|
|
CONFIGB(alternatorControlPin) = GPIO_UNASSIGNED;
|
|
|
|
CONFIGB(alternatorControlPinMode) = OM_DEFAULT;
|
2015-07-10 06:01:56 -07:00
|
|
|
engineConfiguration->targetVBatt = 14;
|
|
|
|
|
2016-02-05 12:02:36 -08:00
|
|
|
engineConfiguration->alternatorControl.offset = 0;
|
2015-11-11 20:01:18 -08:00
|
|
|
engineConfiguration->alternatorControl.pFactor = 30;
|
2017-05-28 19:32:32 -07:00
|
|
|
engineConfiguration->alternatorControl.period = 100;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2016-09-15 20:01:48 -07:00
|
|
|
void onConfigurationChangeAlternatorCallback(engine_configuration_s *previousConfiguration) {
|
2017-05-28 19:32:32 -07:00
|
|
|
shouldResetPid = !altPid.isSame(&previousConfiguration->alternatorControl);
|
2016-09-15 20:01:48 -07:00
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
void initAlternatorCtrl(Logging *sharedLogger) {
|
|
|
|
logger = sharedLogger;
|
|
|
|
addConsoleAction("altinfo", showAltInfo);
|
2019-01-09 19:57:33 -08:00
|
|
|
if (CONFIGB(alternatorControlPin) == GPIO_UNASSIGNED)
|
2015-07-10 06:01:56 -07:00
|
|
|
return;
|
|
|
|
|
2019-01-09 19:57:33 -08:00
|
|
|
if (CONFIGB(onOffAlternatorLogic)) {
|
|
|
|
enginePins.alternatorPin.initPin("on/off alternator", CONFIGB(alternatorControlPin));
|
2016-02-25 14:01:37 -08:00
|
|
|
|
|
|
|
} else {
|
2019-01-09 05:50:51 -08:00
|
|
|
startSimplePwmExt(&alternatorControl,
|
|
|
|
"Alternator control",
|
|
|
|
&engine->executor,
|
2019-01-09 19:57:33 -08:00
|
|
|
CONFIGB(alternatorControlPin),
|
2016-09-13 21:03:14 -07:00
|
|
|
&enginePins.alternatorPin,
|
2016-07-16 23:03:46 -07:00
|
|
|
engineConfiguration->alternatorPwmFrequency, 0.1, applyAlternatorPinState);
|
2016-02-25 14:01:37 -08:00
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
chThdCreateStatic(alternatorControlThreadStack, sizeof(alternatorControlThreadStack), LOWPRIO,
|
2018-12-27 06:40:40 -08:00
|
|
|
(tfunc_t)(void*) AltCtrlThread, NULL);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
2016-01-20 20:03:03 -08:00
|
|
|
|
|
|
|
#endif /* EFI_ALTERNATOR_CONTROL */
|