2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @file accel_enrichment.cpp
|
|
|
|
* @brief Acceleration enrichment calculator
|
|
|
|
*
|
2015-08-21 12:01:36 -07:00
|
|
|
* In this file we have three strategies for acceleration/deceleration fuel correction
|
|
|
|
*
|
|
|
|
* 1) MAP rate-of-change correction
|
|
|
|
* 2) TPS rate-of-change correction
|
|
|
|
* 3) fuel film/wal wetting correction
|
|
|
|
* AWC Added to Wall Coefficient, %
|
|
|
|
* AWA Added to Wall Amount
|
|
|
|
* SOC Sucked Off wall Coefficient, %
|
|
|
|
* SOA Sucked Off wall amount
|
|
|
|
* WF current on-Wall Fuel amount
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* http://rusefi.com/wiki/index.php?title=Manual:Software:Fuel_Control
|
2015-07-10 06:01:56 -07:00
|
|
|
* @date Apr 21, 2014
|
|
|
|
* @author Dmitry Sidin
|
2015-12-31 13:02:30 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2016
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
#include "trigger_central.h"
|
|
|
|
#include "accel_enrichment.h"
|
|
|
|
#include "engine_state.h"
|
|
|
|
#include "engine_math.h"
|
|
|
|
#include "signal_executor.h"
|
2016-03-12 17:03:40 -08:00
|
|
|
#if !EFI_UNIT_TEST || defined(__DOXYGEN__)
|
2016-03-11 08:03:18 -08:00
|
|
|
#include "tunerstudio_configuration.h"
|
|
|
|
extern TunerStudioOutputChannels tsOutputChannels;
|
|
|
|
#endif
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
EXTERN_ENGINE
|
|
|
|
;
|
|
|
|
|
2016-03-11 08:03:18 -08:00
|
|
|
|
|
|
|
tps_tps_Map3D_t tpsTpsMap("tpsTps");
|
|
|
|
|
2016-01-31 14:01:29 -08:00
|
|
|
static Logging *logger = NULL;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2015-08-21 12:01:36 -07:00
|
|
|
WallFuel::WallFuel() {
|
2015-09-03 06:01:31 -07:00
|
|
|
reset();
|
2015-08-21 12:01:36 -07:00
|
|
|
}
|
|
|
|
|
2015-09-02 18:03:43 -07:00
|
|
|
void WallFuel::reset() {
|
2015-09-03 06:01:31 -07:00
|
|
|
memset(wallFuel, 0, sizeof(wallFuel));
|
2015-09-02 18:03:43 -07:00
|
|
|
}
|
|
|
|
|
2015-08-23 20:02:37 -07:00
|
|
|
floatms_t WallFuel::adjust(int injectorIndex, floatms_t target DECLARE_ENGINE_PARAMETER_S) {
|
2015-08-23 22:01:28 -07:00
|
|
|
if (cisnan(target)) {
|
|
|
|
return target;
|
|
|
|
}
|
2016-01-31 08:01:43 -08:00
|
|
|
float addedToWallCoef = CONFIG(addedToWallCoef);
|
2015-08-21 12:01:36 -07:00
|
|
|
|
2016-01-31 08:01:43 -08:00
|
|
|
/**
|
|
|
|
* What amount of fuel is sucked of the walls, based on current amount of fuel on the wall.
|
|
|
|
*/
|
|
|
|
floatms_t suckedOffWallsAmount = wallFuel[injectorIndex] * CONFIG(suckedOffCoef);
|
2015-08-21 12:01:36 -07:00
|
|
|
|
2016-01-31 08:01:43 -08:00
|
|
|
floatms_t adjustedFuelPulse = (target - suckedOffWallsAmount) / (1 - addedToWallCoef);
|
2015-08-21 12:01:36 -07:00
|
|
|
|
2016-01-31 08:01:43 -08:00
|
|
|
float addedToWallsAmount = adjustedFuelPulse * addedToWallCoef;
|
|
|
|
wallFuel[injectorIndex] += addedToWallsAmount - suckedOffWallsAmount;
|
|
|
|
engine->wallFuelCorrection = adjustedFuelPulse - target;
|
|
|
|
return adjustedFuelPulse;
|
2015-08-21 12:01:36 -07:00
|
|
|
}
|
|
|
|
|
2015-08-23 20:02:37 -07:00
|
|
|
floatms_t WallFuel::getWallFuel(int injectorIndex) {
|
|
|
|
return wallFuel[injectorIndex];
|
2015-08-23 18:03:42 -07:00
|
|
|
}
|
|
|
|
|
2016-03-10 19:02:54 -08:00
|
|
|
int AccelEnrichmemnt::getMaxDeltaIndex(DECLARE_ENGINE_PARAMETER_F) {
|
2016-03-09 21:04:40 -08:00
|
|
|
|
|
|
|
int len = minI(cb.getSize(), cb.getCount());
|
|
|
|
if (len < 2)
|
|
|
|
return 0;
|
2016-03-10 19:02:54 -08:00
|
|
|
int ci = cb.currentIndex - 1;
|
|
|
|
float maxValue = cb.get(ci) - cb.get(ci - 1);
|
|
|
|
int resultIndex = ci;
|
|
|
|
|
|
|
|
// todo: 'get' method is maybe a bit heavy because of the branching
|
|
|
|
// todo: this could be optimized with some careful magic
|
2016-03-09 21:04:40 -08:00
|
|
|
|
2016-03-10 19:02:54 -08:00
|
|
|
for (int i = 1; i<len - 1;i++) {
|
|
|
|
float v = cb.get(ci - i) - cb.get(ci - i - 1);
|
2016-03-09 21:04:40 -08:00
|
|
|
if (v > maxValue) {
|
|
|
|
maxValue = v;
|
2016-03-10 19:02:54 -08:00
|
|
|
resultIndex = ci - i;
|
2016-03-09 21:04:40 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-10 19:02:54 -08:00
|
|
|
return resultIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
float AccelEnrichmemnt::getMaxDelta(DECLARE_ENGINE_PARAMETER_F) {
|
|
|
|
int index = getMaxDeltaIndex(PASS_ENGINE_PARAMETER_F);
|
|
|
|
|
2016-03-09 21:04:40 -08:00
|
|
|
FuelSchedule *fs = engine->engineConfiguration2->injectionEvents;
|
2016-03-10 19:02:54 -08:00
|
|
|
return (cb.get(index) - (cb.get(index - 1))) * fs->eventsCount;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2016-01-02 13:01:27 -08:00
|
|
|
// todo: eliminate code duplication between these two methods! Some pointer magic would help.
|
2015-07-10 06:01:56 -07:00
|
|
|
floatms_t AccelEnrichmemnt::getTpsEnrichment(DECLARE_ENGINE_PARAMETER_F) {
|
2016-03-11 08:03:18 -08:00
|
|
|
int index = getMaxDeltaIndex(PASS_ENGINE_PARAMETER_F);
|
|
|
|
|
|
|
|
// FuelSchedule *fs = engine->engineConfiguration2->injectionEvents;
|
|
|
|
float tpsTo = cb.get(index);
|
|
|
|
float tpsFrom = cb.get(index - 1);
|
|
|
|
float d = tpsTo - tpsFrom;
|
|
|
|
|
2016-09-17 16:02:34 -07:00
|
|
|
float valueFromTable = tpsTpsMap.getValue(tpsFrom, tpsTo);
|
2016-03-11 08:03:18 -08:00
|
|
|
|
2016-03-12 17:03:40 -08:00
|
|
|
floatms_t extraFuel;
|
2016-03-11 11:03:23 -08:00
|
|
|
if (d > engineConfiguration->tpsAccelEnrichmentThreshold) {
|
2016-09-17 16:02:34 -07:00
|
|
|
extraFuel = valueFromTable;
|
2016-03-11 11:03:23 -08:00
|
|
|
} else if (d < -engineConfiguration->tpsDecelEnleanmentThreshold) {
|
2016-03-12 17:03:40 -08:00
|
|
|
extraFuel = d * engineConfiguration->tpsDecelEnleanmentMultiplier;
|
2016-03-11 11:03:23 -08:00
|
|
|
} else {
|
2016-03-12 17:03:40 -08:00
|
|
|
extraFuel = 0;
|
2016-03-11 11:03:23 -08:00
|
|
|
}
|
|
|
|
|
2016-03-12 17:03:40 -08:00
|
|
|
#if !EFI_UNIT_TEST || defined(__DOXYGEN__)
|
2016-03-11 08:03:18 -08:00
|
|
|
if (engineConfiguration->debugMode == DBG_TPS_ACCEL) {
|
|
|
|
tsOutputChannels.debugFloatField1 = tpsFrom;
|
|
|
|
tsOutputChannels.debugFloatField2 = tpsTo;
|
2016-09-17 16:02:34 -07:00
|
|
|
tsOutputChannels.debugFloatField3 = valueFromTable;
|
2016-03-12 17:03:40 -08:00
|
|
|
tsOutputChannels.debugFloatField4 = extraFuel;
|
2016-03-11 08:03:18 -08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-03-11 11:03:23 -08:00
|
|
|
|
2016-03-12 17:03:40 -08:00
|
|
|
return extraFuel;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2016-01-02 13:01:27 -08:00
|
|
|
float AccelEnrichmemnt::getEngineLoadEnrichment(DECLARE_ENGINE_PARAMETER_F) {
|
2016-03-12 17:03:40 -08:00
|
|
|
int index = getMaxDeltaIndex(PASS_ENGINE_PARAMETER_F);
|
|
|
|
|
|
|
|
FuelSchedule *fs = engine->engineConfiguration2->injectionEvents;
|
|
|
|
float d = (cb.get(index) - (cb.get(index - 1))) * fs->eventsCount;
|
|
|
|
|
|
|
|
float result = 0;
|
|
|
|
int distance = 0;
|
|
|
|
float taper = 0;
|
2015-12-31 10:02:19 -08:00
|
|
|
if (d > engineConfiguration->engineLoadAccelEnrichmentThreshold) {
|
2016-03-12 17:03:40 -08:00
|
|
|
|
|
|
|
int distance = cb.currentIndex - index;
|
|
|
|
if (distance <= 0) // checking if indexes are out of order due to circular buffer nature
|
|
|
|
distance += minI(cb.getCount(), cb.getSize());
|
|
|
|
|
|
|
|
taper = interpolate2d(distance, engineConfiguration->mapAccelTaperBins, engineConfiguration->mapAccelTaperMult, MAP_ACCEL_TAPER);
|
|
|
|
|
|
|
|
result = taper * d * engineConfiguration->engineLoadAccelEnrichmentMultiplier;
|
|
|
|
} else if (d < -engineConfiguration->engineLoadDecelEnleanmentThreshold) {
|
|
|
|
result = d * engineConfiguration->engineLoadAccelEnrichmentMultiplier;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
2016-03-12 17:03:40 -08:00
|
|
|
|
|
|
|
#if ! EFI_UNIT_TEST || defined(__DOXYGEN__)
|
|
|
|
if (engineConfiguration->debugMode == DBG_EL_ACCEL) {
|
|
|
|
tsOutputChannels.debugIntField1 = distance;
|
|
|
|
tsOutputChannels.debugFloatField1 = result;
|
|
|
|
tsOutputChannels.debugFloatField2 = taper;
|
|
|
|
|
2016-01-02 13:01:27 -08:00
|
|
|
}
|
2016-03-12 17:03:40 -08:00
|
|
|
#endif
|
|
|
|
return result;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void AccelEnrichmemnt::reset() {
|
2016-01-04 21:02:56 -08:00
|
|
|
cb.clear();
|
2016-01-31 10:03:08 -08:00
|
|
|
previousValue = NAN;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2016-03-09 20:02:39 -08:00
|
|
|
void AccelEnrichmemnt::setLength(int length) {
|
|
|
|
cb.setSize(length);
|
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
void AccelEnrichmemnt::onNewValue(float currentValue DECLARE_ENGINE_PARAMETER_S) {
|
2016-03-09 21:04:40 -08:00
|
|
|
cb.add(currentValue);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void AccelEnrichmemnt::onEngineCycleTps(DECLARE_ENGINE_PARAMETER_F) {
|
|
|
|
onNewValue(getTPS(PASS_ENGINE_PARAMETER_F) PASS_ENGINE_PARAMETER);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AccelEnrichmemnt::onEngineCycle(DECLARE_ENGINE_PARAMETER_F) {
|
|
|
|
onNewValue(getEngineLoadT(PASS_ENGINE_PARAMETER_F) PASS_ENGINE_PARAMETER);
|
|
|
|
}
|
|
|
|
|
|
|
|
AccelEnrichmemnt::AccelEnrichmemnt() {
|
|
|
|
reset();
|
|
|
|
cb.setSize(4);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if ! EFI_UNIT_TEST || defined(__DOXYGEN__)
|
|
|
|
|
|
|
|
static void accelInfo() {
|
2016-01-31 14:01:29 -08:00
|
|
|
if (logger == NULL)
|
|
|
|
return;
|
2015-12-31 15:02:17 -08:00
|
|
|
// scheduleMsg(logger, "EL accel length=%d", mapInstance.cb.getSize());
|
|
|
|
scheduleMsg(logger, "EL accel th=%f/mult=%f", engineConfiguration->engineLoadAccelEnrichmentThreshold, engineConfiguration->engineLoadAccelEnrichmentMultiplier);
|
|
|
|
scheduleMsg(logger, "EL decel th=%f/mult=%f", engineConfiguration->engineLoadDecelEnleanmentThreshold, engineConfiguration->engineLoadDecelEnleanmentMultiplier);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
// scheduleMsg(logger, "TPS accel length=%d", tpsInstance.cb.getSize());
|
2016-09-11 18:02:02 -07:00
|
|
|
scheduleMsg(logger, "TPS accel th=%f/mult=%f", engineConfiguration->tpsAccelEnrichmentThreshold, -1);
|
2015-08-23 22:01:28 -07:00
|
|
|
|
|
|
|
scheduleMsg(logger, "added to wall=%f/sucked=%f", engineConfiguration->addedToWallCoef, engineConfiguration->suckedOffCoef);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2015-12-31 15:02:17 -08:00
|
|
|
void setEngineLoadAccelThr(float value) {
|
2015-12-31 10:02:19 -08:00
|
|
|
engineConfiguration->engineLoadAccelEnrichmentThreshold = value;
|
2015-07-10 06:01:56 -07:00
|
|
|
accelInfo();
|
|
|
|
}
|
|
|
|
|
2015-12-31 15:02:17 -08:00
|
|
|
void setEngineLoadAccelMult(float value) {
|
2015-12-31 10:02:19 -08:00
|
|
|
engineConfiguration->engineLoadAccelEnrichmentMultiplier = value;
|
2015-07-10 06:01:56 -07:00
|
|
|
accelInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void setTpsAccelThr(float value) {
|
|
|
|
engineConfiguration->tpsAccelEnrichmentThreshold = value;
|
|
|
|
accelInfo();
|
|
|
|
}
|
|
|
|
|
2015-12-31 15:02:17 -08:00
|
|
|
static void setTpsDecelThr(float value) {
|
|
|
|
engineConfiguration->tpsDecelEnleanmentThreshold = value;
|
|
|
|
accelInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void setTpsDecelMult(float value) {
|
|
|
|
engineConfiguration->tpsDecelEnleanmentMultiplier = value;
|
|
|
|
accelInfo();
|
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
static void setDecelThr(float value) {
|
2015-12-31 15:02:17 -08:00
|
|
|
engineConfiguration->engineLoadDecelEnleanmentThreshold = value;
|
2015-07-10 06:01:56 -07:00
|
|
|
accelInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void setDecelMult(float value) {
|
2015-12-31 15:02:17 -08:00
|
|
|
engineConfiguration->engineLoadDecelEnleanmentMultiplier = value;
|
2015-07-10 06:01:56 -07:00
|
|
|
accelInfo();
|
|
|
|
}
|
|
|
|
|
2016-03-09 20:02:39 -08:00
|
|
|
static void setTpsAccelLen(int length) {
|
|
|
|
if (length < 1) {
|
2015-09-02 17:01:29 -07:00
|
|
|
scheduleMsg(logger, "Length should be positive");
|
2015-07-10 06:01:56 -07:00
|
|
|
return;
|
|
|
|
}
|
2016-03-09 20:02:39 -08:00
|
|
|
engine->tpsAccelEnrichment.setLength(length);
|
2015-07-10 06:01:56 -07:00
|
|
|
accelInfo();
|
|
|
|
}
|
|
|
|
|
2016-03-09 20:02:39 -08:00
|
|
|
void setEngineLoadAccelLen(int length) {
|
|
|
|
if (length < 1) {
|
2015-09-02 17:01:29 -07:00
|
|
|
scheduleMsg(logger, "Length should be positive");
|
2015-07-10 06:01:56 -07:00
|
|
|
return;
|
|
|
|
}
|
2016-03-09 20:02:39 -08:00
|
|
|
engine->engineLoadAccelEnrichment.setLength(length);
|
2015-07-10 06:01:56 -07:00
|
|
|
accelInfo();
|
|
|
|
}
|
|
|
|
|
2016-01-31 12:01:41 -08:00
|
|
|
void updateAccelParameters() {
|
|
|
|
setEngineLoadAccelLen(engineConfiguration->engineLoadAccelLength);
|
|
|
|
setTpsAccelLen(engineConfiguration->tpsAccelLength);
|
|
|
|
}
|
|
|
|
|
2016-03-11 08:03:18 -08:00
|
|
|
#endif /* ! EFI_UNIT_TEST */
|
|
|
|
|
|
|
|
|
|
|
|
void initAccelEnrichment(Logging *sharedLogger DECLARE_ENGINE_PARAMETER_S) {
|
2015-07-10 06:01:56 -07:00
|
|
|
logger = sharedLogger;
|
2016-03-11 08:03:18 -08:00
|
|
|
tpsTpsMap.init(config->tpsTpsAccelTable, config->tpsTpsAccelFromRpmBins, config->tpsTpsAccelToRpmBins);
|
|
|
|
|
|
|
|
#if ! EFI_UNIT_TEST || defined(__DOXYGEN__)
|
2015-07-10 06:01:56 -07:00
|
|
|
addConsoleActionI("set_tps_accel_len", setTpsAccelLen);
|
|
|
|
addConsoleActionF("set_tps_accel_threshold", setTpsAccelThr);
|
2016-09-11 18:02:02 -07:00
|
|
|
//addConsoleActionF("set_tps_accel_multiplier", setTpsAccelMult);
|
2015-12-31 15:02:17 -08:00
|
|
|
addConsoleActionF("set_tps_decel_threshold", setTpsDecelThr);
|
|
|
|
addConsoleActionF("set_tps_decel_multiplier", setTpsDecelMult);
|
|
|
|
|
|
|
|
addConsoleActionI("set_engine_load_accel_len", setEngineLoadAccelLen);
|
|
|
|
addConsoleActionF("set_engine_load_accel_threshold", setEngineLoadAccelThr);
|
|
|
|
addConsoleActionF("set_engine_load_accel_multiplier", setEngineLoadAccelMult);
|
|
|
|
addConsoleActionF("set_engine_decel_threshold", setDecelThr);
|
|
|
|
addConsoleActionF("set_engine_decel_multiplier", setDecelMult);
|
2015-07-10 06:01:56 -07:00
|
|
|
addConsoleAction("accelinfo", accelInfo);
|
|
|
|
|
2016-01-31 12:01:41 -08:00
|
|
|
updateAccelParameters();
|
2015-07-10 06:01:56 -07:00
|
|
|
#endif /* ! EFI_UNIT_TEST */
|
2016-03-11 08:03:18 -08:00
|
|
|
}
|
|
|
|
|