rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
Functions
rpm_calculator.cpp File Reference

Detailed Description

RPM calculator.

Here we listen to position sensor events in order to figure our if engine is currently running or not. Actual getRpm() is calculated once per crankshaft revolution, based on the amount of time passed since the start of previous shaft revolution.

We also have 'instant RPM' logic separate from this 'cycle RPM' logic. Open question is why do we not use instant RPM instead of cycle RPM more often.

Date
Jan 1, 2013
Author
Andrey Belomutskiy, (c) 2012-2020

Definition in file rpm_calculator.cpp.

Functions

operation_mode_e lookupOperationMode ()
 
static bool doesTriggerImplyOperationMode (trigger_type_e type)
 
void rpmShaftPositionCallback (trigger_event_e ckpSignalType, uint32_t trgEventIndex, efitick_t nowNt)
 Shaft position callback used by RPM calculation logic.
 
static void onTdcCallback ()
 
void tdcMarkCallback (uint32_t trgEventIndex, efitick_t nowNt)
 
efitick_t scheduleByAngle (scheduling_s *timer, efitick_t nowNt, angle_t angle, action_s const &action)
 

Function Documentation

◆ doesTriggerImplyOperationMode()

static bool doesTriggerImplyOperationMode ( trigger_type_e  type)
static

Definition at line 68 of file rpm_calculator.cpp.

68 {
69 switch (type) {
72 case trigger_type_e::TT_3_1_CAM: // huh why is this trigger with CAM suffix right in the name on this exception list?!
73 case trigger_type_e::TT_36_2_2_2: // this trigger is special due to rotary application https://github.com/rusefi/rusefi/issues/5566
76 // These modes could be either cam or crank speed
77 return false;
78 default:
79 return true;
80 }
81}

Referenced by RpmCalculator::getOperationMode().

Here is the caller graph for this function:

◆ lookupOperationMode()

operation_mode_e lookupOperationMode ( )

Definition at line 57 of file rpm_calculator.cpp.

Referenced by TriggerCentral::applyShapesConfiguration(), and RpmCalculator::getOperationMode().

Here is the caller graph for this function:

◆ onTdcCallback()

static void onTdcCallback ( )
static

This callback has nothing to do with actual engine control, it just sends a Top Dead Center mark to the rusEfi console digital sniffer.

Definition at line 340 of file rpm_calculator.cpp.

340 {
341#if EFI_UNIT_TEST
342 if (!engine->needTdcCallback) {
343 return;
344 }
345#endif /* EFI_UNIT_TEST */
346
349#if EFI_TOOTH_LOGGER
351#endif /* EFI_TOOTH_LOGGER */
352}
bool needTdcCallback
Definition engine.h:265
static float getOrZero(SensorType type)
Definition sensor.h:83
efitick_t getTimeNowNt()
Definition efitime.cpp:19
static EngineAccessor engine
Definition engine.h:421
void addEngineSnifferTdcEvent(int rpm)
void LogTriggerTopDeadCenter(efitick_t timestamp)
Here is the call graph for this function:

◆ rpmShaftPositionCallback()

void rpmShaftPositionCallback ( trigger_event_e  ckpSignalType,
uint32_t  trgEventIndex,
efitick_t  nowNt 
)

Shaft position callback used by RPM calculation logic.

This callback should always be the first of trigger callbacks because other callbacks depend of values updated here. This callback is invoked on interrupt thread.

Four stroke cycle is two crankshaft revolutions

We always do '* 2' because the event signal is already adjusted to 'per engine cycle' and each revolution of crankshaft consists of two engine cycles revolutions

Definition at line 261 of file rpm_calculator.cpp.

262 {
263
264 bool alwaysInstantRpm = engineConfiguration->alwaysInstantRpm;
265
266 RpmCalculator *rpmState = &engine->rpmCalculator;
267
268 if (trgEventIndex == 0) {
269 if (HAVE_CAM_INPUT()) {
271 }
272
273
274 bool hadRpmRecently = rpmState->checkIfSpinning(nowNt);
275
276 float periodSeconds = engine->rpmCalculator.lastTdcTimer.getElapsedSecondsAndReset(nowNt);
277
278 if (hadRpmRecently) {
279 /**
280 * Four stroke cycle is two crankshaft revolutions
281 *
282 * We always do '* 2' because the event signal is already adjusted to 'per engine cycle'
283 * and each revolution of crankshaft consists of two engine cycles revolutions
284 *
285 */
286 if (!alwaysInstantRpm) {
287 if (periodSeconds == 0) {
288 rpmState->setRpmValue(0);
289 rpmState->rpmRate = 0;
290 } else {
291 // todo: extract utility method? see duplication with high_pressure_pump.cpp
292 int mult = (int)getEngineCycle(getEngineRotationState()->getOperationMode()) / 360;
293 float rpm = 60 * mult / periodSeconds;
294
295 auto rpmDelta = rpm - rpmState->previousRpmValue;
296 rpmState->rpmRate = rpmDelta / (mult * periodSeconds);
297
298 rpmState->setRpmValue(rpm);
299 }
300 }
301 } else {
302 // we are here only once trigger is synchronized for the first time
303 // while transitioning from 'spinning' to 'running'
305 }
306
307 rpmState->onNewEngineCycle();
308 }
309
310
311 // Always update instant RPM even when not spinning up
314
316 trgEventIndex, nowNt);
317
319 if (alwaysInstantRpm) {
320 rpmState->setRpmValue(instantRpm);
321 } else if (rpmState->isSpinningUp()) {
322 rpmState->assignRpmValue(instantRpm);
323#if 0
324 efiPrintf("** RPM: idx=%d sig=%d iRPM=%d", trgEventIndex, ckpSignalType, instantRpm);
325#else
326 UNUSED(ckpSignalType);
327#endif
328 }
329}
TriggerCentral triggerCentral
Definition engine.h:326
RpmCalculator rpmCalculator
Definition engine.h:314
virtual operation_mode_e getOperationMode() const =0
void updateInstantRpm(uint32_t current_index, TriggerWaveform const &triggerShape, TriggerFormDetails *triggerFormDetails, uint32_t index, efitick_t nowNt)
bool isSpinningUp() const
bool checkIfSpinning(efitick_t nowNt) const
void setRpmValue(float value)
void assignRpmValue(float value)
InstantRpmCalculator instantRpm
PrimaryTriggerDecoder triggerState
TriggerWaveform triggerShape
TriggerFormDetails triggerFormDetails
current_cycle_state_s currentCycle
EngineRotationState * getEngineRotationState()
Definition engine.cpp:585
UNUSED(samplingTimeSeconds)
instantRpm("sync: instant RPM", SensorCategory.SENSOR_INPUTS, FieldType.INT16, 326, 1.0, 0.0, 0.0, "rpm")
angle_t getEngineCycle(operation_mode_e operationMode)

Referenced by TriggerCentral::handleShaftSignal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ scheduleByAngle()

efitick_t scheduleByAngle ( scheduling_s timer,
efitick_t  nowNt,
angle_t  angle,
action_s const &  action 
)

Schedules a callback 'angle' degree of crankshaft from now. The callback would be executed once after the duration of time which it takes the crankshaft to rotate to the specified angle.

Returns
tick time of scheduled action

Definition at line 389 of file rpm_calculator.cpp.

389 {
390 float delayUs = engine->rpmCalculator.oneDegreeUs * angle;
391
392 efitick_t actionTimeNt = sumTickAndFloat(nowNt, USF2NT(delayUs));
393
394 engine->scheduler.schedule("angle", timer, actionTimeNt, action);
395
396 return actionTimeNt;
397}
SingleTimerExecutor scheduler
Definition engine.h:279
floatus_t oneDegreeUs
void schedule(const char *msg, scheduling_s *scheduling, efitick_t timeNt, action_s const &action) override
Schedule an action to be executed in the future.
efitick_t sumTickAndFloat(efitick_t ticks, float extra)
Definition efitime.h:90

Referenced by fireSparkAndPrepareNextSchedule(), MapAveragingModule::onEnginePhase(), Engine::onSparkFireKnockSense(), InjectionEvent::onTriggerTooth(), HpfpController::pinTurnOn(), TriggerScheduler::scheduleEventsUntilNextTriggerTooth(), TriggerScheduler::scheduleOrQueue(), scheduleSparkEvent(), startAveraging(), tdcMarkCallback(), and turnSparkPinHighStartCharging().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ tdcMarkCallback()

void tdcMarkCallback ( uint32_t  trgEventIndex,
efitick_t  nowNt 
)

This trigger callback schedules the actual physical TDC callback in relation to trigger synchronization point.

Definition at line 357 of file rpm_calculator.cpp.

358 {
359 bool isTriggerSynchronizationPoint = trgEventIndex == 0;
360 if (isTriggerSynchronizationPoint && getTriggerCentral()->isEngineSnifferEnabled) {
361
362#if EFI_UNIT_TEST
363 if (!engine->tdcMarkEnabled) {
364 return;
365 }
366#endif // EFI_UNIT_TEST
367
368
369 // two instances of scheduling_s are needed to properly handle event overlap
370 int revIndex2 = getRevolutionCounter() % 2;
372 // todo: use tooth event-based scheduling, not just time-based scheduling
373 if (rpm != 0) {
374 angle_t tdcPosition = tdcPosition();
375 // we need a positive angle offset here
376 wrapAngle(tdcPosition, "tdcPosition", ObdCode::CUSTOM_ERR_6553);
377 scheduleByAngle(&engine->tdcScheduler[revIndex2], nowNt, tdcPosition, action_s::make<onTdcCallback>());
378 }
379 }
380}
scheduling_s tdcScheduler[2]
Definition engine.h:298
bool tdcMarkEnabled
Definition engine.h:309
TriggerCentral * getTriggerCentral()
Definition engine.cpp:602
@ CUSTOM_ERR_6553
efitick_t scheduleByAngle(scheduling_s *timer, efitick_t nowNt, angle_t angle, action_s const &action)
float angle_t
void wrapAngle(angle_t &angle, const char *msg, ObdCode code)

Referenced by TriggerCentral::handleShaftSignal().

Here is the call graph for this function:
Here is the caller graph for this function:

Go to the source code of this file.