From 2050580a166b52617fa1ae1a3c213513cb67ac5d Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Wed, 8 Dec 2021 04:26:49 -0800 Subject: [PATCH] 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 --- firmware/controllers/algo/engine.h | 12 +++++-- .../engine_cycle/main_trigger_callback.cpp | 35 +++++++++++-------- .../engine_cycle/main_trigger_callback.h | 2 -- .../test_startOfCrankingPrimingPulse.cpp | 7 ++-- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/firmware/controllers/algo/engine.h b/firmware/controllers/algo/engine.h index d85c20219b..b8104e2d75 100644 --- a/firmware/controllers/algo/engine.h +++ b/firmware/controllers/algo/engine.h @@ -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; diff --git a/firmware/controllers/engine_cycle/main_trigger_callback.cpp b/firmware/controllers/engine_cycle/main_trigger_callback.cpp index addef0fb10..9e207f7cc1 100644 --- a/firmware/controllers/engine_cycle/main_trigger_callback.cpp +++ b/firmware/controllers/engine_cycle/main_trigger_callback.cpp @@ -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 */ diff --git a/firmware/controllers/engine_cycle/main_trigger_callback.h b/firmware/controllers/engine_cycle/main_trigger_callback.h index b4469b877a..3b3e2ad0b0 100644 --- a/firmware/controllers/engine_cycle/main_trigger_callback.h +++ b/firmware/controllers/engine_cycle/main_trigger_callback.h @@ -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); diff --git a/unit_tests/tests/ignition_injection/test_startOfCrankingPrimingPulse.cpp b/unit_tests/tests/ignition_injection/test_startOfCrankingPrimingPulse.cpp index 92ccc1b4b7..26dedf9a55 100644 --- a/unit_tests/tests/ignition_injection/test_startOfCrankingPrimingPulse.cpp +++ b/unit_tests/tests/ignition_injection/test_startOfCrankingPrimingPulse.cpp @@ -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()->onIgnitionStateChanged(true); - - ASSERT_EQ( 1, engine->executor.size()) << "prime fuel"; + ASSERT_EQ(2, engine->executor.size()) << "prime fuel"; }