prime upon ignition voltage, not on power on (#3662)

* ignition controller detects rising edge on voltage

* update test

* comment

* ignore negative transients

* tweak

* test

* priming happens on ignition-on

* priming has its own scheduling

* test

* dead adjacent line of code
This commit is contained in:
Matthew Kennedy 2021-12-08 04:26:49 -08:00 committed by GitHub
parent 161d75197d
commit 2050580a16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 23 deletions

View File

@ -108,7 +108,14 @@ protected:
trigger_type_e getType() const override;
};
#define DEFAULT_MOCK_SPEED -1
class PrimeController : public EngineModule {
public:
void onIgnitionStateChanged(bool ignitionOn) override;
private:
scheduling_s m_start;
scheduling_s m_end;
};
class Engine final : public TriggerStateListener {
public:
@ -136,8 +143,6 @@ public:
PinRepository pinRepository;
InjectionEvent primeInjEvent;
IEtbController *etbControllers[ETB_COUNT] = {nullptr};
IFuelComputer *fuelComputer = nullptr;
@ -157,6 +162,7 @@ public:
MainRelayController,
IgnitionController,
AcController,
PrimeController,
EngineModule // dummy placeholder so the previous entries can all have commas
> engineModules;

View File

@ -438,10 +438,14 @@ static bool isPrimeInjectionPulseSkipped() {
}
/**
* Prime injection pulse, mainly needed for mono-injectors or long intake manifolds.
* Prime injection pulse
* See testStartOfCrankingPrimingPulse()
*/
void startPrimeInjectionPulse() {
void PrimeController::onIgnitionStateChanged(bool ignitionOn) {
if (!ignitionOn) {
// don't prime on ignition-off
return;
}
// First, we need a protection against 'fake' ignition switch on and off (i.e. no engine started), to avoid repeated prime pulses.
// So we check and update the ignition switch counter in non-volatile backup-RAM
@ -460,20 +464,28 @@ void startPrimeInjectionPulse() {
ignSwitchCounter = -1;
// start prime injection if this is a 'fresh start'
if (ignSwitchCounter == 0) {
engine->primeInjEvent.ownIndex = 0;
engine->primeInjEvent.isSimultanious = true;
scheduling_s *sDown = &engine->injectionEvents.elements[0].endOfInjectionEvent;
// When the engine is hot, basically we don't need prime inj.pulse, so we use an interpolation over temperature (falloff).
// If 'primeInjFalloffTemperature' is not specified (by default), we have a prime pulse deactivation at zero celsius degrees, which is okay.
const float maxPrimeInjAtTemperature = -40.0f; // at this temperature the pulse is maximal.
floatms_t pulseLength = interpolateClamped(maxPrimeInjAtTemperature, engineConfiguration->startOfCrankingPrimingPulse,
engineConfiguration->primeInjFalloffTemperature, 0.0f, Sensor::get(SensorType::Clt).value_or(70));
efiPrintf("Firing priming pulse of %.2f ms", pulseLength);
if (pulseLength > 0) {
startSimultaniousInjection();
int turnOffDelayUs = efiRound(MS2US(pulseLength), 1.0f);
engine->executor.scheduleForLater(sDown, turnOffDelayUs, { &endSimultaniousInjectionOnlyTogglePins, engine });
auto now = getTimeNowNt();
// TODO: configurable prime delay
auto primeDelayMs = 200;
auto start = now + MS2NT(primeDelayMs);
auto end = start + MS2NT(pulseLength);
engine->executor.scheduleByTimestampNt("prime", &m_start, start, startSimultaniousInjection);
engine->executor.scheduleByTimestampNt("prime", &m_end, end, endSimultaniousInjectionOnlyTogglePins);
}
} else {
efiPrintf("Skipped priming pulse since ignSwitchCounter = %d", ignSwitchCounter);
}
#if EFI_PROD_CODE
// we'll reset it later when the engine starts
@ -511,11 +523,6 @@ void initMainEventListener() {
#if EFI_PROD_CODE
addConsoleActionP("maininfo", (VoidPtr) showMainInfo, engine);
#endif
// We start prime injection pulse at the early init stage - don't wait for the engine to start spinning!
if (engineConfiguration->startOfCrankingPrimingPulse > 0)
startPrimeInjectionPulse();
}
#endif /* EFI_ENGINE_CONTROL */

View File

@ -15,8 +15,6 @@ void initMainEventListener();
void mainTriggerCallback(uint32_t trgEventIndex, efitick_t edgeTimestamp);
void startPrimeInjectionPulse();
void startSimultaniousInjection(void* = nullptr);
void endSimultaniousInjection(InjectionEvent *event);
void turnInjectionPinHigh(InjectionEvent *event);

View File

@ -42,10 +42,9 @@ TEST(engine, testStartOfCrankingPrimingPulse) {
// we need below freezing temperature to get prime fuel
Sensor::setMockValue(SensorType::Clt, -10);
// prod code invokes this on ECU start, here we have to mimic this behavior
startPrimeInjectionPulse();
// Turn on the ignition switch!
engine->module<PrimeController>()->onIgnitionStateChanged(true);
ASSERT_EQ( 1, engine->executor.size()) << "prime fuel";
ASSERT_EQ(2, engine->executor.size()) << "prime fuel";
}