From d84cf5eea81e524ff4e6afdf48ac9238bbafc3f1 Mon Sep 17 00:00:00 2001 From: rusefillc Date: Sat, 16 Oct 2021 20:16:40 -0400 Subject: [PATCH] splitting accelerations --- .../controllers/algo/accel_enrichment.cpp | 118 ---------------- firmware/controllers/algo/accel_enrichment.h | 16 --- firmware/controllers/algo/algo.mk | 1 + firmware/controllers/algo/event_registry.h | 1 + firmware/controllers/algo/wall_fuel.cpp | 127 ++++++++++++++++++ firmware/controllers/algo/wall_fuel.h | 22 +++ firmware/controllers/math/speed_density.cpp | 2 +- 7 files changed, 152 insertions(+), 135 deletions(-) create mode 100644 firmware/controllers/algo/wall_fuel.cpp create mode 100644 firmware/controllers/algo/wall_fuel.h diff --git a/firmware/controllers/algo/accel_enrichment.cpp b/firmware/controllers/algo/accel_enrichment.cpp index ad1d052ba4..4d8b85b616 100644 --- a/firmware/controllers/algo/accel_enrichment.cpp +++ b/firmware/controllers/algo/accel_enrichment.cpp @@ -22,128 +22,10 @@ */ #include "pch.h" -#include "trigger_central.h" #include "accel_enrichment.h" static tps_tps_Map3D_t tpsTpsMap; -void WallFuel::resetWF() { - wallFuel = 0; -} - -// -floatms_t WallFuel::adjust(floatms_t desiredFuel DECLARE_ENGINE_PARAMETER_SUFFIX) { - invocationCounter++; - if (cisnan(desiredFuel)) { - return desiredFuel; - } - // disable this correction for cranking - if (ENGINE(rpmCalculator).isCranking()) { - return desiredFuel; - } - - ScopePerf perf(PE::WallFuelAdjust); - - /* - this math is based on - SAE 810494 by C. F. Aquino - SAE 1999-01-0553 by Peter J Maloney - - M_cmd = commanded fuel mass (output of this function) - desiredFuel = desired fuel mass (input to this function) - fuelFilmMass = fuel film mass (how much is currently on the wall) - - First we compute how much fuel to command, by accounting for - a) how much fuel will evaporate from the walls, entering the air - b) how much fuel from the injector will hit the walls, being deposited - - Next, we compute how much fuel will be deposited on the walls. The net - effect of these two steps is computed (some leaves walls, some is deposited) - and stored back in fuelFilmMass. - - alpha describes the amount of fuel that REMAINS on the wall per cycle. - It is computed as a function of the evaporation time constant (tau) and - the time the fuel spent on the wall this cycle, (recriprocal RPM). - - beta describes the amount of fuel that hits the wall. - - TODO: these parameters, tau and beta vary with various engine parameters, - most notably manifold pressure (as a proxy for air speed), and coolant - temperature (as a proxy for the intake valve and runner temperature). - - TAU: decreases with increasing temperature. - decreases with decreasing manifold pressure. - - BETA: decreases with increasing temperature. - decreases with decreasing manifold pressure. - */ - - // if tau is really small, we get div/0. - // you probably meant to disable wwae. - float tau = CONFIG(wwaeTau); - if (tau < 0.01f) { - return desiredFuel; - } - - // Ignore really slow RPM - int rpm = GET_RPM(); - if (rpm < 100) { - return desiredFuel; - } - - float alpha = expf_taylor(-120 / (rpm * tau)); - float beta = CONFIG(wwaeBeta); - -#if EFI_TUNER_STUDIO - if (engineConfiguration->debugMode == DBG_KNOCK) { - tsOutputChannels.debugFloatField1 = alpha; - tsOutputChannels.debugFloatField2 = beta; - } -#endif // EFI_TUNER_STUDIO - - // If beta is larger than alpha, the system is underdamped. - // For reasonable values {tau, beta}, this should only be possible - // at extremely low engine speeds (<300rpm ish) - // Clamp beta to less than alpha. - if (beta > alpha) { - beta = alpha; - } - - float fuelFilmMass = wallFuel; - float M_cmd = (desiredFuel - (1 - alpha) * fuelFilmMass) / (1 - beta); - -#if EFI_TUNER_STUDIO - if (engineConfiguration->debugMode == DBG_KNOCK) { - tsOutputChannels.debugFloatField3 = fuelFilmMass; - tsOutputChannels.debugFloatField4 = M_cmd; - } -#endif // EFI_TUNER_STUDIO - - // We can't inject a negative amount of fuel - // If this goes below zero we will be over-fueling slightly, - // but that's ok. - if (M_cmd <= 0) { - M_cmd = 0; - } - - // remainder on walls from last time + new from this time - float fuelFilmMassNext = alpha * fuelFilmMass + beta * M_cmd; - -#if EFI_TUNER_STUDIO - if (engineConfiguration->debugMode == DBG_KNOCK) { - tsOutputChannels.debugFloatField5 = fuelFilmMassNext; - } -#endif // EFI_TUNER_STUDIO - - wallFuel = fuelFilmMassNext; - wallFuelCorrection = M_cmd - desiredFuel; - return M_cmd; -} - -floatms_t WallFuel::getWallFuel() const { - return wallFuel; -} - int AccelEnrichment::getMaxDeltaIndex(DECLARE_ENGINE_PARAMETER_SIGNATURE) { int len = minI(cb.getSize(), cb.getCount()); diff --git a/firmware/controllers/algo/accel_enrichment.h b/firmware/controllers/algo/accel_enrichment.h index a18b2263b0..55f97425ba 100644 --- a/firmware/controllers/algo/accel_enrichment.h +++ b/firmware/controllers/algo/accel_enrichment.h @@ -60,22 +60,6 @@ private: int cycleCnt = 0; }; -/** - * Wall wetting, also known as fuel film - * See https://github.com/rusefi/rusefi/issues/151 for the theory - */ -class WallFuel : public wall_fuel_state { -public: - /** - * @param target desired squirt duration - * @return total adjusted fuel squirt duration once wall wetting is taken into effect - */ - floatms_t adjust(floatms_t target DECLARE_ENGINE_PARAMETER_SUFFIX); - floatms_t getWallFuel() const; - void resetWF(); - int invocationCounter = 0; -}; - void initAccelEnrichment(DECLARE_ENGINE_PARAMETER_SIGNATURE); void setEngineLoadAccelLen(int len); diff --git a/firmware/controllers/algo/algo.mk b/firmware/controllers/algo/algo.mk index 14249ea90d..891596522b 100644 --- a/firmware/controllers/algo/algo.mk +++ b/firmware/controllers/algo/algo.mk @@ -6,6 +6,7 @@ CONTROLLERS_ALGO_SRC_CPP = $(PROJECT_DIR)/controllers/algo/advance_map.cpp \ $(GENERATED_ENUMS_DIR)/auto_generated_commonenum.cpp \ $(PROJECT_DIR)/controllers/algo/fuel_math.cpp \ $(PROJECT_DIR)/controllers/algo/accel_enrichment.cpp \ + $(PROJECT_DIR)/controllers/algo/wall_fuel.cpp \ $(PROJECT_DIR)/controllers/algo/launch_control.cpp \ $(PROJECT_DIR)/controllers/algo/dynoview.cpp \ $(PROJECT_DIR)/controllers/algo/runtime_state.cpp \ diff --git a/firmware/controllers/algo/event_registry.h b/firmware/controllers/algo/event_registry.h index 3b312fa303..710b5680ac 100644 --- a/firmware/controllers/algo/event_registry.h +++ b/firmware/controllers/algo/event_registry.h @@ -13,6 +13,7 @@ #include "fl_stack.h" #include "trigger_structure.h" #include "accel_enrichment.h" +#include "wall_fuel.h" #define MAX_WIRES_COUNT 2 diff --git a/firmware/controllers/algo/wall_fuel.cpp b/firmware/controllers/algo/wall_fuel.cpp new file mode 100644 index 0000000000..c7928b88a8 --- /dev/null +++ b/firmware/controllers/algo/wall_fuel.cpp @@ -0,0 +1,127 @@ +/* + * @file wall_fuel.cpp + * + * @author Matthew Kennedy + */ + +#include "pch.h" +#include "wall_fuel.h" + +void WallFuel::resetWF() { + wallFuel = 0; +} + +floatms_t WallFuel::adjust(floatms_t desiredFuel DECLARE_ENGINE_PARAMETER_SUFFIX) { + invocationCounter++; + if (cisnan(desiredFuel)) { + return desiredFuel; + } + // disable this correction for cranking + if (ENGINE(rpmCalculator).isCranking()) { + return desiredFuel; + } + + ScopePerf perf(PE::WallFuelAdjust); + + /* + this math is based on + SAE 810494 by C. F. Aquino + SAE 1999-01-0553 by Peter J Maloney + + M_cmd = commanded fuel mass (output of this function) + desiredFuel = desired fuel mass (input to this function) + fuelFilmMass = fuel film mass (how much is currently on the wall) + + First we compute how much fuel to command, by accounting for + a) how much fuel will evaporate from the walls, entering the air + b) how much fuel from the injector will hit the walls, being deposited + + Next, we compute how much fuel will be deposited on the walls. The net + effect of these two steps is computed (some leaves walls, some is deposited) + and stored back in fuelFilmMass. + + alpha describes the amount of fuel that REMAINS on the wall per cycle. + It is computed as a function of the evaporation time constant (tau) and + the time the fuel spent on the wall this cycle, (recriprocal RPM). + + beta describes the amount of fuel that hits the wall. + + TODO: these parameters, tau and beta vary with various engine parameters, + most notably manifold pressure (as a proxy for air speed), and coolant + temperature (as a proxy for the intake valve and runner temperature). + + TAU: decreases with increasing temperature. + decreases with decreasing manifold pressure. + + BETA: decreases with increasing temperature. + decreases with decreasing manifold pressure. + */ + + // if tau is really small, we get div/0. + // you probably meant to disable wwae. + float tau = CONFIG(wwaeTau); + if (tau < 0.01f) { + return desiredFuel; + } + + // Ignore really slow RPM + int rpm = GET_RPM(); + if (rpm < 100) { + return desiredFuel; + } + + float alpha = expf_taylor(-120 / (rpm * tau)); + float beta = CONFIG(wwaeBeta); + +#if EFI_TUNER_STUDIO + if (engineConfiguration->debugMode == DBG_KNOCK) { + tsOutputChannels.debugFloatField1 = alpha; + tsOutputChannels.debugFloatField2 = beta; + } +#endif // EFI_TUNER_STUDIO + + // If beta is larger than alpha, the system is underdamped. + // For reasonable values {tau, beta}, this should only be possible + // at extremely low engine speeds (<300rpm ish) + // Clamp beta to less than alpha. + if (beta > alpha) { + beta = alpha; + } + + float fuelFilmMass = wallFuel; + float M_cmd = (desiredFuel - (1 - alpha) * fuelFilmMass) / (1 - beta); + +#if EFI_TUNER_STUDIO + if (engineConfiguration->debugMode == DBG_KNOCK) { + tsOutputChannels.debugFloatField3 = fuelFilmMass; + tsOutputChannels.debugFloatField4 = M_cmd; + } +#endif // EFI_TUNER_STUDIO + + // We can't inject a negative amount of fuel + // If this goes below zero we will be over-fueling slightly, + // but that's ok. + if (M_cmd <= 0) { + M_cmd = 0; + } + + // remainder on walls from last time + new from this time + float fuelFilmMassNext = alpha * fuelFilmMass + beta * M_cmd; + +#if EFI_TUNER_STUDIO + if (engineConfiguration->debugMode == DBG_KNOCK) { + tsOutputChannels.debugFloatField5 = fuelFilmMassNext; + } +#endif // EFI_TUNER_STUDIO + + wallFuel = fuelFilmMassNext; + wallFuelCorrection = M_cmd - desiredFuel; + return M_cmd; +} + +floatms_t WallFuel::getWallFuel() const { + return wallFuel; +} + + + diff --git a/firmware/controllers/algo/wall_fuel.h b/firmware/controllers/algo/wall_fuel.h new file mode 100644 index 0000000000..85efb6849d --- /dev/null +++ b/firmware/controllers/algo/wall_fuel.h @@ -0,0 +1,22 @@ +/* + * @file wall_fuel.h + * + */ + +#pragma once + +/** + * Wall wetting, also known as fuel film + * See https://github.com/rusefi/rusefi/issues/151 for the theory + */ +class WallFuel : public wall_fuel_state { +public: + /** + * @param target desired squirt duration + * @return total adjusted fuel squirt duration once wall wetting is taken into effect + */ + floatms_t adjust(floatms_t target DECLARE_ENGINE_PARAMETER_SUFFIX); + floatms_t getWallFuel() const; + void resetWF(); + int invocationCounter = 0; +}; diff --git a/firmware/controllers/math/speed_density.cpp b/firmware/controllers/math/speed_density.cpp index 464dc3e40b..f8dd337998 100644 --- a/firmware/controllers/math/speed_density.cpp +++ b/firmware/controllers/math/speed_density.cpp @@ -51,7 +51,7 @@ temperature_t getTCharge(int rpm, float tps DECLARE_ENGINE_PARAMETER_SUFFIX) { if ((engine->engineState.sd.isTChargeAirModel = (CONFIG(tChargeMode) == TCHARGE_MODE_AIR_INTERP))) { const floatms_t gramsPerMsToKgPerHour = (3600.0f * 1000.0f) / 1000.0f; // We're actually using an 'old' airMass calculated for the previous cycle, but it's ok, we're not having any self-excitaton issues - floatms_t airMassForEngine = engine->engineState.sd./***display*/airMassInOneCylinder * CONFIG(specs.cylindersCount); + floatms_t airMassForEngine = engine->engineState.sd.airMassInOneCylinder * CONFIG(specs.cylindersCount); // airMass is in grams per 1 cycle for 1 cyl. Convert it to airFlow in kg/h for the engine. // And if the engine is stopped (0 rpm), then airFlow is also zero (avoiding NaN division) floatms_t airFlow = (rpm == 0) ? 0 : airMassForEngine * gramsPerMsToKgPerHour / getEngineCycleDuration(rpm PASS_ENGINE_PARAMETER_SUFFIX);