extract logic from wall wetting AE (#3848)
* extract logic * extract interface * explicitly test wall fuel
This commit is contained in:
parent
bd980e8203
commit
eb14d74846
|
@ -184,6 +184,7 @@ public:
|
|||
AcController,
|
||||
PrimeController,
|
||||
DfcoController,
|
||||
Mockable<WallFuelController>,
|
||||
EngineModule // dummy placeholder so the previous entries can all have commas
|
||||
> engineModules;
|
||||
|
||||
|
|
|
@ -17,11 +17,6 @@ float WallFuel::adjust(float desiredMassGrams) {
|
|||
return desiredMassGrams;
|
||||
}
|
||||
|
||||
// disable this correction for cranking
|
||||
if (engine->rpmCalculator.isCranking()) {
|
||||
return desiredMassGrams;
|
||||
}
|
||||
|
||||
ScopePerf perf(PE::WallFuelAdjust);
|
||||
|
||||
/*
|
||||
|
@ -46,49 +41,15 @@ float WallFuel::adjust(float desiredMassGrams) {
|
|||
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 or beta is really small, we get div/0.
|
||||
// you probably meant to disable wwae.
|
||||
float tau = engineConfiguration->wwaeTau;
|
||||
float beta = engineConfiguration->wwaeBeta;
|
||||
|
||||
if (tau < 0.01f || beta < 0.01f) {
|
||||
// If disabled, pass value through
|
||||
if (!engine->module<WallFuelController>()->getEnable()) {
|
||||
return desiredMassGrams;
|
||||
}
|
||||
|
||||
// Ignore really slow RPM
|
||||
int rpm = Sensor::getOrZero(SensorType::Rpm);
|
||||
if (rpm < 100) {
|
||||
return desiredMassGrams;
|
||||
}
|
||||
|
||||
float alpha = expf_taylor(-120 / (rpm * tau));
|
||||
|
||||
#if EFI_TUNER_STUDIO
|
||||
if (engineConfiguration->debugMode == DBG_KNOCK) {
|
||||
engine->outputChannels.debugFloatField1 = alpha;
|
||||
engine->outputChannels.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 alpha = engine->module<WallFuelController>()->getAlpha();
|
||||
float beta = engine->module<WallFuelController>()->getBeta();
|
||||
|
||||
float fuelFilmMass = wallFuel;
|
||||
float M_cmd = (desiredMassGrams - (1 - alpha) * fuelFilmMass) / (1 - beta);
|
||||
|
@ -124,3 +85,72 @@ float WallFuel::adjust(float desiredMassGrams) {
|
|||
float WallFuel::getWallFuel() const {
|
||||
return wallFuel;
|
||||
}
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
float WallFuelController::computeTau() const {
|
||||
return engineConfiguration->wwaeTau;
|
||||
}
|
||||
|
||||
float WallFuelController::computeBeta() const {
|
||||
return engineConfiguration->wwaeBeta;
|
||||
}
|
||||
|
||||
void WallFuelController::onFastCallback() {
|
||||
// disable wall wetting cranking
|
||||
// TODO: is this correct? Why not correct for cranking?
|
||||
if (engine->rpmCalculator.isCranking()) {
|
||||
m_enable = false;
|
||||
return;
|
||||
}
|
||||
|
||||
float tau = computeTau();
|
||||
float beta = computeBeta();
|
||||
|
||||
// if tau or beta is really small, we get div/0.
|
||||
// you probably meant to disable wwae.
|
||||
if (tau < 0.01f || beta < 0.01f) {
|
||||
m_enable = false;
|
||||
return;
|
||||
}
|
||||
|
||||
auto rpm = Sensor::getOrZero(SensorType::Rpm);
|
||||
|
||||
// Ignore low RPM
|
||||
if (rpm < 100) {
|
||||
m_enable = false;
|
||||
return;
|
||||
}
|
||||
|
||||
float alpha = expf_taylor(-120 / (rpm * tau));
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Store parameters so the model can read them
|
||||
m_alpha = alpha;
|
||||
m_beta = beta;
|
||||
m_enable = true;
|
||||
|
||||
#if EFI_TUNER_STUDIO
|
||||
// TODO: why DBG_KNOCK? That seems wrong.
|
||||
if (engineConfiguration->debugMode == DBG_KNOCK) {
|
||||
engine->outputChannels.debugFloatField1 = alpha;
|
||||
engine->outputChannels.debugFloatField2 = beta;
|
||||
}
|
||||
#endif // EFI_TUNER_STUDIO
|
||||
}
|
||||
|
|
|
@ -20,3 +20,37 @@ public:
|
|||
void resetWF();
|
||||
int invocationCounter = 0;
|
||||
};
|
||||
|
||||
struct IWallFuelController {
|
||||
virtual bool getEnable() const = 0;
|
||||
virtual float getAlpha() const = 0;
|
||||
virtual float getBeta() const = 0;
|
||||
};
|
||||
|
||||
class WallFuelController : public IWallFuelController, public EngineModule {
|
||||
public:
|
||||
using interface_t = IWallFuelController;
|
||||
|
||||
void onFastCallback() override;
|
||||
|
||||
bool getEnable() const override {
|
||||
return m_enable;
|
||||
}
|
||||
|
||||
float getAlpha() const override {
|
||||
return m_alpha;
|
||||
}
|
||||
|
||||
float getBeta() const override {
|
||||
return m_beta;
|
||||
}
|
||||
|
||||
protected:
|
||||
float computeTau() const;
|
||||
float computeBeta() const;
|
||||
|
||||
private:
|
||||
bool m_enable = false;
|
||||
float m_alpha = 0;
|
||||
float m_beta = 0;
|
||||
};
|
||||
|
|
|
@ -9,19 +9,55 @@
|
|||
|
||||
#include "pch.h"
|
||||
|
||||
struct MockWallController : public IWallFuelController {
|
||||
MOCK_METHOD(bool, getEnable, (), (const, override));
|
||||
MOCK_METHOD(float, getAlpha, (), (const, override));
|
||||
MOCK_METHOD(float, getBeta, (), (const, override));
|
||||
};
|
||||
|
||||
TEST(fuel, testWallWettingEnrichmentMath) {
|
||||
EngineTestHelper eth(FORD_ASPIRE_1996);
|
||||
|
||||
engineConfiguration->wwaeTau = 1.0f;
|
||||
engineConfiguration->wwaeBeta = 0.40f;
|
||||
MockWallController wallController;
|
||||
|
||||
engine->rpmCalculator.setRpmValue(3000);
|
||||
// WW is enabled!
|
||||
EXPECT_CALL(wallController, getEnable()).WillRepeatedly(Return(true));
|
||||
|
||||
// 1/2 of fuel remains on walls
|
||||
EXPECT_CALL(wallController, getAlpha()).WillRepeatedly(Return(0.5f));
|
||||
|
||||
// 1/4 of fuel is lands on walls
|
||||
EXPECT_CALL(wallController, getBeta()).WillRepeatedly(Return(0.25f));
|
||||
|
||||
// install our mock in to the engine
|
||||
engine->engineModules.get<WallFuelController>().set(&wallController);
|
||||
|
||||
WallFuel wallFuel;
|
||||
|
||||
// each invocation of 'adjust' changes WallWetting internal state
|
||||
ASSERT_NEAR(16.6666, wallFuel.adjust(10.0), EPS4D);
|
||||
ASSERT_NEAR(16.198, wallFuel.adjust(10.0), EPS4D);
|
||||
EXPECT_NEAR(1.3333, wallFuel.adjust(1), EPS4D);
|
||||
EXPECT_NEAR(1.1111, wallFuel.adjust(1), EPS4D);
|
||||
EXPECT_NEAR(1.0370, wallFuel.adjust(1), EPS4D);
|
||||
EXPECT_NEAR(1.0123, wallFuel.adjust(1), EPS4D);
|
||||
|
||||
// get to steady state
|
||||
for (size_t i = 0; i < 50; i++) {
|
||||
wallFuel.adjust(1);
|
||||
}
|
||||
|
||||
EXPECT_NEAR(1, wallFuel.adjust(1), EPS4D);
|
||||
|
||||
// now run half the fuel
|
||||
EXPECT_NEAR(0.3333, wallFuel.adjust(0.5), EPS4D);
|
||||
EXPECT_NEAR(0.4444, wallFuel.adjust(0.5), EPS4D);
|
||||
EXPECT_NEAR(0.4815, wallFuel.adjust(0.5), EPS4D);
|
||||
EXPECT_NEAR(0.4938, wallFuel.adjust(0.5), EPS4D);
|
||||
|
||||
for (size_t i = 0; i < 50; i++) {
|
||||
wallFuel.adjust(0.5);
|
||||
}
|
||||
|
||||
EXPECT_NEAR(0.5, wallFuel.adjust(0.5), EPS4D);
|
||||
}
|
||||
|
||||
TEST(fuel, testWallWettingEnrichmentScheduling) {
|
||||
|
|
Loading…
Reference in New Issue