From 3a8313a94aa972fe45b05c3abd16309b4cbdf3a7 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sun, 28 Feb 2021 13:56:34 -1000 Subject: [PATCH] try rpm calculator timer (#2053) * add api * rpm calculator * fix fsio * fix float * remove wrong comment * fix timer * clang didn't like this * oops * format Co-authored-by: Matthew Kennedy --- .../engine_cycle/rpm_calculator.cpp | 36 +++++++++---------- .../controllers/engine_cycle/rpm_calculator.h | 4 ++- firmware/controllers/math/engine_math.h | 5 --- 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/firmware/controllers/engine_cycle/rpm_calculator.cpp b/firmware/controllers/engine_cycle/rpm_calculator.cpp index 2f2d23771e..f7a581eb34 100644 --- a/firmware/controllers/engine_cycle/rpm_calculator.cpp +++ b/firmware/controllers/engine_cycle/rpm_calculator.cpp @@ -94,9 +94,6 @@ RpmCalculator::RpmCalculator() : #endif /* EFI_PROD_CODE */ // todo: reuse assignRpmValue() method which needs PASS_ENGINE_PARAMETER_SUFFIX // which we cannot provide inside this parameter-less constructor. need a solution for this minor mess - - // we need this initial to have not_running at first invocation - lastRpmEventTimeNt = (efitick_t) DEEP_IN_THE_PAST_SECONDS * NT_PER_SECOND; } /** @@ -118,11 +115,15 @@ bool RpmCalculator::checkIfSpinning(efitick_t nowNt) const { * note that the result of this subtraction could be negative, that would happen if * we have a trigger event between the time we've invoked 'getTimeNow' and here */ - bool noRpmEventsForTooLong = nowNt - lastRpmEventTimeNt >= NT_PER_SECOND * NO_RPM_EVENTS_TIMEOUT_SECS; // Anything below 60 rpm is not running + + // Anything below 60 rpm is not running + bool noRpmEventsForTooLong = lastTdcTimer.getElapsedSeconds(nowNt) > NO_RPM_EVENTS_TIMEOUT_SECS; + /** * Also check if there were no trigger events */ - bool noTriggerEventsForTooLong = nowNt - engine->triggerCentral.triggerState.previousShaftEventTimeNt >= NT_PER_SECOND; + bool noTriggerEventsForTooLong = engine->triggerCentral.getTimeSinceTriggerEvent(nowNt) >= 1; + if (noRpmEventsForTooLong || noTriggerEventsForTooLong) { return false; } @@ -252,8 +253,9 @@ void rpmShaftPositionCallback(trigger_event_e ckpSignalType, if (index == 0) { bool hadRpmRecently = rpmState->checkIfSpinning(nowNt); + float periodSeconds = engine->rpmCalculator.lastTdcTimer.getElapsedSecondsAndReset(nowNt); + if (hadRpmRecently) { - int32_t diffNt = (int32_t)(nowNt - rpmState->lastRpmEventTimeNt); /** * Four stroke cycle is two crankshaft revolutions * @@ -261,22 +263,21 @@ void rpmShaftPositionCallback(trigger_event_e ckpSignalType, * and each revolution of crankshaft consists of two engine cycles revolutions * */ - if (diffNt == 0) { + if (periodSeconds == 0) { rpmState->setRpmValue(NOISY_RPM); rpmState->rpmRate = 0; } else { int mult = (int)getEngineCycle(engine->getOperationMode(PASS_ENGINE_PARAMETER_SIGNATURE)) / 360; - float rpm = 60.0 * NT_PER_SECOND * mult / diffNt; + float rpm = 60 * mult / periodSeconds; auto rpmDelta = rpm - rpmState->previousRpmValue; - rpmState->rpmRate = rpmDelta / (mult * 1e-6 * NT2US(diffNt)); + rpmState->rpmRate = rpmDelta / (mult * periodSeconds); rpmState->setRpmValue(rpm > UNREALISTIC_RPM ? NOISY_RPM : rpm); - } } + rpmState->onNewEngineCycle(); - rpmState->lastRpmEventTimeNt = nowNt; } @@ -363,16 +364,13 @@ void tdcMarkCallback( * @return Current crankshaft angle, 0 to 720 for four-stroke */ float getCrankshaftAngleNt(efitick_t timeNt DECLARE_ENGINE_PARAMETER_SUFFIX) { - efitick_t timeSinceZeroAngleNt = timeNt - - engine->rpmCalculator.lastRpmEventTimeNt; + float timeSinceZeroAngle = engine->rpmCalculator.lastTdcTimer.getElapsedSeconds(timeNt); - /** - * even if we use 'getOneDegreeTimeUs' macros here, it looks like the - * compiler is not smart enough to figure out that "A / ( B / C)" could be optimized into - * "A * C / B" in order to replace a slower division with a faster multiplication. - */ int rpm = GET_RPM(); - return rpm == 0 ? NAN : timeSinceZeroAngleNt / getOneDegreeTimeNt(rpm); + + float oneDegreeSeconds = (60.0f / 360) / rpm; + + return rpm == 0 ? NAN : timeSinceZeroAngle / oneDegreeSeconds; } void initRpmCalculator(Logging *sharedLogger DECLARE_ENGINE_PARAMETER_SUFFIX) { diff --git a/firmware/controllers/engine_cycle/rpm_calculator.h b/firmware/controllers/engine_cycle/rpm_calculator.h index 3efa4715a5..80c394b57a 100644 --- a/firmware/controllers/engine_cycle/rpm_calculator.h +++ b/firmware/controllers/engine_cycle/rpm_calculator.h @@ -11,6 +11,7 @@ #include "globalaccess.h" #include "scheduler.h" #include "stored_value_sensor.h" +#include "timer.h" // we use this value in case of noise on trigger input lines #define NOISY_RPM -1 @@ -113,7 +114,8 @@ public: * NaN while engine is not spinning */ volatile floatus_t oneDegreeUs = NAN; - volatile efitick_t lastRpmEventTimeNt = 0; + + Timer lastTdcTimer; // RPM rate of change, in RPM per second float rpmRate = 0; diff --git a/firmware/controllers/math/engine_math.h b/firmware/controllers/math/engine_math.h index 625986bddd..262d293b9b 100644 --- a/firmware/controllers/math/engine_math.h +++ b/firmware/controllers/math/engine_math.h @@ -34,11 +34,6 @@ void setFlatInjectorLag(float value DECLARE_CONFIG_PARAMETER_SUFFIX); */ #define getOneDegreeTimeUs(rpm) (1000000.0f * 60 / 360 / (rpm)) -/** - * @return float, time needed to rotate crankshaft by one degree, in native clicks. - */ -#define getOneDegreeTimeNt(rpm) (US2NT(1000000) * 60.0f / 360 / (rpm)) - floatms_t getCrankshaftRevolutionTimeMs(int rpm); floatms_t getEngineCycleDuration(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX);