Schedule sparks with scheduleByAngle (#1092)
* injection * injectors * add edge timestamp to ShaftPositionListener * scheduleByAngle require edgeTimestamp * schedule with nt not us * fix all schedulers * schedule spark based on edge timestamp * aux valves too * update comments * schedule dwell with new stamp * format
This commit is contained in:
parent
19df4661ab
commit
e25a93415f
|
@ -33,6 +33,7 @@ void plainPinTurnOn(AuxActor *current) {
|
||||||
|
|
||||||
scheduleOrQueue(¤t->open,
|
scheduleOrQueue(¤t->open,
|
||||||
TRIGGER_EVENT_UNDEFINED,
|
TRIGGER_EVENT_UNDEFINED,
|
||||||
|
getTimeNowNt(),
|
||||||
current->extra + engine->engineState.auxValveStart,
|
current->extra + engine->engineState.auxValveStart,
|
||||||
{ plainPinTurnOn, current }
|
{ plainPinTurnOn, current }
|
||||||
PASS_ENGINE_PARAMETER_SUFFIX
|
PASS_ENGINE_PARAMETER_SUFFIX
|
||||||
|
@ -44,6 +45,7 @@ void plainPinTurnOn(AuxActor *current) {
|
||||||
|
|
||||||
scheduleOrQueue(¤t->close,
|
scheduleOrQueue(¤t->close,
|
||||||
TRIGGER_EVENT_UNDEFINED,
|
TRIGGER_EVENT_UNDEFINED,
|
||||||
|
getTimeNowNt(),
|
||||||
current->extra + engine->engineState.auxValveEnd,
|
current->extra + engine->engineState.auxValveEnd,
|
||||||
{ plainPinTurnOff, output }
|
{ plainPinTurnOff, output }
|
||||||
PASS_ENGINE_PARAMETER_SUFFIX
|
PASS_ENGINE_PARAMETER_SUFFIX
|
||||||
|
@ -148,6 +150,7 @@ void initAuxValves(Logging *sharedLogger DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
||||||
|
|
||||||
scheduleOrQueue(&actor->open,
|
scheduleOrQueue(&actor->open,
|
||||||
TRIGGER_EVENT_UNDEFINED,
|
TRIGGER_EVENT_UNDEFINED,
|
||||||
|
getTimeNowNt(),
|
||||||
actor->extra + engine->engineState.auxValveStart,
|
actor->extra + engine->engineState.auxValveStart,
|
||||||
{ plainPinTurnOn, actor }
|
{ plainPinTurnOn, actor }
|
||||||
PASS_ENGINE_PARAMETER_SUFFIX
|
PASS_ENGINE_PARAMETER_SUFFIX
|
||||||
|
|
|
@ -509,7 +509,7 @@ static void mainTriggerCallback(trigger_event_e ckpSignalType, uint32_t trgEvent
|
||||||
/**
|
/**
|
||||||
* For spark we schedule both start of coil charge and actual spark based on trigger angle
|
* For spark we schedule both start of coil charge and actual spark based on trigger angle
|
||||||
*/
|
*/
|
||||||
onTriggerEventSparkLogic(limitedSpark, trgEventIndex, rpm PASS_ENGINE_PARAMETER_SUFFIX);
|
onTriggerEventSparkLogic(limitedSpark, trgEventIndex, rpm, edgeTimestamp PASS_ENGINE_PARAMETER_SUFFIX);
|
||||||
|
|
||||||
if (trgEventIndex == 0) {
|
if (trgEventIndex == 0) {
|
||||||
ENGINE(m.mainTriggerCallbackTime) = getTimeNowLowerNt() - ENGINE(m.beforeMainTrigger);
|
ENGINE(m.mainTriggerCallbackTime) = getTimeNowLowerNt() - ENGINE(m.beforeMainTrigger);
|
||||||
|
|
|
@ -124,7 +124,8 @@ static void prepareCylinderIgnitionSchedule(angle_t dwellAngleDuration, floatms_
|
||||||
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];
|
||||||
if (output != NULL) {
|
|
||||||
|
if (output) {
|
||||||
fireSparkBySettingPinLow(event, output);
|
fireSparkBySettingPinLow(event, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,7 +150,7 @@ if (engineConfiguration->debugMode == DBG_DWELL_METRIC) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* EFI_UNIT_TEST */
|
#endif /* EFI_UNIT_TEST */
|
||||||
#if EFI_UNIT_TEST
|
#if EFI_UNIT_TEST
|
||||||
Engine *engine = event->engine;
|
Engine *engine = event->engine;
|
||||||
|
@ -226,34 +227,32 @@ static bool assertNotInIgnitionList(AngleBasedEvent *head, AngleBasedEvent *elem
|
||||||
*/
|
*/
|
||||||
bool scheduleOrQueue(AngleBasedEvent *event,
|
bool scheduleOrQueue(AngleBasedEvent *event,
|
||||||
uint32_t trgEventIndex,
|
uint32_t trgEventIndex,
|
||||||
|
efitick_t edgeTimestamp,
|
||||||
angle_t angle,
|
angle_t angle,
|
||||||
action_s action
|
action_s action
|
||||||
DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
||||||
event->position.setAngle(angle PASS_ENGINE_PARAMETER_SUFFIX);
|
event->position.setAngle(angle PASS_ENGINE_PARAMETER_SUFFIX);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* todo: extract a "scheduleForAngle" method with best implementation into a separate utility method
|
* Here's the status as of Jan 2020:
|
||||||
*
|
* Once we hit the last trigger tooth prior to needed event, schedule it by time. We use as much trigger position angle as possible
|
||||||
* Here's the status as of Nov 2018:
|
|
||||||
* "scheduleForLater" uses time only and for best precision it's best to use "scheduleForLater" only
|
|
||||||
* once we hit the last trigger tooth prior to needed event. This case we use as much trigger position angle as possible
|
|
||||||
* and only use less precise RPM-based time calculation for the last portion of the angle, the one between two teeth closest to the
|
* and only use less precise RPM-based time calculation for the last portion of the angle, the one between two teeth closest to the
|
||||||
* desired angle moment.
|
* desired angle moment.
|
||||||
*
|
|
||||||
* At the moment we only have time-based scheduler. I believe what needs to be added is a trigger-event based scheduler on top of the
|
|
||||||
* time-based schedule. This case we would be firing events with best possible angle precision.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
if (trgEventIndex != TRIGGER_EVENT_UNDEFINED && event->position.triggerEventIndex == trgEventIndex) {
|
if (trgEventIndex != TRIGGER_EVENT_UNDEFINED && event->position.triggerEventIndex == trgEventIndex) {
|
||||||
/**
|
/**
|
||||||
* Spark should be fired before the next trigger event - time-based delay is best precision possible
|
* Spark should be fired before the next trigger event - time-based delay is best precision possible
|
||||||
*/
|
*/
|
||||||
float timeTillIgnitionUs = ENGINE(rpmCalculator.oneDegreeUs) * event->position.angleOffsetFromTriggerEvent;
|
|
||||||
|
|
||||||
|
|
||||||
scheduling_s * sDown = &event->scheduling;
|
scheduling_s * sDown = &event->scheduling;
|
||||||
|
|
||||||
engine->executor.scheduleForLater(sDown, (int) timeTillIgnitionUs, action);
|
scheduleByAngle(
|
||||||
|
sDown,
|
||||||
|
edgeTimestamp,
|
||||||
|
event->position.angleOffsetFromTriggerEvent,
|
||||||
|
action
|
||||||
|
PASS_ENGINE_PARAMETER_SUFFIX
|
||||||
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
event->action = action;
|
event->action = action;
|
||||||
|
@ -273,7 +272,7 @@ bool scheduleOrQueue(AngleBasedEvent *event,
|
||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE void handleSparkEvent(bool limitedSpark, uint32_t trgEventIndex, IgnitionEvent *iEvent,
|
static ALWAYS_INLINE void handleSparkEvent(bool limitedSpark, uint32_t trgEventIndex, IgnitionEvent *iEvent,
|
||||||
int rpm DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
int rpm, efitick_t edgeTimestamp DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
||||||
|
|
||||||
angle_t sparkAngle = iEvent->sparkAngle;
|
angle_t sparkAngle = iEvent->sparkAngle;
|
||||||
const floatms_t dwellMs = ENGINE(engineState.sparkDwell);
|
const floatms_t dwellMs = ENGINE(engineState.sparkDwell);
|
||||||
|
@ -321,18 +320,17 @@ static ALWAYS_INLINE void handleSparkEvent(bool limitedSpark, uint32_t trgEventI
|
||||||
* This way we make sure that coil dwell started while spark was enabled would fire and not burn
|
* This way we make sure that coil dwell started while spark was enabled would fire and not burn
|
||||||
* the coil.
|
* the coil.
|
||||||
*/
|
*/
|
||||||
engine->executor.scheduleForLater(sUp, chargeDelayUs, { &turnSparkPinHigh, iEvent });
|
engine->executor.scheduleByTimestampNt(sUp, edgeTimestamp + US2NT(chargeDelayUs), { &turnSparkPinHigh, iEvent });
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Spark event is often happening during a later trigger event timeframe
|
* Spark event is often happening during a later trigger event timeframe
|
||||||
* TODO: improve precision
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
efiAssertVoid(CUSTOM_ERR_6591, !cisnan(sparkAngle), "findAngle#4");
|
efiAssertVoid(CUSTOM_ERR_6591, !cisnan(sparkAngle), "findAngle#4");
|
||||||
assertAngleRange(sparkAngle, "findAngle#a5", CUSTOM_ERR_6549);
|
assertAngleRange(sparkAngle, "findAngle#a5", CUSTOM_ERR_6549);
|
||||||
|
|
||||||
|
|
||||||
bool scheduled = scheduleOrQueue(&iEvent->sparkEvent, trgEventIndex, sparkAngle, { fireSparkAndPrepareNextSchedule, iEvent } PASS_ENGINE_PARAMETER_SUFFIX);
|
bool scheduled = scheduleOrQueue(&iEvent->sparkEvent, trgEventIndex, edgeTimestamp, sparkAngle, { fireSparkAndPrepareNextSchedule, iEvent } PASS_ENGINE_PARAMETER_SUFFIX);
|
||||||
|
|
||||||
if (scheduled) {
|
if (scheduled) {
|
||||||
#if SPARK_EXTREME_LOGGING
|
#if SPARK_EXTREME_LOGGING
|
||||||
|
@ -408,7 +406,7 @@ static ALWAYS_INLINE void prepareIgnitionSchedule(DECLARE_ENGINE_PARAMETER_SIGNA
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void scheduleAllSparkEventsUntilNextTriggerTooth(uint32_t trgEventIndex DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
static void scheduleAllSparkEventsUntilNextTriggerTooth(uint32_t trgEventIndex, efitick_t edgeTimestamp DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
||||||
AngleBasedEvent *current, *tmp;
|
AngleBasedEvent *current, *tmp;
|
||||||
|
|
||||||
LL_FOREACH_SAFE2(ENGINE(angleBasedEventsHead), current, tmp, nextToothEvent)
|
LL_FOREACH_SAFE2(ENGINE(angleBasedEventsHead), current, tmp, nextToothEvent)
|
||||||
|
@ -423,14 +421,18 @@ static void scheduleAllSparkEventsUntilNextTriggerTooth(uint32_t trgEventIndex D
|
||||||
scheduleMsg(logger, "time to invoke ind=%d %d %d", trgEventIndex, getRevolutionCounter(), (int)getTimeNowUs());
|
scheduleMsg(logger, "time to invoke ind=%d %d %d", trgEventIndex, getRevolutionCounter(), (int)getTimeNowUs());
|
||||||
#endif /* FUEL_MATH_EXTREME_LOGGING */
|
#endif /* FUEL_MATH_EXTREME_LOGGING */
|
||||||
|
|
||||||
|
scheduleByAngle(
|
||||||
float timeTillIgnitionUs = ENGINE(rpmCalculator.oneDegreeUs) * current->position.angleOffsetFromTriggerEvent;
|
sDown,
|
||||||
engine->executor.scheduleForLater(sDown, (int) timeTillIgnitionUs, current->action);
|
edgeTimestamp,
|
||||||
|
current->position.angleOffsetFromTriggerEvent,
|
||||||
|
current->action
|
||||||
|
PASS_ENGINE_PARAMETER_SUFFIX
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onTriggerEventSparkLogic(bool limitedSpark, uint32_t trgEventIndex, int rpm
|
void onTriggerEventSparkLogic(bool limitedSpark, uint32_t trgEventIndex, int rpm, efitick_t edgeTimestamp
|
||||||
DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
||||||
|
|
||||||
ScopePerf perf(PE::OnTriggerEventSparkLogic);
|
ScopePerf perf(PE::OnTriggerEventSparkLogic);
|
||||||
|
@ -449,7 +451,7 @@ void onTriggerEventSparkLogic(bool limitedSpark, uint32_t trgEventIndex, int rpm
|
||||||
* Ignition schedule is defined once per revolution
|
* Ignition schedule is defined once per revolution
|
||||||
* See initializeIgnitionActions()
|
* See initializeIgnitionActions()
|
||||||
*/
|
*/
|
||||||
scheduleAllSparkEventsUntilNextTriggerTooth(trgEventIndex PASS_ENGINE_PARAMETER_SUFFIX);
|
scheduleAllSparkEventsUntilNextTriggerTooth(trgEventIndex, edgeTimestamp PASS_ENGINE_PARAMETER_SUFFIX);
|
||||||
|
|
||||||
|
|
||||||
// scheduleSimpleMsg(&logger, "eventId spark ", eventIndex);
|
// scheduleSimpleMsg(&logger, "eventId spark ", eventIndex);
|
||||||
|
@ -458,7 +460,7 @@ void onTriggerEventSparkLogic(bool limitedSpark, uint32_t trgEventIndex, int rpm
|
||||||
IgnitionEvent *event = &ENGINE(ignitionEvents.elements[i]);
|
IgnitionEvent *event = &ENGINE(ignitionEvents.elements[i]);
|
||||||
if (event->dwellPosition.triggerEventIndex != trgEventIndex)
|
if (event->dwellPosition.triggerEventIndex != trgEventIndex)
|
||||||
continue;
|
continue;
|
||||||
handleSparkEvent(limitedSpark, trgEventIndex, event, rpm PASS_ENGINE_PARAMETER_SUFFIX);
|
handleSparkEvent(limitedSpark, trgEventIndex, event, rpm, edgeTimestamp PASS_ENGINE_PARAMETER_SUFFIX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
|
||||||
int isInjectionEnabled(DECLARE_ENGINE_PARAMETER_SIGNATURE);
|
int isInjectionEnabled(DECLARE_ENGINE_PARAMETER_SIGNATURE);
|
||||||
void onTriggerEventSparkLogic(bool limitedSpark, uint32_t trgEventIndex, int rpm DECLARE_ENGINE_PARAMETER_SUFFIX);
|
void onTriggerEventSparkLogic(bool limitedSpark, uint32_t trgEventIndex, int rpm, efitick_t edgeTimestamp DECLARE_ENGINE_PARAMETER_SUFFIX);
|
||||||
void initSparkLogic(Logging *sharedLogger);
|
void initSparkLogic(Logging *sharedLogger);
|
||||||
void turnSparkPinHigh(IgnitionEvent *event);
|
void turnSparkPinHigh(IgnitionEvent *event);
|
||||||
void fireSparkAndPrepareNextSchedule(IgnitionEvent *event);
|
void fireSparkAndPrepareNextSchedule(IgnitionEvent *event);
|
||||||
|
@ -23,6 +23,7 @@ int isIgnitionTimingError(void);
|
||||||
#define TRIGGER_EVENT_UNDEFINED -1
|
#define TRIGGER_EVENT_UNDEFINED -1
|
||||||
bool scheduleOrQueue(AngleBasedEvent *event,
|
bool scheduleOrQueue(AngleBasedEvent *event,
|
||||||
uint32_t trgEventIndex,
|
uint32_t trgEventIndex,
|
||||||
|
efitick_t edgeTimestamp,
|
||||||
angle_t angle,
|
angle_t angle,
|
||||||
action_s action
|
action_s action
|
||||||
DECLARE_ENGINE_PARAMETER_SUFFIX);
|
DECLARE_ENGINE_PARAMETER_SUFFIX);
|
||||||
|
|
Loading…
Reference in New Issue