diff --git a/firmware/controllers/algo/advance_map.cpp b/firmware/controllers/algo/advance_map.cpp index 7e55f7d3dd..ad53429140 100644 --- a/firmware/controllers/algo/advance_map.cpp +++ b/firmware/controllers/algo/advance_map.cpp @@ -205,12 +205,8 @@ angle_t getAdvance(int rpm, float engineLoad) { #endif } -angle_t getCombinedCylinderIgnitionTrim(size_t cylinderNumber, int rpm, float ignitionLoad) { - // we have two separate per-cylinder trims, that's a feature - // Plus or minus any adjustment if this is an odd-fire engine - auto adjustment = engineConfiguration->timing_offset_cylinder[cylinderNumber]; - - return adjustment + interpolate3d( +angle_t getCylinderIgnitionTrim(size_t cylinderNumber, int rpm, float ignitionLoad) { + return interpolate3d( config->ignTrims[cylinderNumber].table, config->ignTrimLoadBins, ignitionLoad, config->ignTrimRpmBins, rpm diff --git a/firmware/controllers/algo/advance_map.h b/firmware/controllers/algo/advance_map.h index afeeb07e08..52c976a45f 100644 --- a/firmware/controllers/algo/advance_map.h +++ b/firmware/controllers/algo/advance_map.h @@ -10,7 +10,7 @@ #pragma once angle_t getAdvance(int rpm, float engineLoad); -angle_t getCombinedCylinderIgnitionTrim(size_t cylinderNumber, int rpm, float ignitionLoad); +angle_t getCylinderIgnitionTrim(size_t cylinderNumber, int rpm, float ignitionLoad); /** * this method is used to build default advance map */ diff --git a/firmware/controllers/algo/engine2.cpp b/firmware/controllers/algo/engine2.cpp index 9e23be2c9c..6182d32cd6 100644 --- a/firmware/controllers/algo/engine2.cpp +++ b/firmware/controllers/algo/engine2.cpp @@ -184,7 +184,7 @@ void EngineState::periodicFastCallback() { // Apply both per-bank and per-cylinder trims engine->engineState.injectionMass[i] = untrimmedInjectionMass * bankTrim * cylinderTrim; - timingAdvance[i] = correctedIgnitionAdvance + getCombinedCylinderIgnitionTrim(i, rpm, l_ignitionLoad); + timingAdvance[i] = correctedIgnitionAdvance + getCylinderIgnitionTrim(i, rpm, l_ignitionLoad); } shouldUpdateInjectionTiming = getInjectorDutyCycle(rpm) < 90; diff --git a/firmware/controllers/algo/obd_error_codes.h b/firmware/controllers/algo/obd_error_codes.h index f7bbc04190..eddd824bd3 100644 --- a/firmware/controllers/algo/obd_error_codes.h +++ b/firmware/controllers/algo/obd_error_codes.h @@ -1943,7 +1943,7 @@ enum class ObdCode : uint16_t { CUSTOM_ERR_6563 = 6563, CUSTOM_ERR_6564 = 6564, CUSTOM_ERR_6565 = 6565, - CUSTOM_ERR_6566 = 6566, + CUSTOM_ERR_CYL_ANGLE = 6566, CUSTOM_ERR_6567 = 6567, CUSTOM_ERR_6568 = 6568, CUSTOM_ERR_6569 = 6569, diff --git a/firmware/controllers/math/engine_math.cpp b/firmware/controllers/math/engine_math.cpp index 4c1976597a..6c50652c2f 100644 --- a/firmware/controllers/math/engine_math.cpp +++ b/firmware/controllers/math/engine_math.cpp @@ -416,14 +416,18 @@ void prepareOutputSignals() { } angle_t getPerCylinderFiringOrderOffset(uint8_t cylinderIndex, uint8_t cylinderNumber) { - UNUSED(cylinderNumber); // TODO: technical debt // base = position of this cylinder in the firing order. // We get a cylinder every n-th of an engine cycle where N is the number of cylinders auto firingOrderOffset = engine->engineState.engineCycle * cylinderIndex / engineConfiguration->cylindersCount; - assertAngleRange(firingOrderOffset, "getPerCylinderFiringOrderOffset", ObdCode::CUSTOM_ERR_6566); + // Plus or minus any adjustment if this is an odd-fire engine + auto adjustment = engineConfiguration->timing_offset_cylinder[cylinderNumber]; - return firingOrderOffset; + auto result = firingOrderOffset + adjustment; + + assertAngleRange(result, "getCylinderAngle", ObdCode::CUSTOM_ERR_CYL_ANGLE); + + return result; } void setTimingRpmBin(float from, float to) { diff --git a/unit_tests/tests/ignition_injection/test_odd_firing_engine.cpp b/unit_tests/tests/ignition_injection/test_odd_firing_engine.cpp index 53c949692c..7e8e7b5103 100644 --- a/unit_tests/tests/ignition_injection/test_odd_firing_engine.cpp +++ b/unit_tests/tests/ignition_injection/test_odd_firing_engine.cpp @@ -37,16 +37,18 @@ TEST(OddFire, hd) { // ASSERT_NEAR(-200.0, eth.timeToAngle(-66.66666), EPS3D); // ASSERT_NEAR(160.0, eth.timeToAngle(53.333333), EPS3D); // ASSERT_NEAR(-168.0, eth.timeToAngle(-56.0), EPS3D); +// ASSERT_NEAR(-194, eth.timeToAngle(-64.666666), EPS3D); +// ASSERT_NEAR(-201.0, eth.timeToAngle(-67.0), EPS3D); +// ASSERT_NEAR(-522.0, eth.timeToAngle(-174.0), EPS3D); +// ASSERT_NEAR(354.0, eth.timeToAngle(118.0), EPS3D); +// ASSERT_NEAR(127.0, eth.timeToAngle(42.3333333), EPS3D); // ASSERT_NEAR(32, eth.timeToAngle(10.66666666), EPS3D); - angle_t expectedAngle3 = -180 + cylinderTwo - timing; + angle_t expectedAngle3 = -180 - cylinderTwo - timing; - ASSERT_EQ( 8, engine->executor.size()); + ASSERT_EQ( 6, engine->executor.size()); eth.assertEvent5("spark down#3", 3, (void*)fireSparkAndPrepareNextSchedule, eth.angleToTimeUs(expectedAngle3)); - angle_t expectedAngle7 = 180 - cylinderOne - timing; - eth.assertEvent5("spark down#7", 7, (void*)fireSparkAndPrepareNextSchedule, eth.angleToTimeUs(expectedAngle7)); - eth.assertRpm( 500, "spinning-RPM#1"); engine->executor.executeAll(eth.getTimeNowUs() + MS2US(1000000)); @@ -56,8 +58,8 @@ TEST(OddFire, hd) { ASSERT_NEAR(0.0069257142022, getInjectionMass(200), EPS3D); ASSERT_EQ( 8, engine->executor.size()); - eth.assertEvent5("fuel down2#1", 1, (void*)turnInjectionPinLow, eth.angleToTimeUs(180 + PORT_INJECTION_OFFSET)); - eth.assertEvent5("spark down2#3", 3, (void*)fireSparkAndPrepareNextSchedule, eth.angleToTimeUs(-180 + cylinderTwo - timing)); - eth.assertEvent5("fuel down2#5", 5, (void*)turnInjectionPinLow, eth.angleToTimeUs(540 + PORT_INJECTION_OFFSET)); - eth.assertEvent5("spark down2#7", 7, (void*)fireSparkAndPrepareNextSchedule, eth.angleToTimeUs(180 - cylinderOne - timing)); + eth.assertEvent5("spark down2#1", 1, (void*)fireSparkAndPrepareNextSchedule, eth.angleToTimeUs(-540 + cylinderOne - timing)); + eth.assertEvent5("fuel down2#4", 4, (void*)turnInjectionPinLow, eth.angleToTimeUs(PORT_INJECTION_OFFSET + 180 + cylinderOne)); + eth.assertEvent5("spark down2#5", 5, (void*)fireSparkAndPrepareNextSchedule, eth.angleToTimeUs(-180 - cylinderTwo - timing)); + eth.assertEvent5("fuel down2#7", 7, (void*)turnInjectionPinLow, eth.angleToTimeUs(PORT_INJECTION_OFFSET + 540 - cylinderTwo)); }