refactor decel fuel cut (#3830)

* refactor dfco

* s

* output channel logs dfco

* slightly cheeky comment
This commit is contained in:
Matthew Kennedy 2022-01-23 16:44:41 -08:00 committed by GitHub
parent 304b45e039
commit 717d931e78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 72 additions and 60 deletions

View File

@ -287,6 +287,7 @@ uint16_t rpmAcceleration;dRPM;"RPM/s",1, 0, 0, 0, 0
bit launchIsLaunchCondition;
bit launchCombinedConditions
bit launchActivatePinState
bit dfcoActive
uint8_t TEMPLOG_MAP_AT_CYCLE_COUNT;;"", 1, 0, -10000, 10000, 3
uint8_t boostControllerOutput;;"", 1, 0, -10000, 10000, 0

View File

@ -661,6 +661,7 @@ static void updateFlags() {
engine->outputChannels.isIgnitionEnabledIndicator = engine->limpManager.allowIgnition().value;
engine->outputChannels.isInjectionEnabledIndicator = engine->limpManager.allowInjection().value;
engine->outputChannels.isCylinderCleanupActivated = engine->isCylinderCleanupMode;
engine->outputChannels.dfcoActive = engine->module<DfcoController>()->cutFuel();
#if EFI_LAUNCH_CONTROL
engine->outputChannels.launchTriggered = engine->launchController.isLaunchCondition;

View File

@ -22,6 +22,7 @@ CONTROLLERS_ALGO_SRC_CPP = $(PROJECT_DIR)/controllers/algo/advance_map.cpp \
$(PROJECT_DIR)/controllers/algo/airmass/speed_density_base.cpp \
$(PROJECT_DIR)/controllers/algo/fuel/fuel_computer.cpp \
$(PROJECT_DIR)/controllers/algo/fuel/injector_model.cpp \
$(PROJECT_DIR)/controllers/algo/fuel/dfco.cpp \
$(PROJECT_DIR)/controllers/algo/nmea.cpp \
$(PROJECT_DIR)/controllers/algo/defaults/default_base_engine.cpp \
$(PROJECT_DIR)/controllers/algo/defaults/default_cranking.cpp \

View File

@ -36,6 +36,7 @@
#include "boost_control.h"
#include "ignition_controller.h"
#include "alternator_controller.h"
#include "dfco.h"
#ifndef EFI_UNIT_TEST
#error EFI_UNIT_TEST must be defined!
@ -182,6 +183,7 @@ public:
IgnitionController,
AcController,
PrimeController,
DfcoController,
EngineModule // dummy placeholder so the previous entries can all have commas
> engineModules;

View File

@ -123,8 +123,7 @@ void EngineState::periodicFastCallback() {
// todo: move this into slow callback, no reason for CLT corr to be here
running.coolantTemperatureCoefficient = getCltFuelCorrection();
// Fuel cut-off isn't just 0 or 1, it can be tapered
fuelCutoffCorrection = getFuelCutOffCorrection(nowNt, rpm);
engine->module<DfcoController>()->update();
// post-cranking fuel enrichment.
// for compatibility reasons, apply only if the factor is greater than unity (only allow adding fuel)

View File

@ -59,10 +59,6 @@ public:
// Angle between firing the main (primary) spark and the secondary (trailing) spark
angle_t trailingSparkAngle = 0;
// fuel-related;
float fuelCutoffCorrection = 0;
efitick_t coastingFuelCutStartTime = 0;
efitick_t timeSinceLastTChargeK;
float currentVe = 0;

View File

@ -0,0 +1,48 @@
#include "pch.h"
bool DfcoController::getState() const {
if (!engineConfiguration->coastingFuelCutEnabled) {
return false;
}
auto rpm = Sensor::getOrZero(SensorType::Rpm);
const auto [tpsValid, tpsPos] = Sensor::get(SensorType::Tps1);
const auto [cltValid, clt] = Sensor::get(SensorType::Clt);
const auto [mapValid, map] = Sensor::get(SensorType::Map);
// If some sensor is broken, inhibit DFCO
if (!tpsValid || !cltValid || !mapValid) {
return false;
}
bool mapActivate = map < engineConfiguration->coastingFuelCutMap;
bool tpsActivate = tpsPos < engineConfiguration->coastingFuelCutTps;
bool cltActivate = clt > engineConfiguration->coastingFuelCutClt;
// True if throttle, MAP, and CLT are all acceptable for DFCO to occur
bool dfcoAllowed = mapActivate && tpsActivate && cltActivate;
bool rpmActivate = (rpm > engineConfiguration->coastingFuelCutRpmHigh);
bool rpmDeactivate = (rpm < engineConfiguration->coastingFuelCutRpmLow);
// RPM is high enough, and DFCO allowed
if (dfcoAllowed && rpmActivate) {
return true;
}
// RPM too low, or DFCO not allowed
if (!dfcoAllowed || rpmDeactivate) {
return false;
}
// No conditions hit, no change to state (provides hysteresis)
return m_isDfco;
}
void DfcoController::update() {
// Run state machine
m_isDfco = getState();
}
bool DfcoController::cutFuel() const {
return m_isDfco;
}

View File

@ -0,0 +1,13 @@
#pragma once
// DFCO = deceleration fuel cut off, ie, save gas when your foot is off the pedal
class DfcoController : public EngineModule {
public:
void update();
bool cutFuel() const;
private:
bool getState() const;
bool m_isDfco = false;
};

View File

@ -280,8 +280,10 @@ float getInjectionMass(int rpm) {
float cycleFuelMass = getCycleFuelMass(isCranking, baseFuelMass);
efiAssert(CUSTOM_ERR_ASSERT, !cisnan(cycleFuelMass), "NaN cycleFuelMass", 0);
// Fuel cut-off isn't just 0 or 1, it can be tapered
cycleFuelMass *= engine->engineState.fuelCutoffCorrection;
if (engine->module<DfcoController>()->cutFuel()) {
// If decel fuel cut, zero out fuel
cycleFuelMass = 0;
}
float durationMultiplier = getInjectionModeDurationMultiplier();
float injectionFuelMass = cycleFuelMass * durationMultiplier;
@ -347,57 +349,6 @@ float getIatFuelCorrection() {
return interpolate2d(iat, config->iatFuelCorrBins, config->iatFuelCorr);
}
/**
* @brief Called from EngineState::periodicFastCallback to update the state.
* @note The returned value is float, not boolean - to implement taper (smoothed correction).
* @return Fuel duration correction for fuel cut-off control (ex. if coasting). No correction if 1.0
*/
float getFuelCutOffCorrection(efitick_t nowNt, int rpm) {
// no corrections by default
float fuelCorr = 1.0f;
// coasting fuel cut-off correction
if (engineConfiguration->coastingFuelCutEnabled) {
auto [tpsValid, tpsPos] = Sensor::get(SensorType::Tps1);
if (!tpsValid) {
return 1.0f;
}
const auto [cltValid, clt] = Sensor::get(SensorType::Clt);
if (!cltValid) {
return 1.0f;
}
const auto [mapValid, map] = Sensor::get(SensorType::Map);
if (!mapValid) {
return 1.0f;
}
// gather events
bool mapDeactivate = (map >= engineConfiguration->coastingFuelCutMap);
bool tpsDeactivate = (tpsPos >= engineConfiguration->coastingFuelCutTps);
// If no CLT sensor (or broken), don't allow DFCO
bool cltDeactivate = clt < (float)engineConfiguration->coastingFuelCutClt;
bool rpmDeactivate = (rpm < engineConfiguration->coastingFuelCutRpmLow);
bool rpmActivate = (rpm > engineConfiguration->coastingFuelCutRpmHigh);
// state machine (coastingFuelCutStartTime is also used as a flag)
if (!mapDeactivate && !tpsDeactivate && !cltDeactivate && rpmActivate) {
engine->engineState.coastingFuelCutStartTime = nowNt;
} else if (mapDeactivate || tpsDeactivate || rpmDeactivate || cltDeactivate) {
engine->engineState.coastingFuelCutStartTime = 0;
}
// enable fuelcut?
if (engine->engineState.coastingFuelCutStartTime != 0) {
// todo: add taper - interpolate using (nowNt - coastingFuelCutStartTime)?
fuelCorr = 0.0f;
}
}
// todo: add other fuel cut-off checks here (possibly cutFuelOnHardLimit?)
return fuelCorr;
}
float getBaroCorrection() {
if (Sensor::hasSensor(SensorType::BarometricPressure)) {
// Default to 1atm if failed

View File

@ -22,7 +22,6 @@ angle_t getInjectionOffset(float rpm, float load);
float getIatFuelCorrection();
float getCltFuelCorrection();
float getFuelCutOffCorrection(efitick_t nowNt, int rpm);
angle_t getCltTimingCorrection();
float getCrankingFuel(float baseFuel);
float getCrankingFuel3(float baseFuel, uint32_t revolutionCounterSinceStart);

View File

@ -1235,6 +1235,7 @@ gaugeCategory = DynoView
indicator = { acState }, "AC off", "AC on", white, black, blue, white
indicator = { isIdleClosedLoop }, "not idling", "idling", white, black, green, black
indicator = { isIdleCoasting }, "not coasting", "coasting", white, black, green, black
indicator = { dfcoActive }, "no decel cut", "decel cut", white, black, yellow, black
; error codes
indicator = { isTpsError}, "tps", "tps error", white, black, red, black