diff --git a/firmware/controllers/actuators/boost_control.cpp b/firmware/controllers/actuators/boost_control.cpp index deab87aa1d..f8dee33d56 100644 --- a/firmware/controllers/actuators/boost_control.cpp +++ b/firmware/controllers/actuators/boost_control.cpp @@ -15,14 +15,11 @@ #include "boost_control.h" #include "sensor.h" #include "map.h" -#include "io_pins.h" -#include "engine_configuration.h" -#include "pwm_generator_logic.h" -#include "engine_controller.h" #include "pin_repository.h" #include "pwm_generator_logic.h" #include "pid_auto_tune.h" -#include "local_version_holder.h" +#include "electronic_throttle.h" + #define NO_PIN_PERIOD 500 #if defined(HAS_OS_ACCESS) @@ -148,6 +145,8 @@ void BoostController::setOutput(expected output) { if (m_pwm) { m_pwm->setSimplePwmDutyCycle(duty); } + + setEtbWastegatePosition(duty PASS_ENGINE_PARAMETER_SUFFIX); } void BoostController::PeriodicTask() { diff --git a/firmware/controllers/actuators/electronic_throttle.cpp b/firmware/controllers/actuators/electronic_throttle.cpp index dea7dc53b4..532ab74344 100644 --- a/firmware/controllers/actuators/electronic_throttle.cpp +++ b/firmware/controllers/actuators/electronic_throttle.cpp @@ -199,6 +199,10 @@ void EtbController::setIdlePosition(percent_t pos) { m_idlePosition = pos; } +void EtbController::setWastegatePosition(percent_t pos) { + m_wastegatePosition = pos; +} + expected EtbController::getSetpoint() const { switch (m_function) { case ETB_Throttle1: @@ -223,8 +227,7 @@ expected EtbController::getSetpointIdleValve() const { } expected EtbController::getSetpointWastegate() const { - // TODO: implement me! - return unexpected; + return clampF(0, m_wastegatePosition, 100); } expected EtbController::getSetpointEtb() const { @@ -721,9 +724,7 @@ void etbAutocal(size_t throttleIndex) { return; } - auto etb = engine->etbControllers[throttleIndex]; - - if (etb) { + if (auto etb = engine->etbControllers[throttleIndex]) { etb->autoCalibrateTps(); } } @@ -894,12 +895,18 @@ void initElectronicThrottle(DECLARE_ENGINE_PARAMETER_SIGNATURE) { void setEtbIdlePosition(percent_t pos DECLARE_ENGINE_PARAMETER_SUFFIX) { for (int i = 0; i < ETB_COUNT; i++) { - auto etb = engine->etbControllers[i]; - - if (etb) { + if (auto etb = engine->etbControllers[i]) { etb->setIdlePosition(pos); } } } +void setEtbWastegatePosition(percent_t pos DECLARE_ENGINE_PARAMETER_SUFFIX) { + for (int i = 0; i < ETB_COUNT; i++) { + if (auto etb = engine->etbControllers[i]) { + etb->setWastegatePosition(pos); + } + } +} + #endif /* EFI_ELECTRONIC_THROTTLE_BODY */ diff --git a/firmware/controllers/actuators/electronic_throttle.h b/firmware/controllers/actuators/electronic_throttle.h index 2113e0f2f2..6afbd8a5b7 100644 --- a/firmware/controllers/actuators/electronic_throttle.h +++ b/firmware/controllers/actuators/electronic_throttle.h @@ -33,6 +33,7 @@ public: virtual bool init(etb_function_e function, DcMotor *motor, pid_s *pidParameters, const ValueProvider3D* pedalMap) = 0; virtual void reset() = 0; virtual void setIdlePosition(percent_t pos) = 0; + virtual void setWastegatePosition(percent_t pos) = 0; virtual void update() = 0; virtual void autoCalibrateTps() = 0; }; @@ -41,6 +42,7 @@ class EtbController : public IEtbController { public: bool init(etb_function_e function, DcMotor *motor, pid_s *pidParameters, const ValueProvider3D* pedalMap) override; void setIdlePosition(percent_t pos) override; + void setWastegatePosition(percent_t pos) override; void reset() override; // Update the controller's state: read sensors, send output, etc @@ -91,6 +93,7 @@ private: const ValueProvider3D* m_pedalMap = nullptr; float m_idlePosition = 0; + float m_wastegatePosition = 0; // Autotune helpers bool m_lastIsPositive = false; @@ -109,7 +112,9 @@ private: void initElectronicThrottle(DECLARE_ENGINE_PARAMETER_SIGNATURE); void doInitElectronicThrottle(DECLARE_ENGINE_PARAMETER_SIGNATURE); + void setEtbIdlePosition(percent_t pos DECLARE_ENGINE_PARAMETER_SUFFIX); +void setEtbWastegatePosition(percent_t pos DECLARE_ENGINE_PARAMETER_SUFFIX); void setDefaultEtbBiasCurve(DECLARE_CONFIG_PARAMETER_SIGNATURE); void setDefaultEtbParameters(DECLARE_CONFIG_PARAMETER_SIGNATURE); diff --git a/unit_tests/mocks.h b/unit_tests/mocks.h index ee29e5085e..09f1d6e527 100644 --- a/unit_tests/mocks.h +++ b/unit_tests/mocks.h @@ -15,6 +15,7 @@ public: MOCK_METHOD(void, update, (), (override)); MOCK_METHOD(bool, init, (etb_function_e function, DcMotor* motor, pid_s* pidParameters, const ValueProvider3D* pedalMap), (override)); MOCK_METHOD(void, setIdlePosition, (percent_t pos), (override)); + MOCK_METHOD(void, setWastegatePosition, (percent_t pos), (override)); MOCK_METHOD(void, autoCalibrateTps, (), (override)); // ClosedLoopController mocks diff --git a/unit_tests/tests/test_boost.cpp b/unit_tests/tests/test_boost.cpp index f8258c9464..0ee8b94d96 100644 --- a/unit_tests/tests/test_boost.cpp +++ b/unit_tests/tests/test_boost.cpp @@ -106,16 +106,23 @@ TEST(BoostControl, ClosedLoop) { } TEST(BoostControl, SetOutput) { - StrictMock pwm; - BoostController bc; + WITH_ENGINE_TEST_HELPER(TEST_ENGINE); + StrictMock pwm; + StrictMock etb; + BoostController bc; + INJECT_ENGINE_REFERENCE(&bc); + + // ETB wastegate position & PWM should both be set + EXPECT_CALL(etb, setWastegatePosition(0.25f)); EXPECT_CALL(pwm, setSimplePwmDutyCycle(0.25f)); // Don't crash if not init'd (don't deref null ptr m_pwm) EXPECT_NO_THROW(bc.setOutput(25.0f)); - // Init with mock PWM device + // Init with mock PWM device and ETB bc.init(&pwm, nullptr, nullptr, nullptr); + engine->etbControllers[0] = &etb; bc.setOutput(25.0f); } diff --git a/unit_tests/tests/test_etb.cpp b/unit_tests/tests/test_etb.cpp index a58f4d96d1..83186448c4 100644 --- a/unit_tests/tests/test_etb.cpp +++ b/unit_tests/tests/test_etb.cpp @@ -289,6 +289,25 @@ TEST(etb, setpointIdleValveController) { EXPECT_FLOAT_EQ(100, etb.getSetpoint().value_or(-1)); } +TEST(etb, setpointWastegateController) { + EtbController etb; + + etb.init(ETB_Wastegate, nullptr, nullptr, nullptr); + + etb.setWastegatePosition(0); + EXPECT_FLOAT_EQ(0, etb.getSetpoint().value_or(-1)); + etb.setWastegatePosition(50); + EXPECT_FLOAT_EQ(50, etb.getSetpoint().value_or(-1)); + etb.setWastegatePosition(100); + EXPECT_FLOAT_EQ(100, etb.getSetpoint().value_or(-1)); + + // Out of range should be clamped + etb.setWastegatePosition(-10); + EXPECT_FLOAT_EQ(0, etb.getSetpoint().value_or(-1)); + etb.setWastegatePosition(110); + EXPECT_FLOAT_EQ(100, etb.getSetpoint().value_or(-1)); +} + TEST(etb, etbTpsSensor) { // Throw some distinct values on the TPS sensors so we can identify that we're getting the correct one Sensor::setMockValue(SensorType::Tps1, 25.0f);