Merge pull request #1686 from mck1117/ys-1b

Refactor fuel math in to FuelComputer
This commit is contained in:
rusefillc 2020-08-12 22:55:34 -04:00 committed by GitHub
commit 2dd3beb9bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 117 additions and 45 deletions

View File

@ -290,7 +290,6 @@ static void showFuelInfo2(float rpm, float engineLoad) {
float magicAir = SpeedDensityBase::getAirmassImpl(1, 100, convertCelsiusToKelvin(20) PASS_ENGINE_PARAMETER_SUFFIX);
scheduleMsg(&logger, "SD magic fuel %.2f", getInjectionDurationForAirmass(magicAir, 14.7 PASS_ENGINE_PARAMETER_SUFFIX));
scheduleMsg(&logger, "inj flow %.2fcc/min displacement %.2fL", engineConfiguration->injector.flow,
engineConfiguration->specs.displacement);

View File

@ -16,3 +16,4 @@ CONTROLLERS_ALGO_SRC_CPP = $(PROJECT_DIR)/controllers/algo/advance_map.cpp \
$(PROJECT_DIR)/controllers/algo/airmass/maf_airmass.cpp \
$(PROJECT_DIR)/controllers/algo/airmass/speed_density_airmass.cpp \
$(PROJECT_DIR)/controllers/algo/airmass/speed_density_base.cpp \
$(PROJECT_DIR)/controllers/algo/fuel/fuel_computer.cpp \

View File

@ -0,0 +1,27 @@
#include "fuel_computer.h"
EXTERN_ENGINE;
mass_t FuelComputerBase::getCycleFuel(mass_t airmass, int rpm, float load) const {
float stoich = getStoichiometricRatio();
float lambda = getTargetLambda(rpm, load);
float afr = stoich * lambda;
ENGINE(engineState.targetAFR) = afr;
return airmass / afr;
}
FuelComputer::FuelComputer(const ValueProvider3D& afrTable) : m_afrTable(&afrTable) {}
float FuelComputer::getStoichiometricRatio() const {
// TODO: vary this with ethanol content/configured setting/whatever
return 14.7f;
}
float FuelComputer::getTargetLambda(int rpm, float load) const {
efiAssert(OBD_PCM_Processor_Fault, m_afrTable != nullptr, "AFR table null", 0);
// TODO: set the table value in lambda instead of afr
return m_afrTable->getValue(rpm, load) / getStoichiometricRatio();
};

View File

@ -0,0 +1,36 @@
#pragma once
#include "engine.h"
class ValueProvider3D;
using mass_t = float;
struct IFuelComputer {
virtual mass_t getCycleFuel(mass_t airmass, int rpm, float load) const = 0;
};
// This contains the math of the fuel model, but doesn't actually read any configuration
class FuelComputerBase : public IFuelComputer {
public:
DECLARE_ENGINE_PTR;
mass_t getCycleFuel(mass_t airmass, int rpm, float load) const override;
protected:
virtual float getStoichiometricRatio() const = 0;
virtual float getTargetLambda(int rpm, float load) const = 0;
};
// This class is a usable implemenation of a fuel model that reads real configuration
class FuelComputer final : public FuelComputerBase {
public:
FuelComputer(const ValueProvider3D& afrTable);
protected:
float getStoichiometricRatio() const override;
float getTargetLambda(int rpm, float load) const override;
private:
const ValueProvider3D* const m_afrTable;
};

View File

@ -27,6 +27,7 @@
#include "maf_airmass.h"
#include "speed_density_airmass.h"
#include "fuel_math.h"
#include "fuel_computer.h"
#include "interpolation.h"
#include "engine_configuration.h"
#include "allsensors.h"
@ -163,10 +164,10 @@ constexpr float convertToGramsPerSecond(float ccPerMinute) {
/**
* @return per cylinder injection time, in seconds
*/
float getInjectionDurationForAirmass(float airMass, float afr DECLARE_ENGINE_PARAMETER_SUFFIX) {
static float getInjectionDurationForFuelMass(float fuelMass DECLARE_ENGINE_PARAMETER_SUFFIX) {
float gPerSec = convertToGramsPerSecond(CONFIG(injector.flow));
return airMass / (afr * gPerSec);
return fuelMass / gPerSec;
}
static SpeedDensityAirmass sdAirmass(veMap);
@ -185,6 +186,8 @@ AirmassModelBase* getAirmassModel(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
}
}
static FuelComputer fuelComputer(afrMap);
/**
* per-cylinder fuel amount
* todo: rename this method since it's now base+TPSaccel
@ -202,17 +205,14 @@ floatms_t getBaseFuel(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX) {
auto airmass = model->getAirmass(rpm);
// The airmass mode will tell us how to look up AFR - use the provided Y axis value
float targetAfr = afrMap.getValue(rpm, airmass.EngineLoadPercent);
// Plop some state for others to read
ENGINE(engineState.targetAFR) = targetAfr;
ENGINE(engineState.sd.airMassInOneCylinder) = airmass.CylinderAirmass;
ENGINE(engineState.fuelingLoad) = airmass.EngineLoadPercent;
// TODO: independently selectable ignition load mode
ENGINE(engineState.ignitionLoad) = airmass.EngineLoadPercent;
float baseFuel = getInjectionDurationForAirmass(airmass.CylinderAirmass, targetAfr PASS_ENGINE_PARAMETER_SUFFIX) * 1000;
float baseFuelMass = fuelComputer.getCycleFuel(airmass.CylinderAirmass, rpm, airmass.EngineLoadPercent);
float baseFuel = getInjectionDurationForFuelMass(baseFuelMass PASS_ENGINE_PARAMETER_SUFFIX) * 1000;
efiAssert(CUSTOM_ERR_ASSERT, !cisnan(baseFuel), "NaN baseFuel", 0);
engine->engineState.baseFuel = baseFuel;
@ -345,6 +345,8 @@ floatms_t getInjectorLag(float vBatt DECLARE_ENGINE_PARAMETER_SUFFIX) {
void initFuelMap(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
INJECT_ENGINE_REFERENCE(&sdAirmass);
INJECT_ENGINE_REFERENCE(&mafAirmass);
INJECT_ENGINE_REFERENCE(&alphaNAirmass);
INJECT_ENGINE_REFERENCE(&fuelComputer);
#if (IGN_LOAD_COUNT == FUEL_LOAD_COUNT) && (IGN_RPM_COUNT == FUEL_RPM_COUNT)
fuelPhaseMap.init(config->injectionPhase, config->injPhaseLoadBins, config->injPhaseRpmBins);

View File

@ -39,4 +39,3 @@ float getStandardAirCharge(DECLARE_ENGINE_PARAMETER_SIGNATURE);
// convert injection duration (Ms/Nt) to fuel rate (L/h)
float getFuelRate(floatms_t totalInjDuration, efitick_t timePeriod DECLARE_ENGINE_PARAMETER_SUFFIX);
float getInjectionDurationForAirmass(float airMass, float afr DECLARE_ENGINE_PARAMETER_SUFFIX);

View File

@ -56,6 +56,7 @@ CONTROLLERS_INC=\
$(CONTROLLERS_DIR)/system/timer \
$(CONTROLLERS_DIR)/algo \
$(CONTROLLERS_DIR)/algo/airmass \
$(CONTROLLERS_DIR)/algo/fuel \
$(CONTROLLERS_DIR)/engine_cycle \
$(CONTROLLERS_DIR)/trigger/decoders \
$(CONTROLLERS_DIR)/trigger \

View File

@ -0,0 +1,41 @@
#include "engine_test_helper.h"
// sneaky...
#define protected public
#include "fuel_computer.h"
#include "mocks.h"
#include "gtest/gtest.h"
using ::testing::FloatEq;
class MockFuelComputer : public FuelComputerBase {
public:
MOCK_METHOD(float, getStoichiometricRatio, (), (const, override));
MOCK_METHOD(float, getTargetLambda, (int rpm, float load), (const, override));
};
TEST(FuelComputer, getCycleFuel) {
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
MockFuelComputer dut;
INJECT_ENGINE_REFERENCE(&dut);
EXPECT_CALL(dut, getStoichiometricRatio())
.WillOnce(Return(3.0f));
EXPECT_CALL(dut, getTargetLambda(1000, FloatEq(0.8f)))
.WillOnce(Return(5.0f));
auto result = dut.getCycleFuel(7.0f, 1000, 0.8f);
EXPECT_FLOAT_EQ(result, 7.0f / (5 * 3));
}
TEST(FuelComputer, LambdaLookup) {
MockVp3d afrTable;
FuelComputer dut(afrTable);
EXPECT_CALL(afrTable, getValue(1500, FloatEq(0.7f)))
.WillOnce(Return(14.7f));
EXPECT_FLOAT_EQ(dut.getTargetLambda(1500, 0.7f), 1.0f);
}

View File

@ -78,7 +78,7 @@ TEST(AirmassModes, AlphaNFailedTps) {
EXPECT_EQ(result.CylinderAirmass, 0);
}
TEST(misc, MafNormal) {
TEST(AirmassModes, MafNormal) {
WITH_ENGINE_TEST_HELPER(FORD_ASPIRE_1996);
engineConfiguration->fuelAlgorithm = LM_REAL_MAF;
engineConfiguration->injector.flow = 200;

View File

@ -1,34 +0,0 @@
/**
* @file test_speed_density.cpp
*
* @date Jun 26, 2014
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#include "engine_test_helper.h"
#include "speed_density.h"
#include "fuel_math.h"
TEST(big, testSpeedDensity) {
printf("*************************************************** testSpeedDensity\r\n");
WITH_ENGINE_TEST_HELPER(FORD_INLINE_6_1995);
engineConfiguration->trigger.customTotalToothCount = 8;
eth.applyTriggerWaveform();
eth.fireTriggerEvents(36);
ASSERT_EQ( 1500, GET_RPM()) << "RPM";
// 427 cubic inches, that's a LOT of engine
engineConfiguration->specs.displacement = 6.99728;
engineConfiguration->specs.cylindersCount = 8;
engineConfiguration->injector.flow = gramm_second_to_cc_minute(5.303);
float airMass = SpeedDensityBase::getAirmassImpl(0.92, 98, 293.16 PASS_ENGINE_PARAMETER_SUFFIX);
ASSERT_FLOAT_EQ(0.9371106624, airMass);
// 0.01414 sec or 14.14 ms
EXPECT_NEAR(0.014137, getInjectionDurationForAirmass(airMass, 12.5 PASS_ENGINE_PARAMETER_SUFFIX), EPS4D);
}

View File

@ -12,6 +12,7 @@ TESTS_SRC_CPP = \
tests/ignition_injection/test_multispark.cpp \
tests/ignition_injection/test_ignition_scheduling.cpp \
tests/ignition_injection/test_fuelCut.cpp \
tests/ignition_injection/test_fuel_computer.cpp \
tests/test_util.cpp \
tests/test_ion.cpp \
tests/test_aux_valves.cpp \
@ -29,7 +30,6 @@ TESTS_SRC_CPP = \
tests/test_one_cylinder_logic.cpp \
tests/test_pwm_generator.cpp \
tests/test_logic_expression.cpp \
tests/test_speed_density.cpp \
tests/test_signal_executor.cpp \
tests/test_cpp_memory_layout.cpp \
tests/test_sensors.cpp \