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);
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(ð);
|
||||
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