From 338c14c3a832dc15b17b2b3c4425e42310c20872 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sat, 1 Jan 2022 14:47:47 -0600 Subject: [PATCH] cylinder ignition trim (#3709) * cylinder ignition trim * changelog * changelog * test * move UI --- firmware/CHANGELOG.md | 1 + firmware/controllers/algo/advance_map.cpp | 8 +++++ firmware/controllers/algo/advance_map.h | 1 + firmware/controllers/algo/engine2.cpp | 2 +- firmware/tunerstudio/rusefi.input | 29 ++++++++++--------- .../test_ignition_scheduling.cpp | 24 ++++++++++++++- 6 files changed, 49 insertions(+), 16 deletions(-) diff --git a/firmware/CHANGELOG.md b/firmware/CHANGELOG.md index 5f66cc8c63..fd28f1f5fc 100644 --- a/firmware/CHANGELOG.md +++ b/firmware/CHANGELOG.md @@ -29,6 +29,7 @@ All notable user-facing or behavior-altering changes will be documented in this ### Added - Per-cylinder fuel trim tables + - Per-cylinder ignition timing trim tables ## December 2021 Release - "Cookie Exchange" diff --git a/firmware/controllers/algo/advance_map.cpp b/firmware/controllers/algo/advance_map.cpp index 877c98611f..968bee6f2d 100644 --- a/firmware/controllers/algo/advance_map.cpp +++ b/firmware/controllers/algo/advance_map.cpp @@ -168,6 +168,14 @@ angle_t getAdvance(int rpm, float engineLoad) { #endif } +angle_t getCylinderIgnitionTrim(size_t cylinderNumber, int rpm, float ignitionLoad) { + return interpolate3d( + config->ignTrims[cylinderNumber].table, + config->ignTrimLoadBins, ignitionLoad, + config->ignTrimRpmBins, rpm + ); +} + size_t getMultiSparkCount(int rpm) { // Compute multispark (if enabled) if (engineConfiguration->multisparkEnable diff --git a/firmware/controllers/algo/advance_map.h b/firmware/controllers/algo/advance_map.h index b25883d37a..18664bb2b0 100644 --- a/firmware/controllers/algo/advance_map.h +++ b/firmware/controllers/algo/advance_map.h @@ -8,6 +8,7 @@ #pragma once angle_t getAdvance(int rpm, float engineLoad); +angle_t getCylinderIgnitionTrim(size_t cylinderNumber, int rpm, float ignitionLoad); float getTopAdvanceForBore(chamber_style_e style, int octane, double compression, double bore); float getInitialAdvance(int rpm, float map, float advanceMax); void buildTimingMap(float advanceMax); diff --git a/firmware/controllers/algo/engine2.cpp b/firmware/controllers/algo/engine2.cpp index 852652c5f9..4fe6f204f3 100644 --- a/firmware/controllers/algo/engine2.cpp +++ b/firmware/controllers/algo/engine2.cpp @@ -175,7 +175,7 @@ void EngineState::periodicFastCallback() { // Apply both per-bank and per-cylinder trims engine->injectionMass[i] = injectionMass * bankTrim * cylinderTrim; - timingAdvance[i] = advance; + timingAdvance[i] = advance + getCylinderIgnitionTrim(i, rpm, ignitionLoad); } // TODO: calculate me from a table! diff --git a/firmware/tunerstudio/rusefi.input b/firmware/tunerstudio/rusefi.input index 2a1a1aeaad..7f0ef1255b 100644 --- a/firmware/tunerstudio/rusefi.input +++ b/firmware/tunerstudio/rusefi.input @@ -1341,6 +1341,21 @@ menuDialog = main subMenu = std_separator subMenu = ignitionTableTbl, "Ignition advance", 0, {isIgnitionEnabled} + + groupMenu = "Cylinder ign trims" + groupChildMenu = ignTrimTbl1, "Ignition trim cyl 1" + groupChildMenu = ignTrimTbl2, "Ignition trim cyl 2" + groupChildMenu = ignTrimTbl3, "Ignition trim cyl 3" + groupChildMenu = ignTrimTbl4, "Ignition trim cyl 4" + groupChildMenu = ignTrimTbl5, "Ignition trim cyl 5" + groupChildMenu = ignTrimTbl6, "Ignition trim cyl 6" + groupChildMenu = ignTrimTbl7, "Ignition trim cyl 7" + groupChildMenu = ignTrimTbl8, "Ignition trim cyl 8" + groupChildMenu = ignTrimTbl9, "Ignition trim cyl 9" + groupChildMenu = ignTrimTbl10, "Ignition trim cyl 10" + groupChildMenu = ignTrimTbl11, "Ignition trim cyl 11" + groupChildMenu = ignTrimTbl12, "Ignition trim cyl 12" + subMenu = std_separator # corrections @@ -1515,20 +1530,6 @@ menuDialog = main # subMenu = antiLag, "Antilag Setup" # subMenu = std_separator - groupMenu = "Cylinder ign trims" - groupChildMenu = ignTrimTbl1, "Ignition trim cyl 1" - groupChildMenu = ignTrimTbl2, "Ignition trim cyl 2" - groupChildMenu = ignTrimTbl3, "Ignition trim cyl 3" - groupChildMenu = ignTrimTbl4, "Ignition trim cyl 4" - groupChildMenu = ignTrimTbl5, "Ignition trim cyl 5" - groupChildMenu = ignTrimTbl6, "Ignition trim cyl 6" - groupChildMenu = ignTrimTbl7, "Ignition trim cyl 7" - groupChildMenu = ignTrimTbl8, "Ignition trim cyl 8" - groupChildMenu = ignTrimTbl9, "Ignition trim cyl 9" - groupChildMenu = ignTrimTbl10, "Ignition trim cyl 10" - groupChildMenu = ignTrimTbl11, "Ignition trim cyl 11" - groupChildMenu = ignTrimTbl12, "Ignition trim cyl 12" - menu = "Help" subMenu = helpGeneral, "rusEFI Info" diff --git a/unit_tests/tests/ignition_injection/test_ignition_scheduling.cpp b/unit_tests/tests/ignition_injection/test_ignition_scheduling.cpp index 7739bae407..1180ea20ff 100644 --- a/unit_tests/tests/ignition_injection/test_ignition_scheduling.cpp +++ b/unit_tests/tests/ignition_injection/test_ignition_scheduling.cpp @@ -118,5 +118,27 @@ TEST(ignition, trailingSpark) { eth.executeActions(); // secondary coils should be low EXPECT_EQ(enginePins.trailingCoils[0].getLogicValue(), false); - +} + +TEST(ignition, CylinderTimingTrim) { + EngineTestHelper eth(TEST_ENGINE); + + // Base timing 15 degrees + setTable(config->ignitionTable, 15); + + // negative numbers retard timing, positive advance + setTable(config->ignTrims[0].table, -4); + setTable(config->ignTrims[1].table, -2); + setTable(config->ignTrims[2].table, 2); + setTable(config->ignTrims[3].table, 4); + + // run the ignition math + engine->periodicFastCallback(); + + // Check that each cylinder gets the expected timing + float unadjusted = 15; + EXPECT_NEAR(engine->engineState.timingAdvance[0], unadjusted - 4, EPS4D); + EXPECT_NEAR(engine->engineState.timingAdvance[1], unadjusted - 2, EPS4D); + EXPECT_NEAR(engine->engineState.timingAdvance[2], unadjusted + 2, EPS4D); + EXPECT_NEAR(engine->engineState.timingAdvance[3], unadjusted + 4, EPS4D); }