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:
Matthew Kennedy 2021-07-09 05:37:46 -07:00 committed by GitHub
parent dec1f1daff
commit 86683afca2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 102 additions and 9 deletions

View File

@ -171,6 +171,10 @@ void EngineState::periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
float ignitionLoad = getIgnitionLoad(PASS_ENGINE_PARAMETER_SIGNATURE);
timingAdvance = getAdvance(rpm, ignitionLoad PASS_ENGINE_PARAMETER_SUFFIX);
// TODO: calculate me from a table!
trailingSparkAngle = 10;
multispark.count = getMultiSparkCount(rpm PASS_ENGINE_PARAMETER_SUFFIX);
#if EFI_LAUNCH_CONTROL

View File

@ -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"
*/
angle_t timingAdvance = 0;
// Angle between firing the main (primary) spark and the secondary (trailing) spark
angle_t trailingSparkAngle = 0;
// fuel-related;
float fuelCutoffCorrection = 0;
efitick_t coastingFuelCutStartTime = 0;

View File

@ -99,6 +99,9 @@ public:
scheduling_s dwellStartTimer;
AngleBasedEvent sparkEvent;
scheduling_s trailingSparkCharge;
scheduling_s trailingSparkFire;
// How many additional sparks should we fire after the first one?
// For single sparks, this should be zero.
uint8_t sparksRemaining = 0;

View File

@ -698,7 +698,7 @@ void initEngineContoller(DECLARE_ENGINE_PARAMETER_SUFFIX) {
* UNUSED_SIZE constants.
*/
#ifndef RAM_UNUSED_SIZE
#define RAM_UNUSED_SIZE 1400
#define RAM_UNUSED_SIZE 1000
#endif
#ifndef CCM_UNUSED_SIZE
#define CCM_UNUSED_SIZE 300

View File

@ -128,6 +128,14 @@ static void prepareCylinderIgnitionSchedule(angle_t dwellAngleDuration, floatms_
#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) {
for (int i = 0; i< MAX_OUTPUTS_FOR_IGNITION;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 (event->sparksRemaining > 0)
{
if (event->sparksRemaining > 0) {
event->sparksRemaining--;
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"
engine->executor.scheduleByTimestampNt(&event->dwellStartTimer, nextDwellStart, { &turnSparkPinHigh, 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.
prepareCylinderIgnitionSchedule(dwellAngleDuration, sparkDwell, event PASS_ENGINE_PARAMETER_SUFFIX);
}
@ -269,6 +283,15 @@ void turnSparkPinHigh(IgnitionEvent *event) {
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) {

View File

@ -209,6 +209,7 @@ public:
InjectorOutputPin injectors[MAX_CYLINDER_COUNT];
IgnitionOutputPin coils[MAX_CYLINDER_COUNT];
IgnitionOutputPin trailingCoils[MAX_CYLINDER_COUNT];
NamedOutputPin auxValve[AUX_DIGITAL_VALVE_COUNT];
OutputPin tcuSolenoids[TCU_SOLENOID_COUNT];

View File

@ -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 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 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 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

View File

@ -8,6 +8,8 @@
#include "engine_test_helper.h"
#include "spark_logic.h"
using ::testing::_;
TEST(ignition, twoCoils) {
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((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(&eth);
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);
}