2020-02-02 00:56:21 -08:00
|
|
|
/*
|
|
|
|
* boost_control.cpp
|
|
|
|
*
|
|
|
|
* Created on: 13. des. 2019
|
|
|
|
* Author: Ola Ruud
|
|
|
|
*/
|
2021-07-25 22:05:17 -07:00
|
|
|
#include "pch.h"
|
2020-02-02 00:56:21 -08:00
|
|
|
|
|
|
|
#if EFI_BOOST_CONTROL
|
|
|
|
|
|
|
|
#include "boost_control.h"
|
2020-10-18 18:57:04 -07:00
|
|
|
#include "electronic_throttle.h"
|
2024-05-15 09:03:39 -07:00
|
|
|
#include "gppwm_channel_reader.h"
|
2020-10-18 18:57:04 -07:00
|
|
|
|
2020-02-02 00:56:21 -08:00
|
|
|
#define NO_PIN_PERIOD 500
|
|
|
|
|
|
|
|
#if defined(HAS_OS_ACCESS)
|
|
|
|
#error "Unexpected OS ACCESS HERE"
|
|
|
|
#endif
|
|
|
|
|
2024-07-30 03:51:29 -07:00
|
|
|
namespace {
|
2024-08-23 05:57:11 -07:00
|
|
|
Map3D<BOOST_RPM_COUNT, BOOST_LOAD_COUNT, uint8_t, uint8_t, uint8_t> boostMapOpen{"bo"};
|
|
|
|
Map3D<BOOST_RPM_COUNT, BOOST_LOAD_COUNT, uint8_t, uint8_t, uint8_t> boostMapClosed{"bc"};
|
2024-07-30 03:51:29 -07:00
|
|
|
Map2D<BOOST_CURVE_SIZE, float, float> boostCltCorr { "clt" };
|
|
|
|
Map2D<BOOST_CURVE_SIZE, float, float> boostIatCorr { "iat" };
|
2024-07-31 05:10:09 -07:00
|
|
|
Map2D<BOOST_CURVE_SIZE, float, float> boostCltAdder { "clt (adder)" };
|
|
|
|
Map2D<BOOST_CURVE_SIZE, float, float> boostIatAdder { "iat (adder)" };
|
2024-08-23 05:57:11 -07:00
|
|
|
SimplePwm boostPwmControl("boost");
|
2024-07-30 03:51:29 -07:00
|
|
|
}
|
2020-02-02 00:56:21 -08:00
|
|
|
|
2024-07-30 03:51:29 -07:00
|
|
|
void BoostController::init(
|
|
|
|
IPwm* const pwm,
|
|
|
|
const ValueProvider3D* const openLoopMap,
|
|
|
|
const ValueProvider3D* const closedLoopTargetMap,
|
|
|
|
const ValueProvider2D& cltMultiplierProvider,
|
|
|
|
const ValueProvider2D& iatMultiplierProvider,
|
2024-07-31 05:10:09 -07:00
|
|
|
const ValueProvider2D& cltAdderProvider,
|
|
|
|
const ValueProvider2D& iatAdderProvider,
|
2024-07-30 03:51:29 -07:00
|
|
|
pid_s* const pidParams
|
|
|
|
) {
|
2020-05-06 05:40:42 -07:00
|
|
|
m_pwm = pwm;
|
|
|
|
m_openLoopMap = openLoopMap;
|
|
|
|
m_closedLoopTargetMap = closedLoopTargetMap;
|
2024-07-30 03:51:29 -07:00
|
|
|
m_cltBoostCorrMap = &cltMultiplierProvider;
|
|
|
|
m_iatBoostCorrMap = &iatMultiplierProvider;
|
2024-07-31 05:10:09 -07:00
|
|
|
m_cltBoostAdderMap = &cltAdderProvider;
|
|
|
|
m_iatBoostAdderMap = &iatAdderProvider;
|
2020-02-02 00:56:21 -08:00
|
|
|
|
2020-05-06 05:40:42 -07:00
|
|
|
m_pid.initPidClass(pidParams);
|
2022-07-14 10:03:08 -07:00
|
|
|
resetLua();
|
2023-09-26 10:39:43 -07:00
|
|
|
|
|
|
|
hasInitBoost = true;
|
2022-07-14 10:03:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void BoostController::resetLua() {
|
|
|
|
luaTargetAdd = 0;
|
|
|
|
luaTargetMult = 1;
|
2022-12-19 09:05:06 -08:00
|
|
|
luaOpenLoopAdd = 0;
|
2020-05-06 05:40:42 -07:00
|
|
|
}
|
|
|
|
|
2023-09-26 10:39:43 -07:00
|
|
|
void BoostController::onConfigurationChange(engine_configuration_s const * previousConfig) {
|
2024-08-01 15:30:05 -07:00
|
|
|
#if EFI_PROD_CODE
|
|
|
|
initBoostCtrl();
|
|
|
|
#endif
|
|
|
|
|
2024-05-03 22:10:42 -07:00
|
|
|
if (!previousConfig || !m_pid.isSame(&previousConfig->boostPid)) {
|
2020-05-06 05:40:42 -07:00
|
|
|
m_shouldResetPid = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-19 18:06:09 -07:00
|
|
|
expected<float> BoostController::observePlant() {
|
|
|
|
expected<float> map = Sensor::get(SensorType::Map);
|
2023-10-19 18:22:59 -07:00
|
|
|
if (!map.Valid && engineConfiguration->boostType != CLOSED_LOOP) {
|
|
|
|
// if we're in open loop only let's somewhat operate even without valid Map sensor
|
|
|
|
map = 0;
|
|
|
|
}
|
2023-10-19 18:06:09 -07:00
|
|
|
isPlantValid = map.Valid;
|
|
|
|
return map;
|
2020-05-06 05:40:42 -07:00
|
|
|
}
|
2020-02-02 00:56:21 -08:00
|
|
|
|
2021-11-23 12:52:43 -08:00
|
|
|
expected<float> BoostController::getSetpoint() {
|
2020-11-25 04:27:24 -08:00
|
|
|
// If we're in open loop only mode, disregard any target computation.
|
|
|
|
// Open loop needs to work even in case of invalid closed loop config
|
2021-11-24 10:08:24 -08:00
|
|
|
isNotClosedLoop = engineConfiguration->boostType != CLOSED_LOOP;
|
|
|
|
if (isNotClosedLoop) {
|
2022-06-29 00:27:51 -07:00
|
|
|
boostControllerClosedLoopPart = 0;
|
|
|
|
return (float)boostControllerClosedLoopPart;
|
2020-11-25 04:27:24 -08:00
|
|
|
}
|
|
|
|
|
2022-01-20 19:22:52 -08:00
|
|
|
float rpm = Sensor::getOrZero(SensorType::Rpm);
|
2020-02-02 00:56:21 -08:00
|
|
|
|
2023-01-16 17:50:45 -08:00
|
|
|
auto driverIntent = Sensor::get(SensorType::DriverThrottleIntent);
|
|
|
|
isTpsInvalid = !driverIntent.Valid;
|
2020-02-04 17:17:31 -08:00
|
|
|
|
2022-01-01 22:17:22 -08:00
|
|
|
if (isTpsInvalid) {
|
2020-05-06 05:40:42 -07:00
|
|
|
return unexpected;
|
|
|
|
}
|
|
|
|
|
2023-04-11 17:01:34 -07:00
|
|
|
efiAssert(ObdCode::OBD_PCM_Processor_Fault, m_closedLoopTargetMap != nullptr, "boost closed loop target", unexpected);
|
2020-02-02 00:56:21 -08:00
|
|
|
|
2023-05-03 11:04:40 -07:00
|
|
|
float target = m_closedLoopTargetMap->getValue(rpm, driverIntent.Value);
|
2023-11-05 08:25:46 -08:00
|
|
|
#if EFI_ENGINE_CONTROL
|
2023-05-03 11:04:40 -07:00
|
|
|
// Add any blends if configured
|
|
|
|
for (size_t i = 0; i < efi::size(config->boostClosedLoopBlends); i++) {
|
|
|
|
auto result = calculateBlend(config->boostClosedLoopBlends[i], rpm, driverIntent.Value);
|
|
|
|
|
|
|
|
engine->outputChannels.boostClosedLoopBlendParameter[i] = result.BlendParameter;
|
|
|
|
engine->outputChannels.boostClosedLoopBlendBias[i] = result.Bias;
|
|
|
|
engine->outputChannels.boostClosedLoopBlendOutput[i] = result.Value;
|
|
|
|
|
|
|
|
target += result.Value;
|
|
|
|
}
|
2023-11-05 08:25:46 -08:00
|
|
|
#endif //EFI_ENGINE_CONTROL
|
2023-05-03 11:04:40 -07:00
|
|
|
|
2024-07-31 05:10:09 -07:00
|
|
|
target *= luaTargetMult;
|
|
|
|
target += luaTargetAdd;
|
|
|
|
const std::optional<float> temperatureAdder = getBoostControlTargetTemperatureAdder();
|
|
|
|
if (temperatureAdder.has_value()) {
|
|
|
|
target += temperatureAdder.value();
|
|
|
|
}
|
|
|
|
return target;
|
2020-05-06 05:40:42 -07:00
|
|
|
}
|
2020-02-02 00:56:21 -08:00
|
|
|
|
2021-11-23 12:52:43 -08:00
|
|
|
expected<percent_t> BoostController::getOpenLoop(float target) {
|
2021-09-07 11:07:47 -07:00
|
|
|
// Boost control open loop doesn't care about target - only TPS/RPM
|
2020-05-06 05:40:42 -07:00
|
|
|
UNUSED(target);
|
2020-04-05 16:33:33 -07:00
|
|
|
|
2022-01-20 19:22:52 -08:00
|
|
|
float rpm = Sensor::getOrZero(SensorType::Rpm);
|
2024-05-15 09:03:39 -07:00
|
|
|
auto driverIntent = readGppwmChannel(engineConfiguration->boostOpenLoopYAxis);
|
2020-05-06 05:40:42 -07:00
|
|
|
|
2023-01-16 18:12:24 -08:00
|
|
|
isTpsInvalid = !driverIntent.Valid;
|
2021-11-23 12:52:43 -08:00
|
|
|
|
2022-01-01 22:17:22 -08:00
|
|
|
if (isTpsInvalid) {
|
2020-05-06 05:40:42 -07:00
|
|
|
return unexpected;
|
|
|
|
}
|
|
|
|
|
2023-04-11 17:01:34 -07:00
|
|
|
efiAssert(ObdCode::OBD_PCM_Processor_Fault, m_openLoopMap != nullptr, "boost open loop", unexpected);
|
2024-07-30 03:51:29 -07:00
|
|
|
efiAssert(ObdCode::OBD_PCM_Processor_Fault, m_cltBoostCorrMap != nullptr, "boost CLT multiplier", unexpected);
|
|
|
|
efiAssert(ObdCode::OBD_PCM_Processor_Fault, m_iatBoostCorrMap != nullptr, "boost IAT multiplier", unexpected);
|
2020-02-04 17:17:31 -08:00
|
|
|
|
2024-07-30 03:51:29 -07:00
|
|
|
percent_t openLoop = luaOpenLoopAdd + getBoostControlDutyCycleWithTemperatureCorrections(rpm, driverIntent.Value);
|
2023-05-03 11:04:40 -07:00
|
|
|
|
2023-11-05 08:25:46 -08:00
|
|
|
#if EFI_ENGINE_CONTROL
|
2023-05-03 11:04:40 -07:00
|
|
|
// Add any blends if configured
|
|
|
|
for (size_t i = 0; i < efi::size(config->boostOpenLoopBlends); i++) {
|
|
|
|
auto result = calculateBlend(config->boostOpenLoopBlends[i], rpm, driverIntent.Value);
|
|
|
|
|
|
|
|
engine->outputChannels.boostOpenLoopBlendParameter[i] = result.BlendParameter;
|
|
|
|
engine->outputChannels.boostOpenLoopBlendBias[i] = result.Bias;
|
|
|
|
engine->outputChannels.boostOpenLoopBlendOutput[i] = result.Value;
|
|
|
|
|
|
|
|
openLoop += result.Value;
|
|
|
|
}
|
2023-11-05 08:25:46 -08:00
|
|
|
#endif // EFI_ENGINE_CONTROL
|
2020-02-04 17:17:31 -08:00
|
|
|
|
2023-05-20 14:33:56 -07:00
|
|
|
// Add gear-based adder
|
|
|
|
auto gear = Sensor::getOrZero(SensorType::DetectedGear);
|
2023-05-20 14:41:04 -07:00
|
|
|
float gearAdder = engineConfiguration->gearBasedOpenLoopBoostAdder[static_cast<int>(gear) + 1];
|
2023-05-20 14:33:56 -07:00
|
|
|
openLoop += gearAdder;
|
|
|
|
|
2023-05-03 11:04:40 -07:00
|
|
|
openLoopPart = openLoop;
|
|
|
|
return openLoop;
|
2020-05-06 05:40:42 -07:00
|
|
|
}
|
2020-02-04 17:17:31 -08:00
|
|
|
|
2021-09-07 11:07:47 -07:00
|
|
|
percent_t BoostController::getClosedLoopImpl(float target, float manifoldPressure) {
|
2020-05-06 05:40:42 -07:00
|
|
|
// If we're in open loop only mode, make no closed loop correction.
|
2021-11-24 10:08:24 -08:00
|
|
|
isNotClosedLoop = engineConfiguration->boostType != CLOSED_LOOP;
|
|
|
|
if (isNotClosedLoop) {
|
2020-05-06 05:40:42 -07:00
|
|
|
return 0;
|
2020-03-26 16:22:14 -07:00
|
|
|
}
|
|
|
|
|
2020-05-06 05:40:42 -07:00
|
|
|
// Reset PID if requested
|
|
|
|
if (m_shouldResetPid) {
|
|
|
|
m_pid.reset();
|
|
|
|
m_shouldResetPid = false;
|
2020-02-04 17:17:31 -08:00
|
|
|
}
|
2020-02-02 00:56:21 -08:00
|
|
|
|
2020-05-06 05:40:42 -07:00
|
|
|
// If the engine isn't running, don't correct.
|
2022-01-20 19:22:52 -08:00
|
|
|
isZeroRpm = Sensor::getOrZero(SensorType::Rpm) == 0;
|
2022-01-01 22:17:22 -08:00
|
|
|
if (isZeroRpm) {
|
2020-05-06 05:40:42 -07:00
|
|
|
m_pid.reset();
|
|
|
|
return 0;
|
|
|
|
}
|
2020-02-02 00:56:21 -08:00
|
|
|
|
2021-11-23 12:52:43 -08:00
|
|
|
isBelowClosedLoopThreshold = manifoldPressure < engineConfiguration->minimumBoostClosedLoopMap;
|
|
|
|
if (isBelowClosedLoopThreshold) {
|
2021-08-27 14:54:08 -07:00
|
|
|
// We're below the CL threshold, inhibit CL for now
|
|
|
|
m_pid.reset();
|
2022-03-24 05:58:55 -07:00
|
|
|
return 0;
|
2021-08-27 14:54:08 -07:00
|
|
|
}
|
|
|
|
|
2023-09-07 12:32:21 -07:00
|
|
|
return m_pid.getOutput(target, manifoldPressure, FAST_CALLBACK_PERIOD_MS / 1000.0f);
|
2021-09-07 11:07:47 -07:00
|
|
|
}
|
|
|
|
|
2024-07-30 03:51:29 -07:00
|
|
|
float BoostController::getBoostControlDutyCycleWithTemperatureCorrections(
|
|
|
|
const float rpm,
|
|
|
|
const float driverIntent
|
|
|
|
) const {
|
|
|
|
float result = m_openLoopMap->getValue(rpm, driverIntent);
|
2024-07-31 05:10:09 -07:00
|
|
|
std::optional<float> cltBoostMultiplier = getBoostTemperatureCorrection(SensorType::Clt, *m_cltBoostCorrMap);
|
2024-07-30 03:51:29 -07:00
|
|
|
if (cltBoostMultiplier.has_value()) {
|
|
|
|
result *= cltBoostMultiplier.value();
|
|
|
|
}
|
2024-07-31 05:10:09 -07:00
|
|
|
std::optional<float> iatBoostMultiplier = getBoostTemperatureCorrection(SensorType::Iat, *m_iatBoostCorrMap);
|
2024-07-30 03:51:29 -07:00
|
|
|
if (iatBoostMultiplier.has_value()) {
|
|
|
|
result *= iatBoostMultiplier.value();
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2024-07-31 05:10:09 -07:00
|
|
|
std::optional<float> BoostController::getBoostControlTargetTemperatureAdder() const {
|
|
|
|
std::optional<float> result = getBoostTemperatureCorrection(SensorType::Clt, *m_cltBoostAdderMap);
|
|
|
|
const std::optional<float> iatBoostAdder = getBoostTemperatureCorrection(SensorType::Iat, *m_iatBoostAdderMap);
|
|
|
|
if (iatBoostAdder.has_value()) {
|
|
|
|
if (result.has_value()) {
|
|
|
|
result.value() += iatBoostAdder.value();
|
|
|
|
} else {
|
|
|
|
result = iatBoostAdder;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<float> BoostController::getBoostTemperatureCorrection(
|
2024-07-30 03:51:29 -07:00
|
|
|
const SensorType sensorType,
|
2024-07-31 05:10:09 -07:00
|
|
|
const ValueProvider2D& correctionCurve
|
2024-07-30 03:51:29 -07:00
|
|
|
) const {
|
|
|
|
const SensorResult temperature = Sensor::get(sensorType);
|
|
|
|
if (temperature.Valid) {
|
2024-07-31 05:10:09 -07:00
|
|
|
const std::optional<float> boostCorrection = correctionCurve.getValue(temperature.Value);
|
|
|
|
if (boostCorrection.has_value()) {
|
|
|
|
return std::make_optional<float>(boostCorrection.value());
|
2024-07-30 03:51:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-07 11:07:47 -07:00
|
|
|
expected<percent_t> BoostController::getClosedLoop(float target, float manifoldPressure) {
|
2022-06-29 00:13:35 -07:00
|
|
|
boostControllerClosedLoopPart = getClosedLoopImpl(target, manifoldPressure);
|
2022-03-24 05:58:55 -07:00
|
|
|
|
|
|
|
m_pid.postState(engine->outputChannels.boostStatus);
|
2020-05-06 05:40:42 -07:00
|
|
|
|
2022-06-29 00:27:51 -07:00
|
|
|
boostControlTarget = target;
|
2020-05-06 05:40:42 -07:00
|
|
|
|
2022-06-29 00:27:51 -07:00
|
|
|
return (float)boostControllerClosedLoopPart;
|
2020-02-02 00:56:21 -08:00
|
|
|
}
|
|
|
|
|
2020-05-06 05:40:42 -07:00
|
|
|
void BoostController::setOutput(expected<float> output) {
|
2024-04-06 06:04:42 -07:00
|
|
|
// this clamping is just for happier gauge #6339
|
|
|
|
boostOutput = clampPercentValue(output.value_or(engineConfiguration->boostControlSafeDutyCycle));
|
2021-09-07 11:07:47 -07:00
|
|
|
|
2022-01-11 17:47:50 -08:00
|
|
|
if (!engineConfiguration->isBoostControlEnabled) {
|
|
|
|
// If not enabled, force 0% output
|
2023-01-16 17:50:45 -08:00
|
|
|
boostOutput = 0;
|
2022-01-11 17:47:50 -08:00
|
|
|
}
|
|
|
|
|
2023-01-16 17:50:45 -08:00
|
|
|
float duty = PERCENT_TO_DUTY(boostOutput);
|
2020-11-25 18:14:06 -08:00
|
|
|
|
2020-05-06 05:40:42 -07:00
|
|
|
if (m_pwm) {
|
|
|
|
m_pwm->setSimplePwmDutyCycle(duty);
|
|
|
|
}
|
2020-10-18 18:57:04 -07:00
|
|
|
|
2023-11-05 08:25:46 -08:00
|
|
|
#if EFI_ELECTRONIC_THROTTLE_BODY
|
2023-01-16 13:14:01 -08:00
|
|
|
// inject wastegate position into DC controllers, pretty weird workflow to be honest
|
|
|
|
// todo: should it be DC controller pulling?
|
2023-01-16 17:50:45 -08:00
|
|
|
setEtbWastegatePosition(boostOutput);
|
2023-11-05 08:25:46 -08:00
|
|
|
#endif // EFI_ELECTRONIC_THROTTLE_BODY
|
2020-02-02 00:56:21 -08:00
|
|
|
}
|
|
|
|
|
2023-09-26 10:39:43 -07:00
|
|
|
void BoostController::onFastCallback() {
|
2023-01-22 04:40:42 -08:00
|
|
|
if (!hasInitBoost) {
|
2023-09-07 12:32:21 -07:00
|
|
|
return;
|
2023-01-22 04:40:42 -08:00
|
|
|
}
|
|
|
|
|
2023-09-07 12:32:21 -07:00
|
|
|
m_pid.iTermMin = -20;
|
|
|
|
m_pid.iTermMax = 20;
|
2020-05-06 05:40:42 -07:00
|
|
|
|
2023-01-16 17:50:45 -08:00
|
|
|
rpmTooLow = Sensor::getOrZero(SensorType::Rpm) < engineConfiguration->boostControlMinRpm;
|
|
|
|
tpsTooLow = Sensor::getOrZero(SensorType::Tps1) < engineConfiguration->boostControlMinTps;
|
|
|
|
mapTooLow = Sensor::getOrZero(SensorType::Map) < engineConfiguration->boostControlMinMap;
|
2022-07-27 23:45:16 -07:00
|
|
|
|
2024-01-04 17:15:15 -08:00
|
|
|
isBoostControlled = !(rpmTooLow || tpsTooLow || mapTooLow);
|
|
|
|
|
|
|
|
if (!isBoostControlled) {
|
2022-07-27 23:45:16 -07:00
|
|
|
// Passing unexpected will use the safe duty cycle configured by the user
|
|
|
|
setOutput(unexpected);
|
|
|
|
} else {
|
|
|
|
ClosedLoopController::update();
|
|
|
|
}
|
2020-02-02 00:56:21 -08:00
|
|
|
}
|
2020-05-06 05:40:42 -07:00
|
|
|
|
2021-11-16 01:15:29 -08:00
|
|
|
void setDefaultBoostParameters() {
|
2021-01-18 04:04:14 -08:00
|
|
|
engineConfiguration->boostPwmFrequency = 33;
|
2020-02-02 00:56:21 -08:00
|
|
|
engineConfiguration->boostPid.offset = 0;
|
|
|
|
engineConfiguration->boostPid.pFactor = 0.5;
|
|
|
|
engineConfiguration->boostPid.iFactor = 0.3;
|
2021-01-18 04:04:14 -08:00
|
|
|
engineConfiguration->boostPid.maxValue = 20;
|
|
|
|
engineConfiguration->boostPid.minValue = -20;
|
2020-02-02 00:56:21 -08:00
|
|
|
engineConfiguration->boostControlPinMode = OM_DEFAULT;
|
|
|
|
|
2023-11-13 15:30:30 -08:00
|
|
|
setRpmTableBin(config->boostRpmBins);
|
2024-08-22 08:30:53 -07:00
|
|
|
setLinearCurve(config->boostLoadBins, 0, 100, 1);
|
2020-05-06 05:40:42 -07:00
|
|
|
|
|
|
|
for (int loadIndex = 0; loadIndex < BOOST_LOAD_COUNT; loadIndex++) {
|
|
|
|
for (int rpmIndex = 0; rpmIndex < BOOST_RPM_COUNT; rpmIndex++) {
|
2024-08-22 08:30:53 -07:00
|
|
|
config->boostTableClosedLoop[loadIndex][rpmIndex] = (float)config->boostLoadBins[loadIndex];
|
2020-02-04 17:17:31 -08:00
|
|
|
}
|
|
|
|
}
|
2020-11-22 15:30:19 -08:00
|
|
|
|
|
|
|
// Defaults for ETB-style wastegate actuator
|
2021-11-17 00:54:21 -08:00
|
|
|
engineConfiguration->etbWastegatePid.pFactor = 1;
|
|
|
|
engineConfiguration->etbWastegatePid.minValue = -60;
|
|
|
|
engineConfiguration->etbWastegatePid.maxValue = 60;
|
2020-02-02 00:56:21 -08:00
|
|
|
}
|
|
|
|
|
2020-05-06 05:40:42 -07:00
|
|
|
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
|
2022-01-11 17:47:50 -08:00
|
|
|
if (!engineConfiguration->isBoostControlEnabled || !isBrainPinValid(engineConfiguration->boostControlPin)) {
|
2020-02-02 00:56:21 -08:00
|
|
|
return;
|
|
|
|
}
|
2020-02-04 17:17:31 -08:00
|
|
|
|
2020-11-02 21:09:42 -08:00
|
|
|
startSimplePwm(
|
2020-02-04 17:17:31 -08:00
|
|
|
&boostPwmControl,
|
|
|
|
"Boost",
|
2024-07-11 17:03:13 -07:00
|
|
|
&engine->scheduler,
|
2020-02-04 17:17:31 -08:00
|
|
|
&enginePins.boostPin,
|
|
|
|
engineConfiguration->boostPwmFrequency,
|
2023-10-19 09:32:59 -07:00
|
|
|
/*dutyCycle*/0
|
2020-02-04 17:17:31 -08:00
|
|
|
);
|
2020-03-23 20:06:52 -07:00
|
|
|
#endif /* EFI_UNIT_TEST */
|
2020-02-02 00:56:21 -08:00
|
|
|
}
|
|
|
|
|
2021-11-16 01:15:29 -08:00
|
|
|
void initBoostCtrl() {
|
2023-10-19 18:06:09 -07:00
|
|
|
#if EFI_PROD_CODE
|
2024-08-01 15:30:05 -07:00
|
|
|
if (engine->module<BoostController>().unmock().hasInitBoost) {
|
|
|
|
// already initialized - nothing to do here
|
|
|
|
return;
|
|
|
|
}
|
2020-12-06 15:39:50 -08:00
|
|
|
// todo: why do we have 'isBoostControlEnabled' setting exactly?
|
2022-09-27 19:21:18 -07:00
|
|
|
// 'initVvtActuators' is an example of a subsystem without explicit enable
|
2021-11-17 00:54:21 -08:00
|
|
|
if (!engineConfiguration->isBoostControlEnabled) {
|
2020-11-22 15:30:19 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool hasAnyEtbWastegate = false;
|
|
|
|
|
2021-11-17 00:54:21 -08:00
|
|
|
for (size_t i = 0; i < efi::size(engineConfiguration->etbFunctions); i++) {
|
2023-02-18 19:39:45 -08:00
|
|
|
hasAnyEtbWastegate |= engineConfiguration->etbFunctions[i] == DC_Wastegate;
|
2020-11-22 15:30:19 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// If we have neither a boost PWM pin nor ETB wastegate, nothing more to do
|
2021-11-17 00:54:21 -08:00
|
|
|
if (!isBrainPinValid(engineConfiguration->boostControlPin) && !hasAnyEtbWastegate) {
|
2020-02-04 17:17:31 -08:00
|
|
|
return;
|
|
|
|
}
|
2023-10-19 18:06:09 -07:00
|
|
|
#endif
|
2020-02-04 17:17:31 -08:00
|
|
|
|
2020-05-06 05:40:42 -07:00
|
|
|
// Set up open & closed loop tables
|
2024-08-22 08:30:53 -07:00
|
|
|
boostMapOpen.initTable(config->boostTableOpenLoop, config->boostRpmBins, config->boostLoadBins);
|
|
|
|
boostMapClosed.initTable(config->boostTableClosedLoop, config->boostRpmBins, config->boostLoadBins);
|
2024-08-19 13:39:22 -07:00
|
|
|
boostCltCorr.initTable(config->cltBoostCorr, config->cltBoostCorrBins);
|
|
|
|
boostIatCorr.initTable(config->iatBoostCorr, config->iatBoostCorrBins);
|
|
|
|
boostCltAdder.initTable(config->cltBoostAdder, config->cltBoostAdderBins);
|
|
|
|
boostIatAdder.initTable(config->iatBoostAdder, config->iatBoostAdderBins);
|
2020-05-06 05:40:42 -07:00
|
|
|
|
|
|
|
// Set up boost controller instance
|
2024-07-30 03:51:29 -07:00
|
|
|
engine->module<BoostController>().unmock().init(
|
|
|
|
&boostPwmControl,
|
|
|
|
&boostMapOpen,
|
|
|
|
&boostMapClosed,
|
|
|
|
boostCltCorr,
|
|
|
|
boostIatCorr,
|
2024-07-31 05:10:09 -07:00
|
|
|
boostCltAdder,
|
|
|
|
boostIatAdder,
|
2024-07-30 03:51:29 -07:00
|
|
|
&engineConfiguration->boostPid
|
|
|
|
);
|
2020-05-06 05:40:42 -07:00
|
|
|
|
2020-03-23 20:51:51 -07:00
|
|
|
#if !EFI_UNIT_TEST
|
2020-02-02 00:56:21 -08:00
|
|
|
startBoostPin();
|
2020-03-23 20:06:52 -07:00
|
|
|
#endif
|
2020-02-02 00:56:21 -08:00
|
|
|
}
|
|
|
|
|
2023-11-05 08:25:46 -08:00
|
|
|
#endif // EFI_BOOST_CONTROL
|