From 5c84d9536002bc10ca10e44b0a8b86cf526b9b77 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Wed, 6 May 2020 15:52:15 -0700 Subject: [PATCH 1/7] proteus -> exti (#1378) * proteus -> exti * do frankenso pal the same way Co-authored-by: Matthew Kennedy --- .github/workflows/build-firmware.yaml | 2 +- firmware/config/boards/proteus/board.mk | 2 +- firmware/controllers/sensors/map.cpp | 2 +- firmware/hw_layer/trigger_input.cpp | 6 ++++++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-firmware.yaml b/.github/workflows/build-firmware.yaml index b729c7a8d2..d341b0e57b 100644 --- a/.github/workflows/build-firmware.yaml +++ b/.github/workflows/build-firmware.yaml @@ -24,7 +24,7 @@ jobs: - build-target: frankenso-pal efi-cpu: ARCH_STM32F4 efi-board: st_stm32f4 - target-extra-params: -DHAL_TRIGGER_USE_PAL=TRUE -DHAL_USE_ICU=FALSE -DEFI_VEHICLE_SPEED=FALSE -DEFI_LOGIC_ANALYZER=FALSE + target-extra-params: -DHAL_TRIGGER_USE_PAL=TRUE -DEFI_ICU_INPUTS=FALSE -DEFI_VEHICLE_SPEED=FALSE -DEFI_LOGIC_ANALYZER=FALSE - build-target: mre-f4 efi-cpu: ARCH_STM32F4 diff --git a/firmware/config/boards/proteus/board.mk b/firmware/config/boards/proteus/board.mk index 4c657cb8a7..b849cc4150 100644 --- a/firmware/config/boards/proteus/board.mk +++ b/firmware/config/boards/proteus/board.mk @@ -24,4 +24,4 @@ endif # Override DEFAULT_ENGINE_TYPE -DDEFS += $(MCU_DEFS) -DEFI_USE_OSC=TRUE -DEFI_FATAL_ERROR_PIN=GPIOE_3 -DFIRMWARE_ID=\"proteus\" -DDEFAULT_ENGINE_TYPE=PROTEUS -DUSE_ADC3_VBATT_HACK -DSTM32_ADC_USE_ADC3=TRUE -DEFI_INCLUDE_ENGINE_PRESETS=FALSE +DDEFS += $(MCU_DEFS) -DEFI_USE_OSC=TRUE -DEFI_FATAL_ERROR_PIN=GPIOE_3 -DFIRMWARE_ID=\"proteus\" -DDEFAULT_ENGINE_TYPE=PROTEUS -DUSE_ADC3_VBATT_HACK -DSTM32_ADC_USE_ADC3=TRUE -DEFI_INCLUDE_ENGINE_PRESETS=FALSE -DEFI_ICU_INPUTS=FALSE -DHAL_TRIGGER_USE_PAL=TRUE -DEFI_VEHICLE_SPEED=FALSE -DEFI_LOGIC_ANALYZER=FALSE diff --git a/firmware/controllers/sensors/map.cpp b/firmware/controllers/sensors/map.cpp index 9d7c5fd0df..4b9459b5e1 100644 --- a/firmware/controllers/sensors/map.cpp +++ b/firmware/controllers/sensors/map.cpp @@ -277,7 +277,7 @@ void initMapDecoder(Logging *sharedLogger DECLARE_ENGINE_PARAMETER_SUFFIX) { //engine->configurationListeners.registerCallback(applyConfiguration); if (engineConfiguration->hasFrequencyReportingMapSensor) { -#if HAL_USE_ICU +#if EFI_ICU_INPUTS digital_input_s* digitalMapInput = startDigitalCapture("MAP freq", CONFIG(frequencyReportingMapInputPin)); digitalMapInput->setWidthCallback((VoidInt) digitalMapWidthCallback, NULL); diff --git a/firmware/hw_layer/trigger_input.cpp b/firmware/hw_layer/trigger_input.cpp index c08cfa5918..ac7efb9541 100644 --- a/firmware/hw_layer/trigger_input.cpp +++ b/firmware/hw_layer/trigger_input.cpp @@ -76,6 +76,7 @@ static int turnOnTriggerInputPin(const char *msg, int index, bool isTriggerShaft return 0; /* try ICU first */ +#if EFI_ICU_INPUTS if (icuTriggerTurnOnInputPin(msg, index, isTriggerShaft) >= 0) { if (isTriggerShaft) shaftTriggerType[index] = TRIGGER_ICU; @@ -83,6 +84,7 @@ static int turnOnTriggerInputPin(const char *msg, int index, bool isTriggerShaft camTriggerType[index] = TRIGGER_ICU; return 0; } +#endif /* ... then EXTI */ if (extiTriggerTurnOnInputPin(msg, index, isTriggerShaft) >= 0) { @@ -103,15 +105,19 @@ static void turnOffTriggerInputPin(int index, bool isTriggerShaft) { activeConfiguration.triggerInputPins[index] : activeConfiguration.camInputs[index]; if (isTriggerShaft) { +#if EFI_ICU_INPUTS if (shaftTriggerType[index] == TRIGGER_ICU) icuTriggerTurnOffInputPin(brainPin); +#endif if (shaftTriggerType[index] == TRIGGER_EXTI) extiTriggerTurnOffInputPin(brainPin); shaftTriggerType[index] = TRIGGER_NONE; } else { +#if EFI_ICU_INPUTS if (camTriggerType[index] == TRIGGER_ICU) icuTriggerTurnOffInputPin(brainPin); +#endif if (camTriggerType[index] == TRIGGER_EXTI) extiTriggerTurnOffInputPin(brainPin); From e4cee32e7d799dec36f2423918b6b6aade9c7b37 Mon Sep 17 00:00:00 2001 From: rusefi Date: Wed, 6 May 2020 19:10:56 -0400 Subject: [PATCH 2/7] dron0gus --- misc/git_scripts/git_add_upstream.bat | 1 + 1 file changed, 1 insertion(+) diff --git a/misc/git_scripts/git_add_upstream.bat b/misc/git_scripts/git_add_upstream.bat index 6afd00c4e7..841d42af2e 100644 --- a/misc/git_scripts/git_add_upstream.bat +++ b/misc/git_scripts/git_add_upstream.bat @@ -4,6 +4,7 @@ git remote add upstream https://github.com/rusefi/rusefi.git rem The heros, in alpabetical order git remote add andreika-git https://github.com/andreika-git/rusefi git remote add DonaldBecker https://github.com/DonaldBecker/rusefi +git remote add dron0gus https://github.com/dron0gus/rusefi git remote add mck1117 https://github.com/mck1117/rusefi git remote add NOx-z https://github.com/NOx-z/rusefi From 7e817fb4fd4699aa32f48c7b639296d8ad1a6027 Mon Sep 17 00:00:00 2001 From: rusefi Date: Wed, 6 May 2020 19:15:52 -0400 Subject: [PATCH 3/7] steps towards tle8888 --- firmware/util/efilib.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/firmware/util/efilib.h b/firmware/util/efilib.h index 8b142003cf..fd3858e6a8 100644 --- a/firmware/util/efilib.h +++ b/firmware/util/efilib.h @@ -19,6 +19,9 @@ #define BIT(n) (UINT32_C(1) << (n)) +// we also have efi::size which probably does not work for C code +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + // human-readable IDs start from 1 while computer-readbale indexes start from 0 #define ID2INDEX(id) ((id) - 1) From 95d1771bc535c2fe934427e2ae7bf8f54e8adf34 Mon Sep 17 00:00:00 2001 From: rusefi Date: Wed, 6 May 2020 19:20:12 -0400 Subject: [PATCH 4/7] steps towards tle8888 --- firmware/hw_layer/drivers/gpio/tle8888.h | 1 + firmware/hw_layer/pin_repository.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/firmware/hw_layer/drivers/gpio/tle8888.h b/firmware/hw_layer/drivers/gpio/tle8888.h index 82813abc42..73c325e863 100644 --- a/firmware/hw_layer/drivers/gpio/tle8888.h +++ b/firmware/hw_layer/drivers/gpio/tle8888.h @@ -26,6 +26,7 @@ #define Window_watchdog_close_window_time_ms 100.8 #define getRegisterFromResponse(x) (((x) >> 1) & 0x7f) +#define getDataFromResponse(x) (((x) >> 8) & 0xff) // unchangeable value for TLE8888QK // unused for now diff --git a/firmware/hw_layer/pin_repository.cpp b/firmware/hw_layer/pin_repository.cpp index 7da677eeb6..ded995de75 100644 --- a/firmware/hw_layer/pin_repository.cpp +++ b/firmware/hw_layer/pin_repository.cpp @@ -108,10 +108,10 @@ void tle8888_dump_regs(void) for (int request = 0; request < 0x7e + 1; request++) { uint16_t tmp; tle8888_read_reg(request, &tmp); - uint8_t response = getRegisterFromResponse(tmp); - uint8_t data = (tmp >> 8) & 0xff; + uint8_t reg = getRegisterFromResponse(tmp); + uint8_t data = getDataFromResponse(tmp); - scheduleMsg(&logger, "%02x: %02x", response, data); + scheduleMsg(&logger, "%02x: %02x", reg, data); } } #endif From 7007627b70844efa550660ad60e19209dc4a0af2 Mon Sep 17 00:00:00 2001 From: dron0gus Date: Thu, 7 May 2020 03:06:50 +0300 Subject: [PATCH 5/7] [SAFE] Debug cleanups (#1403) * electronic throttle: inprove debug * idle thread: show debug info for configured idle driver * gpio-chips: make private functions static --- firmware/controllers/actuators/dc_motors.cpp | 9 +++------ firmware/controllers/actuators/dc_motors.h | 2 +- .../actuators/electronic_throttle.cpp | 13 +++++++++---- firmware/controllers/actuators/idle_thread.cpp | 16 ++++++++++------ firmware/hw_layer/drivers/gpio/tle8888.c | 6 +++--- 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/firmware/controllers/actuators/dc_motors.cpp b/firmware/controllers/actuators/dc_motors.cpp index 6773b6e558..ef18f587b0 100644 --- a/firmware/controllers/actuators/dc_motors.cpp +++ b/firmware/controllers/actuators/dc_motors.cpp @@ -126,12 +126,9 @@ void setDcMotorDuty(size_t index, float duty) { } #if EFI_PROD_CODE -void showDcMotorInfo(Logging* logger) { - for (int i = 0 ; i < engine->etbActualCount; i++) { - EtbHardware *etb = &etbHardware[i]; +void showDcMotorInfo(Logging* logger, int i) { + EtbHardware *etb = &etbHardware[i]; - scheduleMsg(logger, "ETB %d", i); - scheduleMsg(logger, "Motor: dir=%d DC=%f", etb->dcMotor.isOpenDirection(), etb->dcMotor.get()); - } + scheduleMsg(logger, " motor: dir=%d DC=%f", etb->dcMotor.isOpenDirection(), etb->dcMotor.get()); } #endif diff --git a/firmware/controllers/actuators/dc_motors.h b/firmware/controllers/actuators/dc_motors.h index f587331805..baa359c935 100644 --- a/firmware/controllers/actuators/dc_motors.h +++ b/firmware/controllers/actuators/dc_motors.h @@ -20,5 +20,5 @@ void setDcMotorFrequency(size_t index, int hz); void setDcMotorDuty(size_t index, float duty); #if EFI_PROD_CODE -void showDcMotorInfo(Logging* logger); +void showDcMotorInfo(Logging* logger, int i); #endif diff --git a/firmware/controllers/actuators/electronic_throttle.cpp b/firmware/controllers/actuators/electronic_throttle.cpp index 98b3582ee5..0ee64eb419 100644 --- a/firmware/controllers/actuators/electronic_throttle.cpp +++ b/firmware/controllers/actuators/electronic_throttle.cpp @@ -502,10 +502,15 @@ static void showEthInfo(void) { hwPortname(CONFIG(etbIo[0].controlPin1)), currentEtbDuty, engineConfiguration->etbFreq); - scheduleMsg(&logger, "dir1=%s", hwPortname(CONFIG(etbIo[0].directionPin1))); - scheduleMsg(&logger, "dir2=%s", hwPortname(CONFIG(etbIo[0].directionPin2))); - - showDcMotorInfo(&logger); + int i; + for (i = 0; i < engine->etbActualCount; i++) { + scheduleMsg(&logger, "ETB%d", i); + scheduleMsg(&logger, " dir1=%s", hwPortname(CONFIG(etbIo[i].directionPin1))); + scheduleMsg(&logger, " dir2=%s", hwPortname(CONFIG(etbIo[i].directionPin2))); + scheduleMsg(&logger, " control=%s", hwPortname(CONFIG(etbIo[i].controlPin1))); + scheduleMsg(&logger, " disable=%s", hwPortname(CONFIG(etbIo[i].disablePin))); + showDcMotorInfo(&logger, i); + } #endif /* EFI_PROD_CODE */ } diff --git a/firmware/controllers/actuators/idle_thread.cpp b/firmware/controllers/actuators/idle_thread.cpp index df3afa96dc..a6010d949a 100644 --- a/firmware/controllers/actuators/idle_thread.cpp +++ b/firmware/controllers/actuators/idle_thread.cpp @@ -120,12 +120,16 @@ static void showIdleInfo(void) { getIdlePosition(), boolToString(CONFIG(useStepperIdle))); if (CONFIG(useStepperIdle)) { - scheduleMsg(logger, "directionPin=%s reactionTime=%.2f", hwPortname(CONFIG(idle).stepperDirectionPin), - engineConfiguration->idleStepperReactionTime); - scheduleMsg(logger, "stepPin=%s steps=%d", hwPortname(CONFIG(idle).stepperStepPin), - engineConfiguration->idleStepperTotalSteps); - scheduleMsg(logger, "enablePin=%s/%d", hwPortname(engineConfiguration->stepperEnablePin), - engineConfiguration->stepperEnablePinMode); + if (CONFIG(useHbridges)) { + /* TODO */ + } else { + scheduleMsg(logger, "directionPin=%s reactionTime=%.2f", hwPortname(CONFIG(idle).stepperDirectionPin), + engineConfiguration->idleStepperReactionTime); + scheduleMsg(logger, "stepPin=%s steps=%d", hwPortname(CONFIG(idle).stepperStepPin), + engineConfiguration->idleStepperTotalSteps); + scheduleMsg(logger, "enablePin=%s/%d", hwPortname(engineConfiguration->stepperEnablePin), + engineConfiguration->stepperEnablePinMode); + } } else { if (!CONFIG(isDoubleSolenoidIdle)) { scheduleMsg(logger, "idle valve freq=%d on %s", CONFIG(idle).solenoidFrequency, diff --git a/firmware/hw_layer/drivers/gpio/tle8888.c b/firmware/hw_layer/drivers/gpio/tle8888.c index ccbbf66b94..d9dddb22a1 100644 --- a/firmware/hw_layer/drivers/gpio/tle8888.c +++ b/firmware/hw_layer/drivers/gpio/tle8888.c @@ -630,7 +630,7 @@ void requestTLE8888initialization(void) { /* Driver exported functions. */ /*==========================================================================*/ -int tle8888_writePad(void *data, unsigned int pin, int value) { +static int tle8888_writePad(void *data, unsigned int pin, int value) { if ((pin >= TLE8888_OUTPUTS) || (data == NULL)) return -1; @@ -736,7 +736,7 @@ void tle8888_read_reg(uint16_t reg, uint16_t *val) tle8888_spi_rw(chip, CMD_R(reg), val); } -int tle8888_init(void * data) +static int tle8888_init(void * data) { int ret; struct tle8888_priv *chip; @@ -763,7 +763,7 @@ int tle8888_init(void * data) return 0; } -int tle8888_deinit(void *data) +static int tle8888_deinit(void *data) { (void)data; From 55159cae44910e31d797af54ed61910668a8a7e7 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Wed, 6 May 2020 18:00:40 -0700 Subject: [PATCH 6/7] short term fuel trim: part 1 (#1402) * add cell * add stft cell tests * add bit * minimally generate * config defaults --- .../controllers/algo/engine_configuration.cpp | 46 ++++++++-- .../math/closed_loop_fuel_cell.cpp | 90 +++++++++++++++++++ .../controllers/math/closed_loop_fuel_cell.h | 43 +++++++++ firmware/controllers/math/math.mk | 4 +- firmware/integration/rusefi_config.txt | 2 +- unit_tests/tests/test_stft.cpp | 52 +++++++++++ unit_tests/tests/tests.mk | 1 + 7 files changed, 229 insertions(+), 9 deletions(-) create mode 100644 firmware/controllers/math/closed_loop_fuel_cell.cpp create mode 100644 firmware/controllers/math/closed_loop_fuel_cell.h create mode 100644 unit_tests/tests/test_stft.cpp diff --git a/firmware/controllers/algo/engine_configuration.cpp b/firmware/controllers/algo/engine_configuration.cpp index bff122ee79..7d73d7ed5c 100644 --- a/firmware/controllers/algo/engine_configuration.cpp +++ b/firmware/controllers/algo/engine_configuration.cpp @@ -627,6 +627,44 @@ void setDefaultMultisparkParameters(DECLARE_ENGINE_PARAMETER_SIGNATURE) { engineConfiguration->multisparkMaxSparkingAngle = 30; } +void setDefaultStftSettings(DECLARE_ENGINE_PARAMETER_SIGNATURE) { + auto& cfg = CONFIG(stft); + + // Default to disabled + CONFIG(fuelClosedLoopCorrectionEnabled) = false; + + // Default to proportional mode (for wideband sensors) + CONFIG(stftIgnoreErrorMagnitude) = false; + + // 60 second startup delay - some O2 sensors are slow to warm up. + cfg.startupDelay = 60; + + // Only correct in [12.0, 17.0] + cfg.minAfr = 120; + cfg.maxAfr = 170; + + // Above 60 deg C + cfg.minClt = 60; + + // 0.5% deadband + cfg.deadband = 5; + + // Sensible region defaults + cfg.maxIdleRegionRpm = 1000 / RPM_1_BYTE_PACKING_MULT; + cfg.maxOverrunLoad = 35; + cfg.minPowerLoad = 85; + + // Sensible cell defaults + for (size_t i = 0; i < efi::size(cfg.cellCfgs); i++) { + // 30 second time constant - nice and slow + cfg.cellCfgs[i].timeConstant = 30 * 10; + + /// Allow +-5% + cfg.cellCfgs[i].maxAdd = 5; + cfg.cellCfgs[i].maxRemove = -5; + } +} + void setDefaultGppwmParameters(DECLARE_ENGINE_PARAMETER_SIGNATURE) { // Same config for all channels for (size_t i = 0; i < efi::size(CONFIG(gppwm)); i++) { @@ -852,13 +890,7 @@ static void setDefaultEngineConfiguration(DECLARE_ENGINE_PARAMETER_SIGNATURE) { setDefaultCrankingSettings(PASS_ENGINE_PARAMETER_SIGNATURE); - engineConfiguration->fuelClosedLoopCorrectionEnabled = false; - engineConfiguration->fuelClosedLoopCltThreshold = 70; - engineConfiguration->fuelClosedLoopRpmThreshold = 900; - engineConfiguration->fuelClosedLoopTpsThreshold = 80; - engineConfiguration->fuelClosedLoopAfrLowThreshold = 10.3; - engineConfiguration->fuelClosedLoopAfrHighThreshold = 19.8; - engineConfiguration->fuelClosedLoopPid.pFactor = -0.1; + setDefaultStftSettings(PASS_ENGINE_PARAMETER_SIGNATURE); /** * Idle control defaults diff --git a/firmware/controllers/math/closed_loop_fuel_cell.cpp b/firmware/controllers/math/closed_loop_fuel_cell.cpp new file mode 100644 index 0000000000..c4e10611c6 --- /dev/null +++ b/firmware/controllers/math/closed_loop_fuel_cell.cpp @@ -0,0 +1,90 @@ +#include "closed_loop_fuel_cell.h" +#include "engine.h" +#include "engine_configuration_generated_structures.h" + +EXTERN_ENGINE; + +constexpr float integrator_dt = FAST_CALLBACK_PERIOD_MS * 0.001f; + +void ClosedLoopFuelCellBase::update(float lambdaDeadband, bool ignoreErrorMagnitude DECLARE_ENGINE_PARAMETER_SUFFIX) +{ + // Compute how far off target we are + float lambdaError = getLambdaError(PASS_ENGINE_PARAMETER_SIGNATURE); + + // If we're within the deadband, make no adjustment. + if (absF(lambdaError) < lambdaDeadband) { + return; + } + + // Fixed magnitude - runs in constant adjustment rate mode + if (ignoreErrorMagnitude) { + if (lambdaError > 0) { + lambdaError = 0.1f; + } else { + lambdaError = -0.1f; + } + } + + // Integrate + float adjust = getIntegratorGain() * lambdaError * integrator_dt + + m_adjustment; + + // Clamp to bounds + float minAdjust = getMinAdjustment(); + float maxAdjust = getMaxAdjustment(); + + if (adjust > maxAdjust) { + adjust = maxAdjust; + } else if (adjust < minAdjust) { + adjust = minAdjust; + } + + // Save state + m_adjustment = adjust; +} + +float ClosedLoopFuelCellBase::getAdjustment() const { + return 1.0f + m_adjustment; +} + +float ClosedLoopFuelCellImpl::getLambdaError(DECLARE_ENGINE_PARAMETER_SIGNATURE) const { + return (ENGINE(sensors.currentAfr) - ENGINE(engineState.targetAFR)) / 14.7f; +} + +#define MAX_ADJ (0.25f) + +float ClosedLoopFuelCellImpl::getMaxAdjustment() const { + if (!m_config) { + // If no config, disallow adjustment. + return 0; + } + + float raw = m_config->maxAdd * 0.01f; + // Don't allow maximum less than 0, or more than maximum adjustment + return minF(MAX_ADJ, maxF(raw, 0)); +} + +float ClosedLoopFuelCellImpl::getMinAdjustment() const { + if (!m_config) { + // If no config, disallow adjustment. + return 0; + } + + float raw = m_config->maxRemove * 0.01f; + // Don't allow minimum more than 0, or more than maximum adjustment + return maxF(-MAX_ADJ, minF(raw, 0)); +} + +float ClosedLoopFuelCellImpl::getIntegratorGain() const { + if (!m_config) { + // If no config, disallow adjustment. + return 0.0f; + } + + float timeConstant = m_config->timeConstant * 0.1f; + + // Clamp to reasonable limits - 100ms to 100s + timeConstant = maxF(0.1f, minF(timeConstant, 100)); + + return 1 / timeConstant; +} diff --git a/firmware/controllers/math/closed_loop_fuel_cell.h b/firmware/controllers/math/closed_loop_fuel_cell.h new file mode 100644 index 0000000000..c042fcbe4a --- /dev/null +++ b/firmware/controllers/math/closed_loop_fuel_cell.h @@ -0,0 +1,43 @@ +#pragma once + +#include "globalaccess.h" + +class ClosedLoopFuelCellBase { +public: + // Update the cell's internal state - adjusting fuel up/down as appropriate + void update(float lambdaDeadband, bool ignoreErrorMagnitude DECLARE_ENGINE_PARAMETER_SUFFIX); + + // Get the current adjustment amount, without altering internal state. + float getAdjustment() const; + +protected: + // Helpers - virtual for mocking + virtual float getLambdaError(DECLARE_ENGINE_PARAMETER_SIGNATURE) const = 0; + virtual float getMaxAdjustment() const = 0; + virtual float getMinAdjustment() const = 0; + virtual float getIntegratorGain() const = 0; + +private: + // Current fueling adjustment. + // 0 = no adjustment. + // 0.1 = add 10% fuel. + float m_adjustment = 0; +}; + +struct stft_cell_cfg_s; + +class ClosedLoopFuelCellImpl final : public ClosedLoopFuelCellBase { +public: + void configure(const stft_cell_cfg_s* configuration) { + m_config = configuration; + } + +private: + const stft_cell_cfg_s *m_config = nullptr; + +protected: + float getLambdaError(DECLARE_ENGINE_PARAMETER_SIGNATURE) const override; + float getMaxAdjustment() const override; + float getMinAdjustment() const override; + float getIntegratorGain() const override; +}; diff --git a/firmware/controllers/math/math.mk b/firmware/controllers/math/math.mk index 9d09cf68d6..3a66d4acef 100644 --- a/firmware/controllers/math/math.mk +++ b/firmware/controllers/math/math.mk @@ -3,4 +3,6 @@ CONTROLLERS_MATH_SRC = CONTROLLERS_MATH_SRC_CPP = $(PROJECT_DIR)/controllers/math/engine_math.cpp \ $(PROJECT_DIR)/controllers/math/pid_auto_tune.cpp \ - $(PROJECT_DIR)/controllers/math/speed_density.cpp + $(PROJECT_DIR)/controllers/math/speed_density.cpp \ + $(PROJECT_DIR)/controllers/math/closed_loop_fuel_cell.cpp \ + diff --git a/firmware/integration/rusefi_config.txt b/firmware/integration/rusefi_config.txt index ed25396de1..d329c0d8e9 100644 --- a/firmware/integration/rusefi_config.txt +++ b/firmware/integration/rusefi_config.txt @@ -817,7 +817,7 @@ custom maf_sensor_type_e 4 bits, S32, @OFFSET@, [0:7], @@maf_sensor_type_e_enum@ bit enableCanVss bit enableInnovateLC2 bit showHumanReadableWarning - bit unusedBit_251_10 + bit stftIgnoreErrorMagnitude bit unusedBit_251_11 bit unusedBit_251_12 bit unusedBit_251_13 diff --git a/unit_tests/tests/test_stft.cpp b/unit_tests/tests/test_stft.cpp new file mode 100644 index 0000000000..161dc149a4 --- /dev/null +++ b/unit_tests/tests/test_stft.cpp @@ -0,0 +1,52 @@ + +#include "closed_loop_fuel_cell.h" + +#include "engine.h" + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +using ::testing::_; +using ::testing::Return; +using ::testing::StrictMock; + +class MockClCell : public ClosedLoopFuelCellBase { +public: + MOCK_METHOD(float, getLambdaError, (DECLARE_ENGINE_PARAMETER_SIGNATURE), (const)); + MOCK_METHOD(float, getMaxAdjustment, (), (const)); + MOCK_METHOD(float, getMinAdjustment, (), (const)); + MOCK_METHOD(float, getIntegratorGain, (), (const)); +}; + +TEST(ClosedLoopCell, TestDeadband) { + StrictMock cl; + + // Error is more than deadtime, so nothing else should be called + EXPECT_CALL(cl, getLambdaError(_, _, _)) + .WillOnce(Return(0.05f)); + + cl.update(0.1f, true, nullptr, nullptr, nullptr); + + // Should be zero adjustment + EXPECT_FLOAT_EQ(cl.getAdjustment(), 1.0f); +} + +TEST(ClosedLoopFuelCell, AdjustRate) { + StrictMock cl; + + // Error is more than deadtime, so nothing else should be called + EXPECT_CALL(cl, getLambdaError(_, _, _)) + .WillOnce(Return(0.1f)); + EXPECT_CALL(cl, getMinAdjustment()) + .WillOnce(Return(-0.2f)); + EXPECT_CALL(cl, getMaxAdjustment()) + .WillOnce(Return(0.2f)); + EXPECT_CALL(cl, getIntegratorGain()) + .WillOnce(Return(2.0f)); + + cl.update(0.0f, false, nullptr, nullptr, nullptr); + + // Should have integrated 0.2 * dt + // dt = 1000.0f / FAST_CALLBACK_PERIOD_MS + EXPECT_FLOAT_EQ(cl.getAdjustment(), 1 + (0.2f / (1000.0f / FAST_CALLBACK_PERIOD_MS))); +} diff --git a/unit_tests/tests/tests.mk b/unit_tests/tests/tests.mk index 499c238802..9927a08885 100644 --- a/unit_tests/tests/tests.mk +++ b/unit_tests/tests/tests.mk @@ -49,6 +49,7 @@ TESTS_SRC_CPP = \ tests/sensor/redundant.cpp \ tests/sensor/test_sensor_init.cpp \ tests/test_closed_loop_controller.cpp \ + tests/test_stft.cpp \ tests/test_boost.cpp \ tests/test_gppwm.cpp \ tests/test_fuel_math.cpp \ From 9a7597f6e7cb0918ef0ecea2eff2fa0cb6190b39 Mon Sep 17 00:00:00 2001 From: rusefi Date: Wed, 6 May 2020 22:04:53 -0400 Subject: [PATCH 7/7] Fresh generated - auto --- .../models/src/com/rusefi/config/generated/Fields.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java_console/models/src/com/rusefi/config/generated/Fields.java b/java_console/models/src/com/rusefi/config/generated/Fields.java index 6945ba9399..821c9363d6 100644 --- a/java_console/models/src/com/rusefi/config/generated/Fields.java +++ b/java_console/models/src/com/rusefi/config/generated/Fields.java @@ -1,6 +1,6 @@ package com.rusefi.config.generated; -// this file was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.bat integration\rusefi_config.txt Wed May 06 12:32:31 EDT 2020 +// this file was generated automatically by rusEfi tool ConfigDefinition.jar based on gen_config.bat integration\rusefi_config.txt Wed May 06 22:04:17 EDT 2020 // by class com.rusefi.output.FileJavaFieldsConsumer import com.rusefi.config.*; @@ -1335,6 +1335,7 @@ public class Fields { public static final int stft_offset = 1064; public static final int stft_offset_hex = 428; public static final int stft_startupDelay_offset = 1071; + public static final int stftIgnoreErrorMagnitude_offset = 976; public static final int storageMode_offset = 2260; public static final int tachOutputPin_offset = 704; public static final int tachOutputPinMode_offset = 705; @@ -1548,7 +1549,6 @@ public class Fields { public static final int unusedAtOldBoardConfigurationEnd_offset = 1160; public static final int unusedAtOldBoardConfigurationEnd_offset_hex = 488; public static final int unusedBit4_1476_offset = 1476; - public static final int unusedBit_251_10_offset = 976; public static final int unusedBit_251_11_offset = 976; public static final int unusedBit_251_12_offset = 976; public static final int unusedBit_251_13_offset = 976; @@ -2105,7 +2105,7 @@ public class Fields { public static final Field ENABLECANVSS = Field.create("ENABLECANVSS", 976, FieldType.BIT, 7); public static final Field ENABLEINNOVATELC2 = Field.create("ENABLEINNOVATELC2", 976, FieldType.BIT, 8); public static final Field SHOWHUMANREADABLEWARNING = Field.create("SHOWHUMANREADABLEWARNING", 976, FieldType.BIT, 9); - public static final Field UNUSEDBIT_251_10 = Field.create("UNUSEDBIT_251_10", 976, FieldType.BIT, 10); + public static final Field STFTIGNOREERRORMAGNITUDE = Field.create("STFTIGNOREERRORMAGNITUDE", 976, FieldType.BIT, 10); public static final Field UNUSEDBIT_251_11 = Field.create("UNUSEDBIT_251_11", 976, FieldType.BIT, 11); public static final Field UNUSEDBIT_251_12 = Field.create("UNUSEDBIT_251_12", 976, FieldType.BIT, 12); public static final Field UNUSEDBIT_251_13 = Field.create("UNUSEDBIT_251_13", 976, FieldType.BIT, 13); @@ -3077,7 +3077,7 @@ public class Fields { ENABLECANVSS, ENABLEINNOVATELC2, SHOWHUMANREADABLEWARNING, - UNUSEDBIT_251_10, + STFTIGNOREERRORMAGNITUDE, UNUSEDBIT_251_11, UNUSEDBIT_251_12, UNUSEDBIT_251_13,