rusefi/firmware/controllers/actuators/boost_control.cpp

249 lines
6.2 KiB
C++
Raw Normal View History

/*
* boost_control.cpp
*
* Created on: 13. des. 2019
* Author: Ola Ruud
*/
#include "global.h"
#if EFI_BOOST_CONTROL
#if EFI_TUNER_STUDIO
2020-05-25 10:02:05 -07:00
#include "tunerstudio_outputs.h"
#endif /* EFI_TUNER_STUDIO */
#include "engine.h"
#include "boost_control.h"
#include "sensor.h"
#include "map.h"
#include "pin_repository.h"
2020-04-26 14:40:12 -07:00
#include "pwm_generator_logic.h"
#include "pid_auto_tune.h"
#include "electronic_throttle.h"
#define NO_PIN_PERIOD 500
#if defined(HAS_OS_ACCESS)
#error "Unexpected OS ACCESS HERE"
#endif
EXTERN_ENGINE;
static Logging *logger;
static boostOpenLoop_Map3D_t boostMapOpen("boostmapopen");
static boostOpenLoop_Map3D_t boostMapClosed("boostmapclosed");
static SimplePwm boostPwmControl("boost");
void BoostController::init(SimplePwm* pwm, const ValueProvider3D* openLoopMap, const ValueProvider3D* closedLoopTargetMap, pid_s* pidParams) {
m_pwm = pwm;
m_openLoopMap = openLoopMap;
m_closedLoopTargetMap = closedLoopTargetMap;
m_pid.initPidClass(pidParams);
}
void BoostController::reset() {
m_shouldResetPid = true;
}
void BoostController::onConfigurationChange(pid_s* previousConfiguration) {
if (!m_pid.isSame(previousConfiguration)) {
m_shouldResetPid = true;
}
}
int BoostController::getPeriodMs() {
return GET_PERIOD_LIMITED(&engineConfiguration->boostPid);
}
expected<float> BoostController::observePlant() const {
float map = getMap(PASS_ENGINE_PARAMETER_SIGNATURE);
2020-03-23 20:06:52 -07:00
if (cisnan(map)) {
return unexpected;
}
2020-02-04 17:17:31 -08:00
return map;
}
expected<float> BoostController::getSetpoint() const {
float rpm = GET_RPM();
auto tps = Sensor::get(SensorType::DriverThrottleIntent);
2020-02-04 17:17:31 -08:00
if (!tps) {
return unexpected;
}
if (!m_closedLoopTargetMap) {
return unexpected;
}
return m_closedLoopTargetMap->getValue(rpm / RPM_1_BYTE_PACKING_MULT, tps.Value / TPS_1_BYTE_PACKING_MULT);
}
expected<percent_t> BoostController::getOpenLoop(float target) const {
// Boost control open loop doesn't care about target - only MAP/RPM
UNUSED(target);
float rpm = GET_RPM();
auto tps = Sensor::get(SensorType::DriverThrottleIntent);
if (!tps) {
return unexpected;
}
if (!m_openLoopMap) {
return unexpected;
}
2020-02-04 17:17:31 -08:00
percent_t openLoop = m_openLoopMap->getValue(rpm / RPM_1_BYTE_PACKING_MULT, tps.Value / TPS_1_BYTE_PACKING_MULT);
2020-02-04 17:17:31 -08:00
#if EFI_TUNER_STUDIO
if (engineConfiguration->debugMode == DBG_BOOST) {
tsOutputChannels.debugFloatField1 = openLoop;
}
#endif
return openLoop;
}
2020-02-04 17:17:31 -08:00
expected<percent_t> BoostController::getClosedLoop(float target, float manifoldPressure) {
// If we're in open loop only mode, make no closed loop correction.
if (engineConfiguration->boostType != CLOSED_LOOP) {
return 0;
2020-03-26 16:22:14 -07:00
}
// Reset PID if requested
if (m_shouldResetPid) {
m_pid.reset();
m_shouldResetPid = false;
2020-02-04 17:17:31 -08:00
}
// If the engine isn't running, don't correct.
if (GET_RPM() == 0) {
m_pid.reset();
return 0;
}
float closedLoop = m_pid.getOutput(target, manifoldPressure);
#if EFI_TUNER_STUDIO
if (engineConfiguration->debugMode == DBG_BOOST) {
m_pid.postState(&tsOutputChannels);
tsOutputChannels.debugFloatField2 = closedLoop;
}
#endif /* EFI_TUNER_STUDIO */
return closedLoop;
}
void BoostController::setOutput(expected<float> output) {
// TODO: hook up safe duty cycle
float duty = PERCENT_TO_DUTY(output.value_or(/*CONFIG(boostControlSafeDutyCycle)*/ 0));
if (m_pwm) {
m_pwm->setSimplePwmDutyCycle(duty);
}
setEtbWastegatePosition(duty PASS_ENGINE_PARAMETER_SUFFIX);
}
void BoostController::PeriodicTask() {
m_pid.iTermMin = -50;
m_pid.iTermMax = 50;
update();
}
BoostController boostController;
void setDefaultBoostParameters(DECLARE_CONFIG_PARAMETER_SIGNATURE) {
engineConfiguration->boostPwmFrequency = 55;
engineConfiguration->boostPid.offset = 0;
engineConfiguration->boostPid.pFactor = 0.5;
engineConfiguration->boostPid.iFactor = 0.3;
engineConfiguration->boostPid.periodMs = 100;
engineConfiguration->boostPid.maxValue = 99;
engineConfiguration->boostPid.minValue = -99;
engineConfiguration->boostControlPin = GPIO_UNASSIGNED;
engineConfiguration->boostControlPinMode = OM_DEFAULT;
setLinearCurve(config->boostRpmBins, 0, 8000 / RPM_1_BYTE_PACKING_MULT, 1);
setLinearCurve(config->boostTpsBins, 0, 100 / TPS_1_BYTE_PACKING_MULT, 1);
for (int loadIndex = 0; loadIndex < BOOST_LOAD_COUNT; loadIndex++) {
for (int rpmIndex = 0; rpmIndex < BOOST_RPM_COUNT; rpmIndex++) {
config->boostTableOpenLoop[loadIndex][rpmIndex] = config->boostTpsBins[loadIndex];
2020-02-04 17:17:31 -08:00
config->boostTableClosedLoop[loadIndex][rpmIndex] = config->boostTpsBins[loadIndex];
}
}
2020-11-22 15:30:19 -08:00
// Defaults for ETB-style wastegate actuator
CONFIG(etbWastegatePid).pFactor = 1;
CONFIG(etbWastegatePid).minValue = -60;
CONFIG(etbWastegatePid).maxValue = 60;
}
void startBoostPin() {
2020-03-23 20:06:52 -07:00
#if !EFI_UNIT_TEST
2020-11-22 15:30:19 -08:00
// Only init if a pin is set, no need to start PWM without a pin
if (CONFIG(boostControlPin) == GPIO_UNASSIGNED){
return;
}
2020-02-04 17:17:31 -08:00
startSimplePwm(
2020-02-04 17:17:31 -08:00
&boostPwmControl,
"Boost",
&engine->executor,
&enginePins.boostPin,
engineConfiguration->boostPwmFrequency,
0.5f
2020-02-04 17:17:31 -08:00
);
2020-03-23 20:06:52 -07:00
#endif /* EFI_UNIT_TEST */
}
void stopBoostPin() {
2020-03-23 20:15:44 -07:00
#if !EFI_UNIT_TEST
brain_pin_markUnused(activeConfiguration.boostControlPin);
2020-03-23 20:15:44 -07:00
#endif /* EFI_UNIT_TEST */
}
void onConfigurationChangeBoostCallback(engine_configuration_s *previousConfiguration) {
boostController.onConfigurationChange(&previousConfiguration->boostPid);
}
2020-02-04 17:17:31 -08:00
void initBoostCtrl(Logging *sharedLogger DECLARE_ENGINE_PARAMETER_SUFFIX) {
2020-11-22 15:30:19 -08:00
if (!CONFIG(isBoostControlEnabled)) {
return;
}
bool hasAnyEtbWastegate = false;
for (size_t i = 0; i < efi::size(CONFIG(etbFunctions)); i++) {
hasAnyEtbWastegate |= CONFIG(etbFunctions)[i] == ETB_Wastegate;
}
// If we have neither a boost PWM pin nor ETB wastegate, nothing more to do
if ((CONFIG(boostControlPin) == GPIO_UNASSIGNED)
&& !hasAnyEtbWastegate) {
2020-02-04 17:17:31 -08:00
return;
}
logger = sharedLogger;
// Set up open & closed loop tables
boostMapOpen.init(config->boostTableOpenLoop, config->boostTpsBins, config->boostRpmBins);
boostMapClosed.init(config->boostTableClosedLoop, config->boostTpsBins, config->boostRpmBins);
// Set up boost controller instance
boostController.init(&boostPwmControl, &boostMapOpen, &boostMapClosed, &engineConfiguration->boostPid);
2020-03-23 20:51:51 -07:00
#if !EFI_UNIT_TEST
startBoostPin();
boostController.Start();
2020-03-23 20:06:52 -07:00
#endif
}
#endif