Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAP avg uses engine module callbacks #475

Merged
merged 11 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading