trailing spark scheduling (#2932)
* enable bit * implement trailing sparks * test trailing spark * it helps to call the correct function * add pins * gobblin ram
This commit is contained in:
parent
dec1f1daff
commit
86683afca2
|
@ -171,6 +171,10 @@ void EngineState::periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
||||||
|
|
||||||
float ignitionLoad = getIgnitionLoad(PASS_ENGINE_PARAMETER_SIGNATURE);
|
float ignitionLoad = getIgnitionLoad(PASS_ENGINE_PARAMETER_SIGNATURE);
|
||||||
timingAdvance = getAdvance(rpm, ignitionLoad PASS_ENGINE_PARAMETER_SUFFIX);
|
timingAdvance = getAdvance(rpm, ignitionLoad PASS_ENGINE_PARAMETER_SUFFIX);
|
||||||
|
|
||||||
|
// TODO: calculate me from a table!
|
||||||
|
trailingSparkAngle = 10;
|
||||||
|
|
||||||
multispark.count = getMultiSparkCount(rpm PASS_ENGINE_PARAMETER_SUFFIX);
|
multispark.count = getMultiSparkCount(rpm PASS_ENGINE_PARAMETER_SUFFIX);
|
||||||
|
|
||||||
#if EFI_LAUNCH_CONTROL
|
#if EFI_LAUNCH_CONTROL
|
||||||
|
|
|
@ -47,6 +47,10 @@ public:
|
||||||
* timing advance is angle distance before Top Dead Center (TDP), i.e. "10 degree timing advance" means "happens 10 degrees before TDC"
|
* timing advance is angle distance before Top Dead Center (TDP), i.e. "10 degree timing advance" means "happens 10 degrees before TDC"
|
||||||
*/
|
*/
|
||||||
angle_t timingAdvance = 0;
|
angle_t timingAdvance = 0;
|
||||||
|
|
||||||
|
// Angle between firing the main (primary) spark and the secondary (trailing) spark
|
||||||
|
angle_t trailingSparkAngle = 0;
|
||||||
|
|
||||||
// fuel-related;
|
// fuel-related;
|
||||||
float fuelCutoffCorrection = 0;
|
float fuelCutoffCorrection = 0;
|
||||||
efitick_t coastingFuelCutStartTime = 0;
|
efitick_t coastingFuelCutStartTime = 0;
|
||||||
|
|
|
@ -99,6 +99,9 @@ public:
|
||||||
scheduling_s dwellStartTimer;
|
scheduling_s dwellStartTimer;
|
||||||
AngleBasedEvent sparkEvent;
|
AngleBasedEvent sparkEvent;
|
||||||
|
|
||||||
|
scheduling_s trailingSparkCharge;
|
||||||
|
scheduling_s trailingSparkFire;
|
||||||
|
|
||||||
// How many additional sparks should we fire after the first one?
|
// How many additional sparks should we fire after the first one?
|
||||||
// For single sparks, this should be zero.
|
// For single sparks, this should be zero.
|
||||||
uint8_t sparksRemaining = 0;
|
uint8_t sparksRemaining = 0;
|
||||||
|
|
|
@ -698,7 +698,7 @@ void initEngineContoller(DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
||||||
* UNUSED_SIZE constants.
|
* UNUSED_SIZE constants.
|
||||||
*/
|
*/
|
||||||
#ifndef RAM_UNUSED_SIZE
|
#ifndef RAM_UNUSED_SIZE
|
||||||
#define RAM_UNUSED_SIZE 1400
|
#define RAM_UNUSED_SIZE 1000
|
||||||
#endif
|
#endif
|
||||||
#ifndef CCM_UNUSED_SIZE
|
#ifndef CCM_UNUSED_SIZE
|
||||||
#define CCM_UNUSED_SIZE 300
|
#define CCM_UNUSED_SIZE 300
|
||||||
|
|
|
@ -128,6 +128,14 @@ static void prepareCylinderIgnitionSchedule(angle_t dwellAngleDuration, floatms_
|
||||||
#endif /* FUEL_MATH_EXTREME_LOGGING */
|
#endif /* FUEL_MATH_EXTREME_LOGGING */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void chargeTrailingSpark(IgnitionOutputPin* pin) {
|
||||||
|
pin->setValue(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fireTrailingSpark(IgnitionOutputPin* pin) {
|
||||||
|
pin->setValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
void fireSparkAndPrepareNextSchedule(IgnitionEvent *event) {
|
void fireSparkAndPrepareNextSchedule(IgnitionEvent *event) {
|
||||||
for (int i = 0; i< MAX_OUTPUTS_FOR_IGNITION;i++) {
|
for (int i = 0; i< MAX_OUTPUTS_FOR_IGNITION;i++) {
|
||||||
IgnitionOutputPin *output = event->outputs[i];
|
IgnitionOutputPin *output = event->outputs[i];
|
||||||
|
@ -186,8 +194,7 @@ if (engineConfiguration->debugMode == DBG_DWELL_METRIC) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are more sparks to fire, schedule them
|
// If there are more sparks to fire, schedule them
|
||||||
if (event->sparksRemaining > 0)
|
if (event->sparksRemaining > 0) {
|
||||||
{
|
|
||||||
event->sparksRemaining--;
|
event->sparksRemaining--;
|
||||||
|
|
||||||
efitick_t nextDwellStart = nowNt + engine->engineState.multispark.delay;
|
efitick_t nextDwellStart = nowNt + engine->engineState.multispark.delay;
|
||||||
|
@ -196,9 +203,16 @@ if (engineConfiguration->debugMode == DBG_DWELL_METRIC) {
|
||||||
// We can schedule both of these right away, since we're going for "asap" not "particular angle"
|
// We can schedule both of these right away, since we're going for "asap" not "particular angle"
|
||||||
engine->executor.scheduleByTimestampNt(&event->dwellStartTimer, nextDwellStart, { &turnSparkPinHigh, event });
|
engine->executor.scheduleByTimestampNt(&event->dwellStartTimer, nextDwellStart, { &turnSparkPinHigh, event });
|
||||||
engine->executor.scheduleByTimestampNt(&event->sparkEvent.scheduling, nextFiring, { fireSparkAndPrepareNextSchedule, event });
|
engine->executor.scheduleByTimestampNt(&event->sparkEvent.scheduling, nextFiring, { fireSparkAndPrepareNextSchedule, event });
|
||||||
}
|
} else {
|
||||||
else
|
if (CONFIG(enableTrailingSparks)) {
|
||||||
{
|
// Trailing sparks are enabled - schedule an event for the corresponding trailing coil
|
||||||
|
scheduleByAngle(
|
||||||
|
&event->trailingSparkFire, nowNt, ENGINE(engineState.trailingSparkAngle),
|
||||||
|
{ &fireTrailingSpark, &enginePins.trailingCoils[event->cylinderNumber] }
|
||||||
|
PASS_ENGINE_PARAMETER_SUFFIX
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// If all events have been scheduled, prepare for next time.
|
// If all events have been scheduled, prepare for next time.
|
||||||
prepareCylinderIgnitionSchedule(dwellAngleDuration, sparkDwell, event PASS_ENGINE_PARAMETER_SUFFIX);
|
prepareCylinderIgnitionSchedule(dwellAngleDuration, sparkDwell, event PASS_ENGINE_PARAMETER_SUFFIX);
|
||||||
}
|
}
|
||||||
|
@ -269,6 +283,15 @@ void turnSparkPinHigh(IgnitionEvent *event) {
|
||||||
startDwellByTurningSparkPinHigh(event, output);
|
startDwellByTurningSparkPinHigh(event, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CONFIG(enableTrailingSparks)) {
|
||||||
|
// Trailing sparks are enabled - schedule an event for the corresponding trailing coil
|
||||||
|
scheduleByAngle(
|
||||||
|
&event->trailingSparkCharge, nowNt, ENGINE(engineState.trailingSparkAngle),
|
||||||
|
{ &chargeTrailingSpark, &enginePins.trailingCoils[event->cylinderNumber] }
|
||||||
|
PASS_ENGINE_PARAMETER_SUFFIX
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool assertNotInIgnitionList(AngleBasedEvent *head, AngleBasedEvent *element) {
|
static bool assertNotInIgnitionList(AngleBasedEvent *head, AngleBasedEvent *element) {
|
||||||
|
|
|
@ -209,6 +209,7 @@ public:
|
||||||
|
|
||||||
InjectorOutputPin injectors[MAX_CYLINDER_COUNT];
|
InjectorOutputPin injectors[MAX_CYLINDER_COUNT];
|
||||||
IgnitionOutputPin coils[MAX_CYLINDER_COUNT];
|
IgnitionOutputPin coils[MAX_CYLINDER_COUNT];
|
||||||
|
IgnitionOutputPin trailingCoils[MAX_CYLINDER_COUNT];
|
||||||
NamedOutputPin auxValve[AUX_DIGITAL_VALVE_COUNT];
|
NamedOutputPin auxValve[AUX_DIGITAL_VALVE_COUNT];
|
||||||
OutputPin tcuSolenoids[TCU_SOLENOID_COUNT];
|
OutputPin tcuSolenoids[TCU_SOLENOID_COUNT];
|
||||||
|
|
||||||
|
|
|
@ -541,7 +541,7 @@ bit enableFan1WithAc;+Turn on this fan when AC is on.
|
||||||
bit enableFan2WithAc;+Turn on this fan when AC is on.
|
bit enableFan2WithAc;+Turn on this fan when AC is on.
|
||||||
bit disableFan1WhenStopped;+Inhibit operation of this fan while the engine is not running.
|
bit disableFan1WhenStopped;+Inhibit operation of this fan while the engine is not running.
|
||||||
bit disableFan2WhenStopped;+Inhibit operation of this fan while the engine is not running.
|
bit disableFan2WhenStopped;+Inhibit operation of this fan while the engine is not running.
|
||||||
bit unused_294_8
|
bit enableTrailingSparks;+Enable secondary spark outputs that fire after the primary (rotaries, twin plug engines).
|
||||||
bit isCJ125Verbose;enable cj125verbose/disable cj125verbose
|
bit isCJ125Verbose;enable cj125verbose/disable cj125verbose
|
||||||
bit cj125isUaDivided;+Is your UA CJ125 output wired to MCU via resistor divider? Ua can go over 3.3v but only at lambda >3, i.e very lean AFR above 44.1\nWhen exposed to free air and 17x gain, Ua will be 4.17 volt
|
bit cj125isUaDivided;+Is your UA CJ125 output wired to MCU via resistor divider? Ua can go over 3.3v but only at lambda >3, i.e very lean AFR above 44.1\nWhen exposed to free air and 17x gain, Ua will be 4.17 volt
|
||||||
bit cj125isLsu49
|
bit cj125isLsu49
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include "engine_test_helper.h"
|
#include "engine_test_helper.h"
|
||||||
#include "spark_logic.h"
|
#include "spark_logic.h"
|
||||||
|
|
||||||
|
using ::testing::_;
|
||||||
|
|
||||||
TEST(ignition, twoCoils) {
|
TEST(ignition, twoCoils) {
|
||||||
WITH_ENGINE_TEST_HELPER(BMW_M73_F);
|
WITH_ENGINE_TEST_HELPER(BMW_M73_F);
|
||||||
|
|
||||||
|
@ -33,9 +35,65 @@ TEST(ignition, twoCoils) {
|
||||||
|
|
||||||
ASSERT_EQ(engine->ignitionEvents.elements[3].sparkAngle, 3 * 720 / 12);
|
ASSERT_EQ(engine->ignitionEvents.elements[3].sparkAngle, 3 * 720 / 12);
|
||||||
ASSERT_EQ((void*)engine->ignitionEvents.elements[3].outputs[0], (void*)&enginePins.coils[6]);
|
ASSERT_EQ((void*)engine->ignitionEvents.elements[3].outputs[0], (void*)&enginePins.coils[6]);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ignition, trailingSpark) {
|
||||||
|
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
|
||||||
|
|
||||||
|
EXPECT_CALL(eth.mockAirmass, getAirmass(_))
|
||||||
|
.WillRepeatedly(Return(AirmassResult{0.1008f, 50.0f}));
|
||||||
|
|
||||||
|
setupSimpleTestEngineWithMafAndTT_ONE_trigger(ð);
|
||||||
|
CONFIG(specs.cylindersCount) = 1;
|
||||||
|
CONFIG(specs.firingOrder) = FO_1;
|
||||||
|
CONFIG(isInjectionEnabled) = false;
|
||||||
|
CONFIG(isIgnitionEnabled) = true;
|
||||||
|
|
||||||
|
// Fire trailing spark 10 degrees after main spark
|
||||||
|
ENGINE(engineState.trailingSparkAngle) = 10;
|
||||||
|
|
||||||
|
engineConfiguration->injectionMode = IM_SEQUENTIAL;
|
||||||
|
|
||||||
|
eth.fireTriggerEventsWithDuration(20);
|
||||||
|
// still no RPM since need to cycles measure cycle duration
|
||||||
|
eth.fireTriggerEventsWithDuration(20);
|
||||||
|
eth.clearQueue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger up - scheduling fuel for full engine cycle
|
||||||
|
*/
|
||||||
|
eth.fireRise(20);
|
||||||
|
|
||||||
|
// Primary coil should be high
|
||||||
|
EXPECT_EQ(enginePins.coils[0].getLogicValue(), true);
|
||||||
|
EXPECT_EQ(enginePins.trailingCoils[0].getLogicValue(), false);
|
||||||
|
|
||||||
|
// Should be a TDC callback + spark firing
|
||||||
|
EXPECT_EQ(engine->executor.size(), 2);
|
||||||
|
|
||||||
|
// execute all actions
|
||||||
|
eth.clearQueue();
|
||||||
|
|
||||||
|
// Primary and secondary coils should be low - primary just fired
|
||||||
|
EXPECT_EQ(enginePins.coils[0].getLogicValue(), false);
|
||||||
|
EXPECT_EQ(enginePins.trailingCoils[0].getLogicValue(), false);
|
||||||
|
|
||||||
|
// Now enable trailing sparks
|
||||||
|
CONFIG(enableTrailingSparks) = true;
|
||||||
|
|
||||||
|
// Fire trigger fall - should schedule ignition chargings (rising edges)
|
||||||
|
eth.fireFall(20);
|
||||||
|
eth.clearQueue();
|
||||||
|
|
||||||
|
// Primary and secondary coils should be low
|
||||||
|
EXPECT_EQ(enginePins.coils[0].getLogicValue(), true);
|
||||||
|
EXPECT_EQ(enginePins.trailingCoils[0].getLogicValue(), true);
|
||||||
|
|
||||||
|
// Fire trigger rise - should schedule ignition firings
|
||||||
|
eth.fireRise(20);
|
||||||
|
eth.clearQueue();
|
||||||
|
|
||||||
|
// Primary and secondary coils should be low
|
||||||
|
EXPECT_EQ(enginePins.coils[0].getLogicValue(), false);
|
||||||
|
EXPECT_EQ(enginePins.trailingCoils[0].getLogicValue(), false);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue