Skip to content

Commit

Permalink
MAP avg uses engine module callbacks (#475)
Browse files Browse the repository at this point in the history
* use engine module callbacks

* happy tests

* happy small-can-board

* interact with map avg via module

* simplify map avg init

* tweaks

* omit module to disable it instead!

* unnecessary guard

* minor cleanups

* unnecessary branch - lookups for these tables are fine at 0 rpm

* oop
  • Loading branch information
mck1117 authored Aug 30, 2024
1 parent e41f3bb commit 761efd8
Show file tree
Hide file tree
Showing 17 changed files with 76 additions and 92 deletions.
3 changes: 2 additions & 1 deletion firmware/config/boards/hellen/small-can-board/board.mk
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ DDEFS += -DEFI_SHAFT_POSITION_INPUT=FALSE
DDEFS += -DEFI_ALTERNATOR_CONTROL=FALSE
DDEFS += -DEFI_VVT_PID=FALSE
DDEFS += -DEFI_EMULATE_POSITION_SENSORS=FALSE
DDEFS += -DEFI_MAP_AVERAGING=FALSE
DDEFS += -DEFI_HPFP=FALSE
DDEFS += -DEFI_TOOTH_LOGGER=FALSE
DDEFS += -DRAM_UNUSED_SIZE=100

NO_MAP_AVERAGING = yes

DDEFS += -DHW_SMALL_CAN_BOARD=1

#Mass Storage
Expand Down
4 changes: 0 additions & 4 deletions firmware/config/stm32f4ems/efifeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,6 @@
//#define EFI_MALFUNCTION_INDICATOR FALSE
#endif

#ifndef EFI_MAP_AVERAGING
#define EFI_MAP_AVERAGING TRUE
#endif

// todo: most of this should become configurable

// todo: switch to continuous ADC conversion for fast ADC?
Expand Down
4 changes: 0 additions & 4 deletions firmware/controllers/algo/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,10 +466,6 @@ injection_mode_e getCurrentInjectionMode() {
void Engine::periodicFastCallback() {
ScopePerf pc(PE::EnginePeriodicFastCallback);

#if EFI_MAP_AVERAGING
refreshMapAveragingPreCalc();
#endif

engineState.periodicFastCallback();

tachUpdate();
Expand Down
8 changes: 3 additions & 5 deletions firmware/controllers/engine_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,11 +513,9 @@ void commonInitEngineController() {
initElectronicThrottle();
#endif /* EFI_ELECTRONIC_THROTTLE_BODY */

#if EFI_MAP_AVERAGING
if (engineConfiguration->isMapAveragingEnabled) {
initMapAveraging();
}
#endif /* EFI_MAP_AVERAGING */
#ifdef MODULE_MAP_AVERAGING
initMapAveraging();
#endif /* MODULE_MAP_AVERAGING */

#if EFI_BOOST_CONTROL
initBoostCtrl();
Expand Down
8 changes: 1 addition & 7 deletions firmware/controllers/engine_cycle/main_trigger_callback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ void mainTriggerCallback(uint32_t trgEventIndex, efitick_t edgeTimestamp, angle_
// todo: check for 'trigger->is_synchnonized?'
return;
}
if (rpm == NOISY_RPM) {
if (rpm == NOISY_RPM || rpm > UNREALISTIC_RPM) {
warning(ObdCode::OBD_Crankshaft_Position_Sensor_A_Circuit_Malfunction, "noisy trigger");
return;
}
Expand Down Expand Up @@ -113,12 +113,6 @@ void mainTriggerCallback(uint32_t trgEventIndex, efitick_t edgeTimestamp, angle_
* For spark we schedule both start of coil charge and actual spark based on trigger angle
*/
onTriggerEventSparkLogic(rpm, edgeTimestamp, currentPhase, nextPhase);

#if !EFI_UNIT_TEST
#if EFI_MAP_AVERAGING
mapAveragingTriggerCallback(edgeTimestamp, currentPhase, nextPhase);
#endif /* EFI_MAP_AVERAGING */
#endif /* EFI_UNIT_TEST */
}

#endif /* EFI_ENGINE_CONTROL */
82 changes: 38 additions & 44 deletions firmware/controllers/modules/map_averaging/map_averaging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@

#include "pch.h"

#if EFI_MAP_AVERAGING

#include "trigger_central.h"

#if EFI_SENSOR_CHART
Expand Down Expand Up @@ -78,6 +76,11 @@ static void startAveraging(sampler* s) {
{ endAveraging, &averager });
}

void MapAverager::showInfo(const char* sensorName) const {
const auto value = get();
efiPrintf("Sensor \"%s\" is MAP averager: valid: %s value: %.2f averaged sample count: %d", sensorName, boolToString(value.Valid), value.Value, m_lastCounter);
}

void MapAverager::start(uint8_t cylinderIndex) {
chibios_rt::CriticalSectionLocker csl;

Expand Down Expand Up @@ -133,24 +136,21 @@ void MapAverager::stop() {
}
}

#if HAL_USE_ADC

/**
* 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
*/
void mapAveragingAdcCallback(float instantVoltage) {
void MapAveragingModule::submitSample(float volts) {
efiAssertVoid(ObdCode::CUSTOM_ERR_6650, getCurrentRemainingStack() > 128, "lowstck#9a");

SensorResult mapResult = getMapAvg(currentMapAverager).submit(instantVoltage);
SensorResult mapResult = getMapAvg(currentMapAverager).submit(volts);

float instantMap = mapResult.value_or(0);
#if EFI_TUNER_STUDIO
engine->outputChannels.instantMAPValue = instantMap;
#endif // EFI_TUNER_STUDIO
}
#endif

static void endAveraging(MapAverager* arg) {
arg->stop();
Expand All @@ -169,50 +169,39 @@ static void applyMapMinBufferLength() {
}
}

void refreshMapAveragingPreCalc() {
int rpm = Sensor::getOrZero(SensorType::Rpm);
if (isValidRpm(rpm)) {
MAP_sensor_config_s * c = &engineConfiguration->map;
angle_t start = interpolate2d(rpm, c->samplingAngleBins, c->samplingAngle);
angle_t duration = interpolate2d(rpm, c->samplingWindowBins, c->samplingWindow);
efiAssertVoid(ObdCode::CUSTOM_ERR_MAP_START_ASSERT, !std::isnan(start), "start");
assertAngleRange(duration, "samplingDuration", ObdCode::CUSTOM_ERR_6563);

// Clamp the duration to slightly less than one cylinder period
float cylinderPeriod = engine->engineState.engineCycle / engineConfiguration->cylindersCount;
duration = clampF(10, duration, cylinderPeriod - 10);

for (size_t i = 0; i < engineConfiguration->cylindersCount; i++) {
float cylinderStart = start + getCylinderAngle(i, ID2INDEX(getCylinderId(i)));;
wrapAngle(cylinderStart, "cylinderStart", ObdCode::CUSTOM_ERR_6562);
engine->engineState.mapAveragingStart[i] = cylinderStart;
}
void MapAveragingModule::onFastCallback() {
float rpm = Sensor::getOrZero(SensorType::Rpm);

engine->engineState.mapAveragingDuration = duration;
} else {
for (size_t i = 0; i < engineConfiguration->cylindersCount; i++) {
engine->engineState.mapAveragingStart[i] = 0;
}
MAP_sensor_config_s * c = &engineConfiguration->map;

angle_t start = interpolate2d(rpm, c->samplingAngleBins, c->samplingAngle);
efiAssertVoid(ObdCode::CUSTOM_ERR_MAP_START_ASSERT, !std::isnan(start), "start");

engine->engineState.mapAveragingDuration = 0;
for (size_t i = 0; i < engineConfiguration->cylindersCount; i++) {
float cylinderStart = start + getCylinderAngle(i, ID2INDEX(getCylinderId(i)));;
wrapAngle(cylinderStart, "cylinderStart", ObdCode::CUSTOM_ERR_6562);
engine->engineState.mapAveragingStart[i] = cylinderStart;
}

angle_t duration = interpolate2d(rpm, c->samplingWindowBins, c->samplingWindow);
assertAngleRange(duration, "samplingDuration", ObdCode::CUSTOM_ERR_6563);

// Clamp the duration to slightly less than one cylinder period
float cylinderPeriod = engine->engineState.engineCycle / engineConfiguration->cylindersCount;
engine->engineState.mapAveragingDuration = clampF(10, duration, cylinderPeriod - 10);
}

// Callback to schedule the start of map averaging for each cylinder
void mapAveragingTriggerCallback(efitick_t edgeTimestamp, angle_t currentPhase, angle_t nextPhase) {
#if EFI_ENGINE_CONTROL
int rpm = Sensor::getOrZero(SensorType::Rpm);
if (!isValidRpm(rpm)) {
void MapAveragingModule::onEnginePhase(float rpm,
efitick_t edgeTimestamp,
float currentPhase,
float nextPhase) {
if (!engineConfiguration->isMapAveragingEnabled) {
return;
}

ScopePerf perf(PE::MapAveragingTriggerCallback);

if (engineConfiguration->mapMinBufferLength != mapMinBufferLength) {
applyMapMinBufferLength();
}

int samplingCount = engineConfiguration->measureMapOnlyInOneCylinder ? 1 : engineConfiguration->cylindersCount;

for (int i = 0; i < samplingCount; i++) {
Expand All @@ -228,15 +217,20 @@ void mapAveragingTriggerCallback(efitick_t edgeTimestamp, angle_t currentPhase,
}

auto& s = samplers[i];
s.cylinderIndex = i;

scheduleByAngle(&s.timer, edgeTimestamp, angleOffset, { startAveraging, &s });
}
#endif
}

void MapAveragingModule::onConfigurationChange(engine_configuration_s const * previousConfig) {
if (!previousConfig || engineConfiguration->mapMinBufferLength != previousConfig->mapMinBufferLength) {
applyMapMinBufferLength();
}
}

void initMapAveraging() {
for (size_t i = 0; i < efi::size(samplers); i++) {
samplers[i].cylinderIndex = i;
}

applyMapMinBufferLength();
}

#endif /* EFI_MAP_AVERAGING */
24 changes: 13 additions & 11 deletions firmware/controllers/modules/map_averaging/map_averaging.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,11 @@

#include "sensor_converter_func.h"

#if EFI_MAP_AVERAGING

#if HAL_USE_ADC
void mapAveragingAdcCallback(float instantVoltage);
#endif

void initMapAveraging();
void refreshMapAveragingPreCalc();

void mapAveragingTriggerCallback(efitick_t edgeTimestamp, angle_t currentPhase, angle_t nextPhase);

// allow smoothing up to number of cylinders
#define MAX_MAP_BUFFER_LENGTH (MAX_CYLINDER_COUNT)

#endif /* EFI_MAP_AVERAGING */

class MapAverager : public StoredValueSensor {
public:
MapAverager(SensorType type, efidur_t timeout)
Expand Down Expand Up @@ -54,3 +43,16 @@ class MapAverager : public StoredValueSensor {
};

MapAverager& getMapAvg(size_t idx);

class MapAveragingModule : public EngineModule {
public:
void onConfigurationChange(engine_configuration_s const * previousConfig);

void onFastCallback() override;
void onEnginePhase(float rpm,
efitick_t edgeTimestamp,
float currentPhase,
float nextPhase) override;

void submitSample(float volts);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MODULES_INC += $(PROJECT_DIR)/controllers/modules/map_averaging
MODULES_CPPSRC += $(PROJECT_DIR)/controllers/modules/map_averaging/map_averaging.cpp
MODULES_INCLUDE += \#include "map_averaging.h"\n
# MODULES_LIST += MapSampler,
MODULES_LIST += MapAveragingModule,

DDEFS += -DMODULE_MAP_AVERAGING
5 changes: 4 additions & 1 deletion firmware/controllers/modules/modules.mk
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
include $(PROJECT_DIR)/controllers/modules/fan/fan.mk
include $(PROJECT_DIR)/controllers/modules/fuel_pump/fuel_pump.mk
include $(PROJECT_DIR)/controllers/modules/gear_detector/gear_detector.mk
include $(PROJECT_DIR)/controllers/modules/map_averaging/map_averaging.mk
include $(PROJECT_DIR)/controllers/modules/trip_odometer/trip_odometer.mk

ifeq ($(NO_MAP_AVERAGING),)
include $(PROJECT_DIR)/controllers/modules/map_averaging/map_averaging.mk
endif
4 changes: 2 additions & 2 deletions firmware/controllers/sensors/impl/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ static void printMAPInfo() {
#if EFI_ANALOG_SENSORS
efiPrintf("instant value=%.2fkPa", Sensor::getOrZero(SensorType::Map));

#if EFI_MAP_AVERAGING
#ifdef MODULE_MAP_AVERAGING
efiPrintf("map type=%d/%s MAP=%.2fkPa mapMinBufferLength=%d", engineConfiguration->map.sensor.type,
getAir_pressure_sensor_type_e(engineConfiguration->map.sensor.type),
Sensor::getOrZero(SensorType::Map),
mapMinBufferLength);
#endif // EFI_MAP_AVERAGING
#endif // MODULE_MAP_AVERAGING

adc_channel_e mapAdc = engineConfiguration->map.sensor.hwChannel;
char pinNameBuffer[16];
Expand Down
5 changes: 0 additions & 5 deletions firmware/controllers/sensors/sensor_info_printing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@ void Lps25Sensor::showInfo(const char* sensorName) const {
efiPrintf("%s: LPS25 baro %.2f kPa", sensorName, get().Value);
}

void MapAverager::showInfo(const char* sensorName) const {
const auto value = get();
efiPrintf("Sensor \"%s\" is MAP averager: valid: %s value: %.2f averaged sample count: %d", sensorName, boolToString(value.Valid), value.Value, m_lastCounter);
}

void LinearFunc::showInfo(float testRawValue) const {
efiPrintf(" Linear function slope: %.2f offset: %.2f min: %.1f max: %.1f", m_a, m_b, m_minOutput, m_maxOutput);
const auto value = convert(testRawValue);
Expand Down
8 changes: 5 additions & 3 deletions firmware/hw_layer/hardware.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,11 @@ void onFastAdcComplete(adcsample_t*) {
// this callback is executed 10 000 times a second, it needs to be as fast as possible!
ScopePerf perf(PE::AdcCallbackFast);

#if EFI_MAP_AVERAGING
mapAveragingAdcCallback(adcToVoltsDivided(getFastAdc(fastMapSampleIndex), engineConfiguration->map.sensor.hwChannel));
#endif /* EFI_MAP_AVERAGING */
#ifdef MODULE_MAP_AVERAGING
engine->module<MapAveragingModule>()->submitSample(
adcToVoltsDivided(getFastAdc(fastMapSampleIndex), engineConfiguration->map.sensor.hwChannel)
);
#endif // MODULE_MAP_AVERAGING

#if EFI_SENSOR_CHART && EFI_SHAFT_POSITION_INPUT
if (getEngineState()->sensorChartMode == SC_AUX_FAST1) {
Expand Down
6 changes: 6 additions & 0 deletions firmware/init/sensor/init_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ static FunctionalSensor slowMapSensor2(SensorType::MapSlow2, MS2NT(50));
static FunctionalSensor compressorDischargePress(SensorType::CompressorDischargePressure, MS2NT(50));
static FunctionalSensor throttleInletPress(SensorType::ThrottleInletPressure, MS2NT(50));

#ifdef MODULE_MAP_AVERAGING
// lowest reasonable idle is maybe 600 rpm
// one sample per cycle (1 cylinder, or "sample one cyl" mode) gives a period of 100ms
// add some margin -> 200ms timeout for fast MAP sampling
Expand All @@ -25,6 +26,7 @@ MapAverager fastMapSensor2(SensorType::MapFast2, MS2NT(200));
MapAverager& getMapAvg(size_t idx) {
return idx == 0 ? fastMapSensor : fastMapSensor2;
}
#endif // MODULE_MAP_AVERAGING

// Combine MAP sensors: prefer fast sensor, but use slow if fast is unavailable.
static FallbackSensor mapCombiner(SensorType::Map, SensorType::MapFast, SensorType::MapSlow);
Expand Down Expand Up @@ -102,17 +104,21 @@ void initMap() {

slowMapSensor.setFunction(mapConverter);
slowMapSensor2.setFunction(mapConverter);
#ifdef MODULE_MAP_AVERAGING
fastMapSensor.setFunction(mapConverter);
fastMapSensor2.setFunction(mapConverter);
#endif // MODULE_MAP_AVERAGING
compressorDischargePress.setFunction(mapConverter);
throttleInletPress.setFunction(mapConverter);

auto mapChannel = engineConfiguration->map.sensor.hwChannel;
if (isAdcChannelValid(mapChannel)) {
slowMapSensor.Register();
slowMapSensor2.Register();
#ifdef MODULE_MAP_AVERAGING
fastMapSensor.Register();
fastMapSensor2.Register();
#endif // MODULE_MAP_AVERAGING
mapCombiner.Register();
mapCombiner2.Register();

Expand Down
1 change: 0 additions & 1 deletion simulator/simulator/efifeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@

#define EFI_USE_UART_DMA FALSE

#define EFI_MAP_AVERAGING TRUE
#define EFI_ALTERNATOR_CONTROL TRUE

#define EFI_ENGINE_AUDI_AAN FALSE
Expand Down
1 change: 0 additions & 1 deletion simulator/simulator/rusEfiFunctionalTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include "sensor_chart.h"
#include "bench_test.h"
#include "tunerstudio.h"
#include "map_averaging.h"
#include "mmc_card.h"
#include "memstreams.h"
#include <chprintf.h>
Expand Down
2 changes: 0 additions & 2 deletions unit_tests/efifeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@

#define EFI_BOARD_TEST FALSE

#define EFI_MAP_AVERAGING TRUE

#define EFI_LUA TRUE

#define EFI_HPFP TRUE
Expand Down
1 change: 1 addition & 0 deletions unit_tests/engine_test_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ EngineTestHelper::EngineTestHelper(engine_type_e engineType, configuration_callb
initDataStructures();

resetConfigurationExt(configurationCallback, engineType);
engineConfiguration->isMapAveragingEnabled = false;

validateConfig();

Expand Down

0 comments on commit 761efd8

Please sign in to comment.