rusEFI
The most advanced open source ECU
Functions | Variables
map_averaging.cpp File Reference

Detailed Description

In order to have best MAP estimate possible, we real MAP value at a relatively high frequency and average the value within a specified angle position window for each cylinder

Date
Dec 11, 2013
Author
Andrey Belomutskiy, (c) 2012-2020

This file is part of rusEfi - see http://rusefi.com

rusEfi is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file map_averaging.cpp.

Functions

 fail ("EFI_SHAFT_POSITION_INPUT required to have EFI_EMULATE_POSITION_SENSORS") static NamedOutputPin mapAveragingPin("map")
 
static void endAveraging (MapAverager *arg)
 
static void startAveraging (sampler *s)
 
float filterMapValue (float value)
 
void mapAveragingAdcCallback (float instantVoltage)
 
static void applyMapMinBufferLength ()
 
void refreshMapAveragingPreCalc ()
 
void mapAveragingTriggerCallback (uint32_t index, efitick_t edgeTimestamp)
 
void initMapAveraging ()
 

Variables

static float averagedMapRunningBuffer [MAX_MAP_BUFFER_LENGTH]
 
static int mapMinBufferLength = 0
 
static int averagedMapBufIdx = 0
 
static sampler samplers [MAX_CYLINDER_COUNT][2]
 
static size_t currentMapAverager = 0
 

Function Documentation

◆ applyMapMinBufferLength()

static void applyMapMinBufferLength ( )
static

Definition at line 176 of file map_averaging.cpp.

176  {
177  // check range
178  mapMinBufferLength = maxI(minI(engineConfiguration->mapMinBufferLength, MAX_MAP_BUFFER_LENGTH), 1);
179  // reset index
180  averagedMapBufIdx = 0;
181  // fill with maximum values
182  for (int i = 0; i < mapMinBufferLength; i++) {
183  averagedMapRunningBuffer[i] = FLT_MAX;
184  }
185 }
static float averagedMapRunningBuffer[MAX_MAP_BUFFER_LENGTH]
static int averagedMapBufIdx
static int mapMinBufferLength
engine_configuration_s * engineConfiguration

Referenced by initMapAveraging(), and mapAveragingTriggerCallback().

Here is the caller graph for this function:

◆ endAveraging()

static void endAveraging ( MapAverager arg)
static

Definition at line 169 of file map_averaging.cpp.

169  {
170  arg->stop();
171 
172  mapAveragingPin.setLow();
173 }
Here is the call graph for this function:

◆ fail()

fail ( "EFI_SHAFT_POSITION_INPUT required to have EFI_EMULATE_POSITION_SENSORS"  )

this instance does not have a real physical pin - it's only used for engine sniffer

todo: we can kind of add real physical pin just for a very narrow case of troubleshooting but only if we ever need it :)

Engine idles around 20Hz and revs up to 140Hz, at 60/2 and 8 cylinders we have about 20Khz events If we can read buffer at 50Hz we want buffer to be about 400 elements.

Definition at line 34 of file trigger_emulator_algo.cpp.

41  {
42 }

Referenced by Engine::periodicSlowCallback().

Here is the caller graph for this function:

◆ filterMapValue()

float filterMapValue ( float  value)

Definition at line 105 of file map_averaging.cpp.

105  {
106  static float state = 0;
107  if (state == 0) {
108  state = value;
109  return value;
110  }
111  float result = state + engineConfiguration->mapExpAverageAlpha * (value - state);
112  state = result;
113  return result;
114 }
static ScState state

Referenced by MapAverager::stop().

Here is the caller graph for this function:

◆ initMapAveraging()

void initMapAveraging ( )

Definition at line 277 of file map_averaging.cpp.

277  {
279 }
static void applyMapMinBufferLength()

Referenced by commonInitEngineController().

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

◆ mapAveragingAdcCallback()

void mapAveragingAdcCallback ( float  instantVoltage)

This method is invoked from ADC callback.

Note
This method is invoked OFTEN, this method is a potential bottleneck - the implementation should be as fast as possible

Definition at line 151 of file map_averaging.cpp.

151  {
152  efiAssertVoid(ObdCode::CUSTOM_ERR_6650, hasLotsOfRemainingStack(), "lowstck#9a");
153 
154  SensorResult mapResult = getMapAvg(currentMapAverager).submit(instantVoltage);
155 
156  if (!mapResult) {
157  // hopefully this warning is not too much CPU consumption for fast ADC callback
158  warning(ObdCode::CUSTOM_INSTANT_MAP_DECODING, "Invalid MAP at %f", instantVoltage);
159  }
160 
161 #if EFI_TUNER_STUDIO
162  float instantMap = mapResult.value_or(0);
163  engine->outputChannels.instantMAPValue = instantMap;
164 #endif // EFI_TUNER_STUDIO
165 }
TunerStudioOutputChannels outputChannels
Definition: engine.h:99
SensorResult submit(float sensorVolts)
Engine * engine
bool warning(ObdCode code, const char *fmt,...)
static size_t currentMapAverager
MapAverager & getMapAvg(size_t idx)
Definition: init_map.cpp:26
@ CUSTOM_ERR_6650
@ CUSTOM_INSTANT_MAP_DECODING
expected< float > SensorResult
Definition: sensor.h:55
scaled_channel< uint16_t, 30, 1 > instantMAPValue

Referenced by onFastAdcComplete().

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

◆ mapAveragingTriggerCallback()

void mapAveragingTriggerCallback ( uint32_t  index,
efitick_t  edgeTimestamp 
)

Shaft Position callback used to schedule start and end of MAP averaging

Definition at line 221 of file map_averaging.cpp.

222  {
223 #if EFI_ENGINE_CONTROL && EFI_PROD_CODE
224  // this callback is invoked on interrupt thread
225  if (index != (uint32_t)engineConfiguration->mapAveragingSchedulingAtIndex)
226  return;
227 
229  if (!isValidRpm(rpm)) {
230  return;
231  }
232 
234 
237  }
238 
239  // todo: this could be pre-calculated
241 
242  for (int i = 0; i < samplingCount; i++) {
243  angle_t samplingStart = engine->engineState.mapAveragingStart[i];
244 
245  angle_t samplingDuration = engine->engineState.mapAveragingDuration;
246  // todo: this assertion could be moved out of trigger handler
247  assertAngleRange(samplingDuration, "samplingDuration", ObdCode::CUSTOM_ERR_6563);
248  if (samplingDuration <= 0) {
249  warning(ObdCode::CUSTOM_MAP_ANGLE_PARAM, "map sampling angle should be positive");
250  return;
251  }
252 
253  angle_t samplingEnd = samplingStart + samplingDuration;
254 
255  if (std::isnan(samplingEnd)) {
256  // todo: when would this happen?
257  warning(ObdCode::CUSTOM_ERR_6549, "no map angles");
258  return;
259  }
260 
261  // todo: pre-calculate samplingEnd for each cylinder
262  wrapAngle(samplingEnd, "samplingEnd", ObdCode::CUSTOM_ERR_6563);
263  // only if value is already prepared
264  int structIndex = getRevolutionCounter() % 2;
265 
266  sampler* s = &samplers[i][structIndex];
267 
268  // at the moment we schedule based on time prediction based on current RPM and angle
269  // we are loosing precision in case of changing RPM - the further away is the event the worse is precision
270  // todo: schedule this based on closest trigger event, same as ignition works
271  scheduleByAngle(&s->startTimer, edgeTimestamp, samplingStart,
272  { startAveraging, s });
273  }
274 #endif // EFI_ENGINE_CONTROL && EFI_PROD_CODE
275 }
EngineState engineState
Definition: engine.h:312
angle_t mapAveragingStart[MAX_CYLINDER_COUNT]
Definition: engine_state.h:54
angle_t mapAveragingDuration
Definition: engine_state.h:55
static float getOrZero(SensorType type)
Definition: sensor.h:92
static sampler samplers[MAX_CYLINDER_COUNT][2]
@ CUSTOM_ERR_6549
@ CUSTOM_MAP_ANGLE_PARAM
@ CUSTOM_ERR_6563
@ MapAveragingTriggerCallback
efitick_t scheduleByAngle(scheduling_s *timer, efitick_t nowNt, angle_t angle, action_s action)
float angle_t
Definition: rusefi_types.h:59
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:

◆ refreshMapAveragingPreCalc()

void refreshMapAveragingPreCalc ( )

Definition at line 187 of file map_averaging.cpp.

187  {
189  if (isValidRpm(rpm)) {
191  angle_t start = interpolate2d(rpm, c->samplingAngleBins, c->samplingAngle);
192  efiAssertVoid(ObdCode::CUSTOM_ERR_MAP_START_ASSERT, !std::isnan(start), "start");
193 
195  efiAssertVoid(ObdCode::CUSTOM_ERR_MAP_AVG_OFFSET, !std::isnan(offsetAngle), "offsetAngle");
196 
197  for (size_t i = 0; i < engineConfiguration->cylindersCount; i++) {
198  // todo: potential micro-optimization to reuse getEngineState()->engineCycle?
199  angle_t cylinderOffset = getEngineCycle(getEngineRotationState()->getOperationMode()) * i / engineConfiguration->cylindersCount;
200  efiAssertVoid(ObdCode::CUSTOM_ERR_MAP_CYL_OFFSET, !std::isnan(cylinderOffset), "cylinderOffset");
201  // part of this formula related to specific cylinder offset is never changing - we can
202  // move the loop into start-up calculation and not have this loop as part of periodic calculation
203  // todo: change the logic as described above in order to reduce periodic CPU usage?
204  float cylinderStart = start + cylinderOffset - offsetAngle + tdcPosition();
205  wrapAngle(cylinderStart, "cylinderStart", ObdCode::CUSTOM_ERR_6562);
206  engine->engineState.mapAveragingStart[i] = cylinderStart;
207  }
209  } else {
210  for (size_t i = 0; i < engineConfiguration->cylindersCount; i++) {
212  }
214  }
215 
216 }
TriggerCentral triggerCentral
Definition: engine.h:286
TriggerFormDetails triggerFormDetails
angle_t eventAngles[2 *PWM_PHASE_MAX_COUNT]
EngineRotationState * getEngineRotationState()
Definition: engine.cpp:592
@ CUSTOM_ERR_MAP_AVG_OFFSET
@ CUSTOM_ERR_6562
@ CUSTOM_ERR_MAP_CYL_OFFSET
@ CUSTOM_ERR_MAP_START_ASSERT
angle_t getEngineCycle(operation_mode_e operationMode)

Referenced by Engine::periodicFastCallback().

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

◆ startAveraging()

static void startAveraging ( sampler *  s)
static

Definition at line 69 of file map_averaging.cpp.

69  {
70  efiAssertVoid(ObdCode::CUSTOM_ERR_6649, hasLotsOfRemainingStack(), "lowstck#9");
71 
72  // TODO: set currentMapAverager based on cylinder bank
73  auto& averager = getMapAvg(currentMapAverager);
74  averager.start();
75 
76  mapAveragingPin.setHigh();
77 
79  { endAveraging, &averager });
80 }
efitick_t getTimeNowNt()
Definition: efitime.cpp:19
@ CUSTOM_ERR_6649
Here is the call graph for this function:

Variable Documentation

◆ averagedMapBufIdx

int averagedMapBufIdx = 0
static

Definition at line 52 of file map_averaging.cpp.

Referenced by applyMapMinBufferLength(), and MapAverager::stop().

◆ averagedMapRunningBuffer

float averagedMapRunningBuffer[MAX_MAP_BUFFER_LENGTH]
static

Definition at line 50 of file map_averaging.cpp.

Referenced by applyMapMinBufferLength(), and MapAverager::stop().

◆ currentMapAverager

size_t currentMapAverager = 0
static

Definition at line 67 of file map_averaging.cpp.

Referenced by mapAveragingAdcCallback(), and startAveraging().

◆ mapMinBufferLength

int mapMinBufferLength = 0
static

◆ samplers

sampler samplers[MAX_CYLINDER_COUNT][2]
static

Definition at line 62 of file map_averaging.cpp.

Referenced by mapAveragingTriggerCallback().

Go to the source code of this file.