diff --git a/firmware/controllers/engine_cycle/knock_controller.cpp b/firmware/controllers/engine_cycle/knock_controller.cpp index 58d25f71ed..4e0bb80bee 100644 --- a/firmware/controllers/engine_cycle/knock_controller.cpp +++ b/firmware/controllers/engine_cycle/knock_controller.cpp @@ -11,6 +11,12 @@ #include "hip9011.h" +void KnockController::onConfigurationChange(engine_configuration_s const * previousConfig) { + KnockControllerBase::onConfigurationChange(previousConfig); + + m_maxRetardTable.init(config->maxKnockRetardTable, config->maxKnockRetardRpmBins, config->maxKnockRetardLoadBins); +} + int getCylinderKnockBank(uint8_t cylinderNumber) { // C/C++ can't index in to bit fields, we have to provide lookup ourselves switch (cylinderNumber) { @@ -45,7 +51,7 @@ int getCylinderKnockBank(uint8_t cylinderNumber) { } } -bool KnockController::onKnockSenseCompleted(uint8_t cylinderNumber, float dbv, efitick_t lastKnockTime) { +bool KnockControllerBase::onKnockSenseCompleted(uint8_t cylinderNumber, float dbv, efitick_t lastKnockTime) { bool isKnock = dbv > m_knockThreshold; #if EFI_TUNER_STUDIO @@ -77,23 +83,24 @@ bool KnockController::onKnockSenseCompleted(uint8_t cylinderNumber, float dbv, e // Adjust knock retard under lock chibios_rt::CriticalSectionLocker csl; auto newRetard = m_knockRetard + retardAmount; - m_knockRetard = clampF(0, newRetard, engineConfiguration->knockRetardMaximum); + m_knockRetard = clampF(0, newRetard, m_maximumRetard); } } return isKnock; } -float KnockController::getKnockRetard() const { +float KnockControllerBase::getKnockRetard() const { return m_knockRetard; } -uint32_t KnockController::getKnockCount() const { +uint32_t KnockControllerBase::getKnockCount() const { return m_knockCount; } -void KnockController::onFastCallback() { +void KnockControllerBase::onFastCallback() { m_knockThreshold = getKnockThreshold(); + m_maximumRetard = getMaximumRetard(); constexpr auto callbackPeriodSeconds = FAST_CALLBACK_PERIOD_MS / 1000.0f; @@ -118,6 +125,10 @@ float KnockController::getKnockThreshold() const { ); } +float KnockController::getMaximumRetard() const { + return m_maxRetardTable.getValue(Sensor::getOrZero(SensorType::Rpm), getIgnitionLoad()); +} + // This callback is to be implemented by the knock sense driver __attribute__((weak)) void onStartKnockSampling(uint8_t cylinderNumber, float samplingTimeSeconds, uint8_t channelIdx) { UNUSED(cylinderNumber); diff --git a/firmware/controllers/engine_cycle/knock_controller.txt b/firmware/controllers/engine_cycle/knock_controller.txt index 1ce575681a..d8127b2559 100644 --- a/firmware/controllers/engine_cycle/knock_controller.txt +++ b/firmware/controllers/engine_cycle/knock_controller.txt @@ -1,6 +1,6 @@ struct_no_prefix knock_controller_s - -angle_t m_knockRetard;Degrees retarded: larger number = more retard -float m_knockThreshold -uint32_t m_knockCount + angle_t m_knockRetard;Degrees retarded: larger number = more retard + float m_knockThreshold + uint32_t m_knockCount + float m_maximumRetard end_struct diff --git a/firmware/controllers/engine_cycle/knock_logic.h b/firmware/controllers/engine_cycle/knock_logic.h index 093a87809a..ec8ef75a25 100644 --- a/firmware/controllers/engine_cycle/knock_logic.h +++ b/firmware/controllers/engine_cycle/knock_logic.h @@ -12,9 +12,9 @@ int getCylinderKnockBank(uint8_t cylinderNumber); -class KnockController : public EngineModule, public knock_controller_s { +class KnockControllerBase : public EngineModule, public knock_controller_s { public: - KnockController() { + KnockControllerBase() { // start with threshold higher than any possible knock to avoid recording spurious knocks m_knockThreshold = 100; } @@ -27,10 +27,26 @@ public: float getKnockRetard() const; uint32_t getKnockCount() const; - virtual float getKnockThreshold() const; + virtual float getKnockThreshold() const = 0; + virtual float getMaximumRetard() const = 0; private: using PD = PeakDetect; PD peakDetectors[12]; PD allCylinderPeakDetector; }; + +class KnockController : public KnockControllerBase { +public: + KnockController() + { + } + + void onConfigurationChange(engine_configuration_s const * /*previousConfig*/) override; + + float getKnockThreshold() const override; + float getMaximumRetard() const override; + +private: + Map3D<6, 6, uint8_t, uint8_t, uint8_t> m_maxRetardTable; +}; diff --git a/firmware/integration/rusefi_config.txt b/firmware/integration/rusefi_config.txt index 8c94713088..ee8b02e293 100644 --- a/firmware/integration/rusefi_config.txt +++ b/firmware/integration/rusefi_config.txt @@ -647,7 +647,7 @@ end_struct uint8_t autoscale knockRetardAggression;+Ignition timing to remove when a knock event occurs.;"%", 0.1, 0, 0, 20, 1 uint8_t autoscale knockRetardReapplyRate;+After a knock event, reapply timing at this rate.;"deg/s", 0.1, 0, 0, 10, 1 -uint8_t knockRetardMaximum;+Maximum amount of knock retard.;"deg", 1, 0, 0, 30, 0 +uint8_t unused556;;"", 1, 0, 0, 1, 0 uint8_t vssFilterReciprocal;Set this so your vehicle speed signal is responsive, but not noisy. Larger value give smoother but slower response.;"", 1, 0, 2, 200, 0 @@ -1720,6 +1720,10 @@ 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 +uint8_t[6 x 6] autoscale maxKnockRetardTable;;"deg", 0.25, 0, 0, 30, 2 +uint8_t[6] maxKnockRetardLoadBins;;"%", 1, 0, 0, 250, 0 +uint8_t[6] autoscale maxKnockRetardRpmBins;;"RPM", 100, 0, 0, 25000, 0 + end_struct ! Pedal Position Sensor diff --git a/firmware/tunerstudio/rusefi.input b/firmware/tunerstudio/rusefi.input index 601274a702..3b5583af58 100644 --- a/firmware/tunerstudio/rusefi.input +++ b/firmware/tunerstudio/rusefi.input @@ -958,6 +958,12 @@ curve = 32Curve, "3-2 Shift Solenoid Percent by Speed" zBins = throttle2TrimTable gridOrient = 250, 0, 340 ; Space 123 rotation of grid in degrees. + table = maxKnockRetardTbl, maxKnockRetardMap, "Max knock retard", 1 + xBins = maxKnockRetardRpmBins, RPMValue + yBins = maxKnockRetardLoadBins, TPSValue + zBins = maxKnockRetardTable + gridOrient = 250, 0, 340 ; Space 123 rotation of grid in degrees. + #if LAMBDA table = lambdaTableTbl, lambdaTableMap, "Target Lambda Table", 1 #else @@ -1677,7 +1683,8 @@ menuDialog = main subMenu = std_separator subMenu = hipFunction, "HIP9011 settings (knock sensor) (alpha version)" @@if_ts_show_hip9011 - subMenu = softwareKnock, "Software Knock" @@if_ts_show_software_knock + subMenu = softwareKnock, "Software knock" @@if_ts_show_software_knock + subMenu = maxKnockRetardTbl, "Max knock retard" @@if_ts_show_software_knock subMenu = std_separator subMenu = smLaunchControl, "Launch Control" diff --git a/unit_tests/tests/test_knock.cpp b/unit_tests/tests/test_knock.cpp index 882999810e..1292dfca30 100644 --- a/unit_tests/tests/test_knock.cpp +++ b/unit_tests/tests/test_knock.cpp @@ -2,11 +2,16 @@ #include "knock_logic.h" -struct MockKnockController : public KnockController { +struct MockKnockController : public KnockControllerBase { float getKnockThreshold() const override { // Knock threshold of 20dBv return 20; } + + float getMaximumRetard() const override { + // Maximum 8 degrees retarded + return 8; + } }; TEST(Knock, Retards) { @@ -14,8 +19,6 @@ TEST(Knock, Retards) { // Aggression of 10% engineConfiguration->knockRetardAggression = 10; - // Maximum 8 degrees retarded - engineConfiguration->knockRetardMaximum = 8; MockKnockController dut; dut.onFastCallback(); @@ -52,8 +55,6 @@ TEST(Knock, Reapply) { // Aggression of 10% engineConfiguration->knockRetardAggression = 10; - // Maximum 8 degrees retarded - engineConfiguration->knockRetardMaximum = 8; // Apply 1 degree/second engineConfiguration->knockRetardReapplyRate = 1;