refactor decel fuel cut (#3830)
* refactor dfco * s * output channel logs dfco * slightly cheeky comment
This commit is contained in:
parent
304b45e039
commit
717d931e78
|
@ -287,6 +287,7 @@ uint16_t rpmAcceleration;dRPM;"RPM/s",1, 0, 0, 0, 0
|
||||||
bit launchIsLaunchCondition;
|
bit launchIsLaunchCondition;
|
||||||
bit launchCombinedConditions
|
bit launchCombinedConditions
|
||||||
bit launchActivatePinState
|
bit launchActivatePinState
|
||||||
|
bit dfcoActive
|
||||||
|
|
||||||
uint8_t TEMPLOG_MAP_AT_CYCLE_COUNT;;"", 1, 0, -10000, 10000, 3
|
uint8_t TEMPLOG_MAP_AT_CYCLE_COUNT;;"", 1, 0, -10000, 10000, 3
|
||||||
uint8_t boostControllerOutput;;"", 1, 0, -10000, 10000, 0
|
uint8_t boostControllerOutput;;"", 1, 0, -10000, 10000, 0
|
||||||
|
|
|
@ -661,6 +661,7 @@ static void updateFlags() {
|
||||||
engine->outputChannels.isIgnitionEnabledIndicator = engine->limpManager.allowIgnition().value;
|
engine->outputChannels.isIgnitionEnabledIndicator = engine->limpManager.allowIgnition().value;
|
||||||
engine->outputChannels.isInjectionEnabledIndicator = engine->limpManager.allowInjection().value;
|
engine->outputChannels.isInjectionEnabledIndicator = engine->limpManager.allowInjection().value;
|
||||||
engine->outputChannels.isCylinderCleanupActivated = engine->isCylinderCleanupMode;
|
engine->outputChannels.isCylinderCleanupActivated = engine->isCylinderCleanupMode;
|
||||||
|
engine->outputChannels.dfcoActive = engine->module<DfcoController>()->cutFuel();
|
||||||
|
|
||||||
#if EFI_LAUNCH_CONTROL
|
#if EFI_LAUNCH_CONTROL
|
||||||
engine->outputChannels.launchTriggered = engine->launchController.isLaunchCondition;
|
engine->outputChannels.launchTriggered = engine->launchController.isLaunchCondition;
|
||||||
|
|
|
@ -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/airmass/speed_density_base.cpp \
|
||||||
$(PROJECT_DIR)/controllers/algo/fuel/fuel_computer.cpp \
|
$(PROJECT_DIR)/controllers/algo/fuel/fuel_computer.cpp \
|
||||||
$(PROJECT_DIR)/controllers/algo/fuel/injector_model.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/nmea.cpp \
|
||||||
$(PROJECT_DIR)/controllers/algo/defaults/default_base_engine.cpp \
|
$(PROJECT_DIR)/controllers/algo/defaults/default_base_engine.cpp \
|
||||||
$(PROJECT_DIR)/controllers/algo/defaults/default_cranking.cpp \
|
$(PROJECT_DIR)/controllers/algo/defaults/default_cranking.cpp \
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "boost_control.h"
|
#include "boost_control.h"
|
||||||
#include "ignition_controller.h"
|
#include "ignition_controller.h"
|
||||||
#include "alternator_controller.h"
|
#include "alternator_controller.h"
|
||||||
|
#include "dfco.h"
|
||||||
|
|
||||||
#ifndef EFI_UNIT_TEST
|
#ifndef EFI_UNIT_TEST
|
||||||
#error EFI_UNIT_TEST must be defined!
|
#error EFI_UNIT_TEST must be defined!
|
||||||
|
@ -182,6 +183,7 @@ public:
|
||||||
IgnitionController,
|
IgnitionController,
|
||||||
AcController,
|
AcController,
|
||||||
PrimeController,
|
PrimeController,
|
||||||
|
DfcoController,
|
||||||
EngineModule // dummy placeholder so the previous entries can all have commas
|
EngineModule // dummy placeholder so the previous entries can all have commas
|
||||||
> engineModules;
|
> engineModules;
|
||||||
|
|
||||||
|
|
|
@ -123,8 +123,7 @@ void EngineState::periodicFastCallback() {
|
||||||
// todo: move this into slow callback, no reason for CLT corr to be here
|
// todo: move this into slow callback, no reason for CLT corr to be here
|
||||||
running.coolantTemperatureCoefficient = getCltFuelCorrection();
|
running.coolantTemperatureCoefficient = getCltFuelCorrection();
|
||||||
|
|
||||||
// Fuel cut-off isn't just 0 or 1, it can be tapered
|
engine->module<DfcoController>()->update();
|
||||||
fuelCutoffCorrection = getFuelCutOffCorrection(nowNt, rpm);
|
|
||||||
|
|
||||||
// post-cranking fuel enrichment.
|
// post-cranking fuel enrichment.
|
||||||
// for compatibility reasons, apply only if the factor is greater than unity (only allow adding fuel)
|
// for compatibility reasons, apply only if the factor is greater than unity (only allow adding fuel)
|
||||||
|
|
|
@ -59,10 +59,6 @@ public:
|
||||||
// Angle between firing the main (primary) spark and the secondary (trailing) spark
|
// Angle between firing the main (primary) spark and the secondary (trailing) spark
|
||||||
angle_t trailingSparkAngle = 0;
|
angle_t trailingSparkAngle = 0;
|
||||||
|
|
||||||
// fuel-related;
|
|
||||||
float fuelCutoffCorrection = 0;
|
|
||||||
efitick_t coastingFuelCutStartTime = 0;
|
|
||||||
|
|
||||||
efitick_t timeSinceLastTChargeK;
|
efitick_t timeSinceLastTChargeK;
|
||||||
|
|
||||||
float currentVe = 0;
|
float currentVe = 0;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
};
|
|
@ -280,8 +280,10 @@ float getInjectionMass(int rpm) {
|
||||||
float cycleFuelMass = getCycleFuelMass(isCranking, baseFuelMass);
|
float cycleFuelMass = getCycleFuelMass(isCranking, baseFuelMass);
|
||||||
efiAssert(CUSTOM_ERR_ASSERT, !cisnan(cycleFuelMass), "NaN cycleFuelMass", 0);
|
efiAssert(CUSTOM_ERR_ASSERT, !cisnan(cycleFuelMass), "NaN cycleFuelMass", 0);
|
||||||
|
|
||||||
// Fuel cut-off isn't just 0 or 1, it can be tapered
|
if (engine->module<DfcoController>()->cutFuel()) {
|
||||||
cycleFuelMass *= engine->engineState.fuelCutoffCorrection;
|
// If decel fuel cut, zero out fuel
|
||||||
|
cycleFuelMass = 0;
|
||||||
|
}
|
||||||
|
|
||||||
float durationMultiplier = getInjectionModeDurationMultiplier();
|
float durationMultiplier = getInjectionModeDurationMultiplier();
|
||||||
float injectionFuelMass = cycleFuelMass * durationMultiplier;
|
float injectionFuelMass = cycleFuelMass * durationMultiplier;
|
||||||
|
@ -347,57 +349,6 @@ float getIatFuelCorrection() {
|
||||||
return interpolate2d(iat, config->iatFuelCorrBins, config->iatFuelCorr);
|
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() {
|
float getBaroCorrection() {
|
||||||
if (Sensor::hasSensor(SensorType::BarometricPressure)) {
|
if (Sensor::hasSensor(SensorType::BarometricPressure)) {
|
||||||
// Default to 1atm if failed
|
// Default to 1atm if failed
|
||||||
|
|
|
@ -22,7 +22,6 @@ angle_t getInjectionOffset(float rpm, float load);
|
||||||
float getIatFuelCorrection();
|
float getIatFuelCorrection();
|
||||||
|
|
||||||
float getCltFuelCorrection();
|
float getCltFuelCorrection();
|
||||||
float getFuelCutOffCorrection(efitick_t nowNt, int rpm);
|
|
||||||
angle_t getCltTimingCorrection();
|
angle_t getCltTimingCorrection();
|
||||||
float getCrankingFuel(float baseFuel);
|
float getCrankingFuel(float baseFuel);
|
||||||
float getCrankingFuel3(float baseFuel, uint32_t revolutionCounterSinceStart);
|
float getCrankingFuel3(float baseFuel, uint32_t revolutionCounterSinceStart);
|
||||||
|
|
|
@ -1235,6 +1235,7 @@ gaugeCategory = DynoView
|
||||||
indicator = { acState }, "AC off", "AC on", white, black, blue, white
|
indicator = { acState }, "AC off", "AC on", white, black, blue, white
|
||||||
indicator = { isIdleClosedLoop }, "not idling", "idling", white, black, green, black
|
indicator = { isIdleClosedLoop }, "not idling", "idling", white, black, green, black
|
||||||
indicator = { isIdleCoasting }, "not coasting", "coasting", 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
|
; error codes
|
||||||
indicator = { isTpsError}, "tps", "tps error", white, black, red, black
|
indicator = { isTpsError}, "tps", "tps error", white, black, red, black
|
||||||
|
|
Loading…
Reference in New Issue