diff --git a/firmware/CHANGELOG.md b/firmware/CHANGELOG.md index 01cc464ce5..153a02c709 100644 --- a/firmware/CHANGELOG.md +++ b/firmware/CHANGELOG.md @@ -27,6 +27,7 @@ Release template (copy/paste this for new release): ### Added - Time delay before DFCO #4292 + - Manual electronic throttle synchronization #3680 ### Fixed - Inverted vvt control #4464 diff --git a/firmware/controllers/actuators/electronic_throttle.cpp b/firmware/controllers/actuators/electronic_throttle.cpp index fc1cf6903d..21a559d0b7 100644 --- a/firmware/controllers/actuators/electronic_throttle.cpp +++ b/firmware/controllers/actuators/electronic_throttle.cpp @@ -94,6 +94,7 @@ #endif /* ETB_MAX_COUNT */ static pedal2tps_t pedal2tpsMap; +static Map3D<6, 6, int8_t, uint8_t, uint8_t> throttle2TrimTable; constexpr float etbPeriodSeconds = 1.0f / ETB_LOOP_FREQUENCY; @@ -384,9 +385,8 @@ float EtbController::getLuaAdjustment() const { } } -percent_t EtbController2::getThrottleTrim(float /*rpm*/, percent_t /*targetPosition*/) const { - // TODO: implement me #3680 - return 0; +percent_t EtbController2::getThrottleTrim(float rpm, percent_t targetPosition) const { + return m_throttle2Trim.getValue(rpm, targetPosition); } expected EtbController::getOpenLoop(percent_t target) { @@ -614,8 +614,13 @@ void EtbController::autoCalibrateTps() { */ #include "periodic_thread_controller.h" +#include + template struct EtbImpl final : public TBase { + template + EtbImpl(TArgs&&... args) : TBase(std::forward(args)...) { } + void update() override { #if EFI_TUNER_STUDIO if (TBase::m_isAutocal) { @@ -688,7 +693,7 @@ struct EtbImpl final : public TBase { // real implementation (we mock for some unit tests) static EtbImpl etb1; -static EtbImpl etb2; +static EtbImpl etb2(throttle2TrimTable); static_assert(ETB_COUNT == 2); static EtbController* etbControllers[] = { &etb1, &etb2 }; @@ -961,6 +966,7 @@ void doInitElectronicThrottle() { #endif /* EFI_PROD_CODE */ pedal2tpsMap.init(config->pedalToTpsTable, config->pedalToTpsPedalBins, config->pedalToTpsRpmBins); + throttle2TrimTable.init(config->throttle2TrimTable, config->throttle2TrimTpsBins, config->throttle2TrimRpmBins); bool shouldInitThrottles = Sensor::hasSensor(SensorType::AcceleratorPedalPrimary); bool anyEtbConfigured = false; diff --git a/firmware/controllers/actuators/electronic_throttle_impl.h b/firmware/controllers/actuators/electronic_throttle_impl.h index 4fba3b16a4..b2079be367 100644 --- a/firmware/controllers/actuators/electronic_throttle_impl.h +++ b/firmware/controllers/actuators/electronic_throttle_impl.h @@ -115,5 +115,13 @@ class EtbController1 : public EtbController { }; class EtbController2 : public EtbController { public: + EtbController2(const ValueProvider3D& throttle2TrimTable) + : m_throttle2Trim(throttle2TrimTable) + { + } + percent_t getThrottleTrim(float rpm, percent_t /*targetPosition*/) const override; + +private: + const ValueProvider3D& m_throttle2Trim; }; diff --git a/firmware/integration/rusefi_config.txt b/firmware/integration/rusefi_config.txt index d93e8c03a8..1cf66908b0 100644 --- a/firmware/integration/rusefi_config.txt +++ b/firmware/integration/rusefi_config.txt @@ -1715,7 +1715,11 @@ uint8_t[8] tcu_tccUnlockSpeed;;"MPH", 1, 0, 0, 255, 0 uint8_t[8] tcu_32SpeedBins;;"KPH", 1, 0, 0, 255, 0 uint8_t[8] tcu_32Vals;;"%", 1, 0, 0, 255, 0 - + +int8_t[6 x 6] autoscale throttle2TrimTable;;"%", 0.1, 0, -10, 10, 1 +uint8_t[6] throttle2TrimTpsBins;;"%", 1, 0, 0, 120, 0 +uint8_t[6] autoscale throttle2TrimRpmBins;;"RPM", 100, 0, 0, 25000, 0 + end_struct ! Pedal Position Sensor diff --git a/firmware/tunerstudio/rusefi.input b/firmware/tunerstudio/rusefi.input index a9b4b5f47c..25568b520f 100644 --- a/firmware/tunerstudio/rusefi.input +++ b/firmware/tunerstudio/rusefi.input @@ -952,6 +952,11 @@ curve = 32Curve, "3-2 Shift Solenoid Percent by Speed" gridOrient = 250, 0, 340 ; Space 123 rotation of grid in degrees. upDownLabel = "(Later)", "(Sooner)" + table = throttle2TrimTbl, throttle2TrimMap, "ETB #2 Trim", 1 + xBins = throttle2TrimRpmBins, RPMValue + yBins = throttle2TrimTpsBins, TPSValue + zBins = throttle2TrimTable + gridOrient = 250, 0, 340 ; Space 123 rotation of grid in degrees. #if LAMBDA table = lambdaTableTbl, lambdaTableMap, "Target Lambda Table", 1 @@ -1551,6 +1556,7 @@ menuDialog = main subMenu = etbDialog, "Electronic throttle body" @@if_ts_show_etb subMenu = etbTpsBiasCurve, "ETB bias curve (feed forward)" @@if_ts_show_etb subMenu = pedalToTpsTbl, "ETB pedal target" @@if_ts_show_etb + subMenu = throttle2TrimTbl, "ETB #2 Trim", { tps2_1AdcChannel != @@ADC_CHANNEL_NONE@@ } @@if_ts_show_etb subMenu = std_separator subMenu = vvtPidDialog, "VVT outputs and PID", { vvtMode1 != @@vvt_mode_e_VVT_INACTIVE@@ } diff --git a/unit_tests/tests/actuators/test_etb.cpp b/unit_tests/tests/actuators/test_etb.cpp index 34c6711a12..176de6c39a 100644 --- a/unit_tests/tests/actuators/test_etb.cpp +++ b/unit_tests/tests/actuators/test_etb.cpp @@ -15,6 +15,7 @@ using ::testing::_; using ::testing::Ne; +using ::testing::Return; using ::testing::StrictMock; TEST(etb, initializationNoPedal) { @@ -323,6 +324,37 @@ TEST(etb, testSetpointOnlyPedal) { EXPECT_EQ(90, etb.getSetpoint().value_or(-1)); } +TEST(etb, setpointSecondThrottleTrim) { + EngineTestHelper eth(TEST_ENGINE); + + // Don't use ETB for idle, we aren't testing that yet - just pedal table for now + engineConfiguration->useETBforIdleControl = false; + + + // Mock pedal map that's just passthru pedal -> target + StrictMock pedalMap; + EXPECT_CALL(pedalMap, getValue(_, _)) + .WillRepeatedly([](float xRpm, float y) { + return y; + }); + + // Should get called with the un-adjusted setpoint + StrictMock throttleTrimTable; + EXPECT_CALL(throttleTrimTable, getValue(0, 47)) + .WillOnce(Return(4)); + + // Must have TPS & PPS initialized for ETB setup + Sensor::setMockValue(SensorType::Tps1Primary, 0); + Sensor::setMockValue(SensorType::Tps1, 0.0f, true); + Sensor::setMockValue(SensorType::AcceleratorPedal, 0.0f, true); + + EtbController2 etb(throttleTrimTable); + etb.init(ETB_Throttle1, nullptr, nullptr, &pedalMap, true); + + Sensor::setMockValue(SensorType::AcceleratorPedal, 47, true); + EXPECT_EQ(51, etb.getSetpoint().value_or(-1)); +} + TEST(etb, setpointIdle) { EngineTestHelper eth(TEST_ENGINE);