diff --git a/firmware/console/status_loop.cpp b/firmware/console/status_loop.cpp index ef91b33dff..0911ab6870 100644 --- a/firmware/console/status_loop.cpp +++ b/firmware/console/status_loop.cpp @@ -851,7 +851,7 @@ void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels DECLARE_ break; case DBG_INSTANT_RPM: { - float instantRpm = engine->triggerCentral.triggerState.instantRpm; + float instantRpm = engine->triggerCentral.triggerState.getInstantRpm(); tsOutputChannels->debugFloatField1 = instantRpm; tsOutputChannels->debugFloatField2 = instantRpm / GET_RPM(); } diff --git a/firmware/controllers/actuators/idle_thread.cpp b/firmware/controllers/actuators/idle_thread.cpp index 7f0fc4cdb6..dd8746aef2 100644 --- a/firmware/controllers/actuators/idle_thread.cpp +++ b/firmware/controllers/actuators/idle_thread.cpp @@ -289,6 +289,10 @@ float IdleController::getIdleTimingAdjustment(int rpm, int targetRpm, Phase phas return 0; } + if (CONFIG(useInstantRpmForIdle)) { + rpm = engine->triggerCentral.triggerState.getInstantRpm(); + } + // If inside the deadzone, do nothing if (absI(rpm - targetRpm) < CONFIG(idleTimingPidDeadZone)) { m_timingPid.reset(); @@ -454,8 +458,7 @@ static percent_t automaticIdleController(float tpsPos, float rpm, int targetRpm, float rpm; if (CONFIG(useInstantRpmForIdle)) { - efitick_t nowNt = getTimeNowNt(); - rpm = engine->triggerCentral.triggerState.calculateInstantRpm(&engine->triggerCentral.triggerFormDetails, NULL, nowNt PASS_ENGINE_PARAMETER_SUFFIX); + rpm = engine->triggerCentral.triggerState.getInstantRpm(); } else { rpm = GET_RPM(); } diff --git a/firmware/controllers/algo/engine.cpp b/firmware/controllers/algo/engine.cpp index 0b2a2eba98..2d3bd8a71c 100644 --- a/firmware/controllers/algo/engine.cpp +++ b/firmware/controllers/algo/engine.cpp @@ -397,10 +397,6 @@ void Engine::OnTriggerStateProperState(efitick_t nowNt) { Engine *engine = this; EXPAND_Engine; -#if EFI_SHAFT_POSITION_INPUT - triggerCentral.triggerState.runtimeStatistics(&triggerCentral.triggerFormDetails, nowNt PASS_ENGINE_PARAMETER_SUFFIX); -#endif /* EFI_SHAFT_POSITION_INPUT */ - rpmCalculator.setSpinningUp(nowNt); } diff --git a/firmware/controllers/algo/obd_error_codes.h b/firmware/controllers/algo/obd_error_codes.h index 3fb1ceb1f8..c35b2b9b99 100644 --- a/firmware/controllers/algo/obd_error_codes.h +++ b/firmware/controllers/algo/obd_error_codes.h @@ -1736,7 +1736,7 @@ typedef enum { CUSTOM_OBD_PIN_CONFLICT = 6048, CUSTOM_OBD_LOW_FREQUENCY = 6049, - CUSTOM_OBD_ZERO_CYLINDER_COUNT = 6051, + CUSTOM_6051 = 6051, CUSTOM_OBD_TS_PAGE_MISMATCH = 6052, CUSTOM_OBD_TS_OUTPUT_MISMATCH = 6053, CUSTOM_TOO_LONG_CRANKING_FUEL_INJECTION = 6054, diff --git a/firmware/controllers/date_stamp.h b/firmware/controllers/date_stamp.h index 79b96a78d4..a5e5490832 100644 --- a/firmware/controllers/date_stamp.h +++ b/firmware/controllers/date_stamp.h @@ -1,2 +1,2 @@ #pragma once -#define VCS_DATE 20210112 +#define VCS_DATE 20210115 diff --git a/firmware/controllers/engine_cycle/fuel_schedule.cpp b/firmware/controllers/engine_cycle/fuel_schedule.cpp index 79a7e62084..f9d13d8d01 100644 --- a/firmware/controllers/engine_cycle/fuel_schedule.cpp +++ b/firmware/controllers/engine_cycle/fuel_schedule.cpp @@ -52,15 +52,15 @@ bool FuelSchedule::addFuelEventsForCylinder(int i DECLARE_ENGINE_PARAMETER_SUFF */ floatms_t fuelMs = ENGINE(injectionDuration); efiAssert(CUSTOM_ERR_ASSERT, !cisnan(fuelMs), "NaN fuelMs", false); - angle_t injectionDuration = MS2US(fuelMs) / oneDegreeUs; - efiAssert(CUSTOM_ERR_ASSERT, !cisnan(injectionDuration), "NaN injectionDuration", false); - assertAngleRange(injectionDuration, "injectionDuration_r", CUSTOM_INJ_DURATION); + angle_t injectionDurationAngle = MS2US(fuelMs) / oneDegreeUs; + efiAssert(CUSTOM_ERR_ASSERT, !cisnan(injectionDurationAngle), "NaN injectionDurationAngle", false); + assertAngleRange(injectionDurationAngle, "injectionDuration_r", CUSTOM_INJ_DURATION); floatus_t injectionOffset = ENGINE(engineState.injectionOffset); if (cisnan(injectionOffset)) { // injection offset map not ready - we are not ready to schedule fuel events return false; } - angle_t baseAngle = injectionOffset - injectionDuration; + angle_t baseAngle = injectionOffset - injectionDurationAngle; efiAssert(CUSTOM_ERR_ASSERT, !cisnan(baseAngle), "NaN baseAngle", false); assertAngleRange(baseAngle, "baseAngle_r", CUSTOM_ERR_6554); @@ -81,18 +81,6 @@ bool FuelSchedule::addFuelEventsForCylinder(int i DECLARE_ENGINE_PARAMETER_SUFF injectorIndex = 0; } - assertAngleRange(baseAngle, "addFbaseAngle", CUSTOM_ADD_BASE); - - int cylindersCount = CONFIG(specs.cylindersCount); - if (cylindersCount < 1) { - // May 2020 this somehow still happens with functional tests, maybe race condition? - warning(CUSTOM_OBD_ZERO_CYLINDER_COUNT, "Invalid cylinder count: %d", cylindersCount); - return false; - } - - float angle = baseAngle - + i * ENGINE(engineCycle) / cylindersCount; - InjectorOutputPin *secondOutput; if (mode == IM_BATCH && CONFIG(twoWireBatchInjection)) { /** @@ -111,20 +99,22 @@ bool FuelSchedule::addFuelEventsForCylinder(int i DECLARE_ENGINE_PARAMETER_SUFF InjectorOutputPin *output = &enginePins.injectors[injectorIndex]; bool isSimultanious = mode == IM_SIMULTANEOUS; + InjectionEvent *ev = &elements[i]; + INJECT_ENGINE_REFERENCE(ev); + + ev->ownIndex = i; + ev->outputs[0] = output; + ev->outputs[1] = secondOutput; + ev->isSimultanious = isSimultanious; + if (!isSimultanious && !output->isInitialized()) { // todo: extract method for this index math warning(CUSTOM_OBD_INJECTION_NO_PIN_ASSIGNED, "no_pin_inj #%s", output->name); } - InjectionEvent *ev = &elements[i]; - ev->ownIndex = i; - INJECT_ENGINE_REFERENCE(ev); - fixAngle(angle, "addFuel#1", CUSTOM_ERR_6554); + angle_t ignitionPositionWithinEngineCycle = ENGINE(ignitionPositionWithinEngineCycle[i]); - ev->outputs[0] = output; - ev->outputs[1] = secondOutput; - - ev->isSimultanious = isSimultanious; + float angle = baseAngle + ignitionPositionWithinEngineCycle; if (TRIGGER_WAVEFORM(getSize()) < 1) { warning(CUSTOM_ERR_NOT_INITIALIZED_TRIGGER, "uninitialized TriggerWaveform"); diff --git a/firmware/controllers/engine_cycle/rpm_calculator.cpp b/firmware/controllers/engine_cycle/rpm_calculator.cpp index dd91898133..2f2d23771e 100644 --- a/firmware/controllers/engine_cycle/rpm_calculator.cpp +++ b/firmware/controllers/engine_cycle/rpm_calculator.cpp @@ -295,9 +295,14 @@ void rpmShaftPositionCallback(trigger_event_e ckpSignalType, // while transitioning from 'spinning' to 'running' // Replace 'normal' RPM with instant RPM for the initial spin-up period engine->triggerCentral.triggerState.movePreSynchTimestamps(PASS_ENGINE_PARAMETER_SIGNATURE); - int prevIndex; - float instantRpm = engine->triggerCentral.triggerState.calculateInstantRpm(&engine->triggerCentral.triggerFormDetails, - &prevIndex, nowNt PASS_ENGINE_PARAMETER_SUFFIX); + } + + // Always update instant RPM even when not spinning up + engine->triggerCentral.triggerState.updateInstantRpm(&engine->triggerCentral.triggerFormDetails, nowNt PASS_ENGINE_PARAMETER_SUFFIX); + + if (rpmState->isSpinningUp()) { + float instantRpm = engine->triggerCentral.triggerState.getInstantRpm(); + // validate instant RPM - we shouldn't skip the cranking state instantRpm = minF(instantRpm, CONFIG(cranking.rpm) - 1); rpmState->assignRpmValue(instantRpm); diff --git a/firmware/controllers/trigger/trigger_decoder.cpp b/firmware/controllers/trigger/trigger_decoder.cpp index 8756559660..cd5f74361e 100644 --- a/firmware/controllers/trigger/trigger_decoder.cpp +++ b/firmware/controllers/trigger/trigger_decoder.cpp @@ -211,8 +211,7 @@ void TriggerStateWithRunningStatistics::movePreSynchTimestamps(DECLARE_ENGINE_PA } } -float TriggerStateWithRunningStatistics::calculateInstantRpm(TriggerFormDetails *triggerFormDetails, - int *prevIndexOut, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) { +float TriggerStateWithRunningStatistics::calculateInstantRpm(TriggerFormDetails *triggerFormDetails, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) { int current_index = currentCycle.current_index; // local copy so that noone changes the value on us assertIsInBoundsWithResult(current_index, timeOfLastEvent, "calc timeOfLastEvent", 0); timeOfLastEvent[current_index] = nowNt; @@ -229,10 +228,6 @@ float TriggerStateWithRunningStatistics::calculateInstantRpm(TriggerFormDetails // todo: prevIndex should be pre-calculated int prevIndex = triggerFormDetails->triggerIndexByAngle[(int)previousAngle]; - if (prevIndexOut) { - *prevIndexOut = prevIndex; - } - // now let's get precise angle for that event angle_t prevIndexAngle = triggerFormDetails->eventAngles[prevIndex]; efitick_t time90ago = timeOfLastEvent[prevIndex]; @@ -255,10 +250,14 @@ float TriggerStateWithRunningStatistics::calculateInstantRpm(TriggerFormDetails instantRpmValue[current_index] = instantRpm; // This fixes early RPM instability based on incomplete data - if (instantRpm < RPM_LOW_THRESHOLD) + if (instantRpm < RPM_LOW_THRESHOLD) { return prevInstantRpmValue; + } + prevInstantRpmValue = instantRpm; + m_instantRpmRatio = instantRpm / instantRpmValue[prevIndex]; + return instantRpm; } @@ -276,23 +275,20 @@ void TriggerStateWithRunningStatistics::setLastEventTimeForInstantRpm(efitick_t spinningEvents[spinningEventIndex++] = nowNt; } -void TriggerStateWithRunningStatistics::runtimeStatistics(TriggerFormDetails *triggerFormDetails, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) { - if (engineConfiguration->debugMode == DBG_INSTANT_RPM) { - instantRpm = calculateInstantRpm(triggerFormDetails, NULL, nowNt PASS_ENGINE_PARAMETER_SUFFIX); - } - if (ENGINE(sensorChartMode) == SC_RPM_ACCEL || ENGINE(sensorChartMode) == SC_DETAILED_RPM) { - int prevIndex; - instantRpm = calculateInstantRpm(triggerFormDetails, &prevIndex, nowNt PASS_ENGINE_PARAMETER_SUFFIX); +void TriggerStateWithRunningStatistics::updateInstantRpm(TriggerFormDetails *triggerFormDetails, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) { + m_instantRpm = calculateInstantRpm(triggerFormDetails, nowNt PASS_ENGINE_PARAMETER_SUFFIX); + #if EFI_SENSOR_CHART + if (ENGINE(sensorChartMode) == SC_RPM_ACCEL || ENGINE(sensorChartMode) == SC_DETAILED_RPM) { angle_t currentAngle = triggerFormDetails->eventAngles[currentCycle.current_index]; if (CONFIG(sensorChartMode) == SC_DETAILED_RPM) { - scAddData(currentAngle, instantRpm); + scAddData(currentAngle, m_instantRpm); } else { - scAddData(currentAngle, instantRpm / instantRpmValue[prevIndex]); + scAddData(currentAngle, m_instantRpmRatio); } -#endif /* EFI_SENSOR_CHART */ } +#endif /* EFI_SENSOR_CHART */ } bool TriggerState::isValidIndex(const TriggerWaveform& triggerShape) const { diff --git a/firmware/controllers/trigger/trigger_decoder.h b/firmware/controllers/trigger/trigger_decoder.h index 925f2046a4..eb90689e89 100644 --- a/firmware/controllers/trigger/trigger_decoder.h +++ b/firmware/controllers/trigger/trigger_decoder.h @@ -169,7 +169,11 @@ private: class TriggerStateWithRunningStatistics : public TriggerState { public: TriggerStateWithRunningStatistics(); - float instantRpm = 0; + + float getInstantRpm() const { + return m_instantRpm; + } + /** * timestamp of each trigger wheel tooth */ @@ -187,15 +191,22 @@ public: */ float prevInstantRpmValue = 0; void movePreSynchTimestamps(DECLARE_ENGINE_PARAMETER_SIGNATURE); - float calculateInstantRpm(TriggerFormDetails *triggerFormDetails, int *prevIndex, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX); + #if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT - void runtimeStatistics(TriggerFormDetails *triggerFormDetails, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX); + void updateInstantRpm(TriggerFormDetails *triggerFormDetails, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX); #endif /** * Update timeOfLastEvent[] on every trigger event - even without synchronization * Needed for early spin-up RPM detection. */ void setLastEventTimeForInstantRpm(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX); + +private: + float calculateInstantRpm(TriggerFormDetails *triggerFormDetails, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX); + + float m_instantRpm = 0; + float m_instantRpmRatio = 0; + }; angle_t getEngineCycle(operation_mode_e operationMode);