Skip to content

Commit

Permalink
Tps-accel. fractional mode (#715)
Browse files Browse the repository at this point in the history
* Add new config settings for tps_accel_fractional_mode

* Add new variables for the fractional algo

* Add resetFractionValues() method

* Call onEngineCycleTps() and fix onEngineCycle()

* Implement the fractional algo

* More debug outputs for tps-enrich

* Nice & juicy unit-test!
  • Loading branch information
andreika-git authored and rusefi committed Mar 29, 2019
1 parent c34d7ca commit 4b5ed3e
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 4 deletions.
62 changes: 61 additions & 1 deletion firmware/controllers/algo/accel_enrichment.cpp
Expand Up @@ -190,12 +190,38 @@ floatms_t AccelEnrichmemnt::getTpsEnrichment(DECLARE_ENGINE_PARAMETER_SIGNATURE)
extraFuel = 0;
}

// Fractional enrichment (fuel portions are accumulated and split between several engine cycles.
// This is a crude imitation of carburetor's acceleration pump.
if (CONFIG(tpsAccelFractionPeriod) > 1 || CONFIG(tpsAccelFractionDivisor) > 1.0f) {
// make sure both values are non-zero
float periodF = (float)maxI(CONFIG(tpsAccelFractionPeriod), 1);
float divisor = maxF(CONFIG(tpsAccelFractionDivisor), 1.0f);

// if current extra fuel portion is not "strong" enough, then we keep up the "pump pressure" with the accumulated portion
floatms_t maxExtraFuel = maxF(extraFuel, accumulatedValue);
// use only a fixed fraction of the accumulated portion
floatms_t injFuel = maxExtraFuel / divisor;

// update max counters
maxExtraPerCycle = maxF(extraFuel, maxExtraPerCycle);
maxInjectedPerPeriod = maxF(injFuel, maxInjectedPerPeriod);

// evenly split it between several engine cycles
extraFuel = injFuel / periodF;
} else {
resetFractionValues();
}

if (engineConfiguration->debugMode == DBG_TPS_ACCEL) {
#if EFI_TUNER_STUDIO || defined(__DOXYGEN__)
tsOutputChannels.debugFloatField1 = tpsFrom;
tsOutputChannels.debugFloatField2 = tpsTo;
tsOutputChannels.debugFloatField3 = valueFromTable;
tsOutputChannels.debugFloatField4 = extraFuel;
tsOutputChannels.debugFloatField5 = accumulatedValue;
tsOutputChannels.debugFloatField6 = maxExtraPerPeriod;
tsOutputChannels.debugFloatField7 = maxInjectedPerPeriod;
tsOutputChannels.debugIntField1 = cycleCnt;
#endif /* EFI_TUNER_STUDIO */
}

Expand Down Expand Up @@ -236,6 +262,15 @@ float AccelEnrichmemnt::getEngineLoadEnrichment(DECLARE_ENGINE_PARAMETER_SIGNATU
void AccelEnrichmemnt::reset() {
cb.clear();
previousValue = NAN;
resetFractionValues();
}

void AccelEnrichmemnt::resetFractionValues() {
accumulatedValue = 0;
maxExtraPerCycle = 0;
maxExtraPerPeriod = 0;
maxInjectedPerPeriod = 0;
cycleCnt = 0;
}

void AccelEnrichmemnt::setLength(int length) {
Expand All @@ -247,7 +282,32 @@ void AccelEnrichmemnt::onNewValue(float currentValue DECLARE_ENGINE_PARAMETER_SU
}

void AccelEnrichmemnt::onEngineCycleTps(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
onNewValue(getTPS(PASS_ENGINE_PARAMETER_SIGNATURE) PASS_ENGINE_PARAMETER_SUFFIX);
// we update values in handleFuel() directly
//onNewValue(getTPS(PASS_ENGINE_PARAMETER_SIGNATURE) PASS_ENGINE_PARAMETER_SUFFIX);

// we used some extra fuel during the current cycle, so we "charge" our "acceleration pump" with it
accumulatedValue -= maxExtraPerPeriod;
maxExtraPerPeriod = maxF(maxExtraPerCycle, maxExtraPerPeriod);
maxExtraPerCycle = 0;
accumulatedValue += maxExtraPerPeriod;

// update the accumulated value every 'Period' engine cycles
if (--cycleCnt <= 0) {
maxExtraPerPeriod = 0;

// we've injected this portion during the cycle, so we set what's left for the next cycle
accumulatedValue -= maxInjectedPerPeriod;
maxInjectedPerPeriod = 0;

// it's an infinitely convergent series, so we set a limit at some point
// (also make sure that accumulatedValue is positive, for safety)
static const floatms_t smallEpsilon = 0.001f;
if (accumulatedValue < smallEpsilon)
accumulatedValue = 0;

// reset the counter
cycleCnt = CONFIG(tpsAccelFractionPeriod);
}
}

void AccelEnrichmemnt::onEngineCycle(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
Expand Down
9 changes: 9 additions & 0 deletions firmware/controllers/algo/accel_enrichment.h
Expand Up @@ -36,12 +36,21 @@ class AccelEnrichmemnt {
void onEngineCycle(DECLARE_ENGINE_PARAMETER_SIGNATURE);
void onEngineCycleTps(DECLARE_ENGINE_PARAMETER_SIGNATURE);
void reset();
void resetFractionValues();
void setLength(int length);
cyclic_buffer<float> cb;
void onNewValue(float currentValue DECLARE_ENGINE_PARAMETER_SUFFIX);

private:
float previousValue;
/**
* Used for Fractional TPS enrichment.
*/
floatms_t accumulatedValue;
floatms_t maxExtraPerCycle;
floatms_t maxExtraPerPeriod;
floatms_t maxInjectedPerPeriod;
int cycleCnt;
};

/**
Expand Down
5 changes: 4 additions & 1 deletion firmware/controllers/trigger/main_trigger_callback.cpp
Expand Up @@ -391,7 +391,10 @@ static ALWAYS_INLINE void handleFuel(const bool limitedFuel, uint32_t trgEventIn
#endif /* FUEL_MATH_EXTREME_LOGGING */

ENGINE(tpsAccelEnrichment.onNewValue(getTPS(PASS_ENGINE_PARAMETER_SIGNATURE) PASS_ENGINE_PARAMETER_SUFFIX));
ENGINE(engineLoadAccelEnrichment.onEngineCycle(PASS_ENGINE_PARAMETER_SIGNATURE));
if (trgEventIndex == 0) {
ENGINE(tpsAccelEnrichment.onEngineCycleTps(PASS_ENGINE_PARAMETER_SIGNATURE));
ENGINE(engineLoadAccelEnrichment.onEngineCycle(PASS_ENGINE_PARAMETER_SIGNATURE));
}

/**
* we have same assignment of 'getInjectionDuration' to 'injectionDuration' in periodicFastCallback()
Expand Down
7 changes: 5 additions & 2 deletions firmware/integration/rusefi_config.txt
Expand Up @@ -991,10 +991,13 @@ tChargeMode_e tChargeMode;
int16_t idleTimingPidWorkZone;The timing correction works only if RPM is close enough, otherwise the IAC correction works;"RPM", 1, 0, 0, 1000, 0
int16_t idleTimingPidDeadZone;If RPM is too perfect, let's leave the advance angle alone to avoid oscillation;"RPM", 1, 0, 0, 1000, 0
int16_t idlePidFalloffDeltaRpm;Added to the work zone for smooth correction falloff;"RPM", 1, 0, 0, 1000, 0
int16_t unusedIdleTimingPid;

int16_t tpsAccelFractionPeriod;+A delay in cycles between fuel-enrich. portions;"cycles", 1, 0, 0, 500, 0
float tpsAccelFractionDivisor;+A fraction divisor: 1 or less = entire portion at once, or split into diminishing fractions;"coef", 1, 0, 0, 100, 2

spi_device_e tle8888spiDevice;

int[614] mainUnusedEnd;
int[613] mainUnusedEnd;


end_struct
Expand Down
3 changes: 3 additions & 0 deletions firmware/tunerstudio/rusefi.input
Expand Up @@ -2160,6 +2160,9 @@ cmd_set_engine_type_default = "w\x00\x31\x00\x00"
field = "Accel Threshold", tpsAccelEnrichmentThreshold
field = "Decel Threshold", tpsDecelEnleanmentThreshold
; field = "Decel Multiplier", tpsDecelEnleanmentMultiplier
field = "#Accelerator Pump model:"
field = "Fraction Period", tpsAccelFractionPeriod
field = "Fraction Divisor", tpsAccelFractionDivisor

dialog = WallWettingAccelPanel, "Wall Wetting (alpha version)"
field = "evaporation time constant", wwaeTau
Expand Down
66 changes: 66 additions & 0 deletions unit_tests/tests/test_accel_enrichment.cpp
Expand Up @@ -37,3 +37,69 @@ TEST(big, testAccelEnrichment) {
engine->tpsAccelEnrichment.onNewValue(0 PASS_ENGINE_PARAMETER_SUFFIX);
ASSERT_EQ( 0, engine->tpsAccelEnrichment.getMaxDelta(PASS_ENGINE_PARAMETER_SIGNATURE)) << "maxDelta";
}

static void doFractionalTpsIteration(int period, int divisor, int numCycles, std::vector<floatms_t> &tpsEnrich DECLARE_ENGINE_PARAMETER_SUFFIX) {
// every cycle
engineConfiguration->tpsAccelFractionPeriod = period;
// split into 2 portions
engineConfiguration->tpsAccelFractionDivisor = divisor;

engine->tpsAccelEnrichment.reset();
engine->tpsAccelEnrichment.onNewValue(0 PASS_ENGINE_PARAMETER_SUFFIX);
for (int i = 0; i < numCycles; i++) {
engine->tpsAccelEnrichment.onNewValue(10 PASS_ENGINE_PARAMETER_SUFFIX);
engine->tpsAccelEnrichment.onEngineCycleTps(PASS_ENGINE_PARAMETER_SIGNATURE);
tpsEnrich[i] = engine->tpsAccelEnrichment.getTpsEnrichment(PASS_ENGINE_PARAMETER_SIGNATURE);
}
}

TEST(big, testAccelEnrichmentFractionalTps) {
printf("====================================================================================== testAccelEnrichmentFractionalTps\r\n");

WITH_ENGINE_TEST_HELPER(FORD_ASPIRE_1996);

// setup
engineConfiguration->tpsAccelEnrichmentThreshold = 5;

// fill tps2tps map (todo: there should be a better way?)
static const float tpsTpsConst = 1.0f;
for (int loadIndex = 0; loadIndex < TPS_TPS_ACCEL_TABLE; loadIndex++) {
for (int rpmIndex = 0; rpmIndex < TPS_TPS_ACCEL_TABLE; rpmIndex++) {
config->tpsTpsAccelTable[loadIndex][rpmIndex] = tpsTpsConst;
}
}

Logging logger;
initAccelEnrichment(&logger PASS_ENGINE_PARAMETER_SUFFIX);

engine->rpmCalculator.setRpmValue(600 PASS_ENGINE_PARAMETER_SUFFIX);
engine->periodicFastCallback(PASS_ENGINE_PARAMETER_SIGNATURE);

engine->tpsAccelEnrichment.setLength(2);


const int numCycles = 4;
std::vector<floatms_t> tpsEnrich(numCycles);

// first, test the default behavior without fractional division
doFractionalTpsIteration(1, 1, numCycles, tpsEnrich PASS_ENGINE_PARAMETER_SUFFIX);
// the portion for the first cycle is full-enriched and there's no enrichment for next cycles
EXPECT_THAT(tpsEnrich, testing::ElementsAre(1.0f, 0.0f, 0.0f, 0.0f)) << "fractionalTps#1";

// divide into 2 each cycle
doFractionalTpsIteration(1, 2, numCycles, tpsEnrich PASS_ENGINE_PARAMETER_SUFFIX);
// we have half-portion for the first cycle, then 1/4-th and 1/8th and so on...
EXPECT_THAT(tpsEnrich, testing::ElementsAre(0.5f, 0.25f, 0.125f, 0.0625f)) << "fractionalTps#2";

// split every portion into 3 sub-portions (so the whole enrichment takes longer)
doFractionalTpsIteration(3, 1, numCycles, tpsEnrich PASS_ENGINE_PARAMETER_SUFFIX);
// we have 1/3rd-portion for the first three cycles
const float th = (1.0f / 3.0f);
EXPECT_THAT(tpsEnrich, testing::ElementsAre(testing::FloatEq(th), testing::FloatEq(th), testing::FloatEq(th), 0.0f)) << "fractionalTps#3";

// split every divided portion into 2 sub-portions (so the whole enrichment takes longer)
doFractionalTpsIteration(2, 2, numCycles, tpsEnrich PASS_ENGINE_PARAMETER_SUFFIX);
// we have half-portion for the first two cycles, and 1/4-th portion for the next 2 cycles, and so on...
EXPECT_THAT(tpsEnrich, testing::ElementsAre(0.25f, 0.25f, 0.125f, 0.125f)) << "fractionalTps#4";

}

0 comments on commit 4b5ed3e

Please sign in to comment.