Add injector model class (#1687)
* stub injector model * tests Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
parent
42e77da8ff
commit
5929164fb3
|
@ -17,3 +17,4 @@ CONTROLLERS_ALGO_SRC_CPP = $(PROJECT_DIR)/controllers/algo/advance_map.cpp \
|
||||||
$(PROJECT_DIR)/controllers/algo/airmass/speed_density_airmass.cpp \
|
$(PROJECT_DIR)/controllers/algo/airmass/speed_density_airmass.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 \
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
#include "injector_model.h"
|
||||||
|
|
||||||
|
EXTERN_ENGINE;
|
||||||
|
|
||||||
|
void InjectorModelBase::prepare() {
|
||||||
|
m_massFlowRate = getInjectorMassFlowRate();
|
||||||
|
m_deadtime = getDeadtime();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr float convertToGramsPerSecond(float ccPerMinute) {
|
||||||
|
float ccPerSecond = ccPerMinute / 60;
|
||||||
|
return ccPerSecond * 0.72f; // 0.72g/cc fuel density
|
||||||
|
}
|
||||||
|
|
||||||
|
float InjectorModel::getInjectorMassFlowRate() const {
|
||||||
|
// TODO: injector flow dependent upon rail pressure (and temperature/ethanol content?)
|
||||||
|
auto injectorVolumeFlow = CONFIG(injector.flow);
|
||||||
|
return convertToGramsPerSecond(injectorVolumeFlow);
|
||||||
|
}
|
||||||
|
|
||||||
|
float InjectorModel::getDeadtime() const {
|
||||||
|
return interpolate2d(
|
||||||
|
"lag",
|
||||||
|
ENGINE(sensors.vBatt),
|
||||||
|
engineConfiguration->injector.battLagCorrBins,
|
||||||
|
engineConfiguration->injector.battLagCorr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
float InjectorModelBase::getInjectionDuration(float fuelMassGram) const {
|
||||||
|
// TODO: support injector nonlinearity correction
|
||||||
|
|
||||||
|
floatms_t baseDuration = fuelMassGram / m_massFlowRate * 1000;
|
||||||
|
return baseDuration + m_deadtime;
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "engine.h"
|
||||||
|
|
||||||
|
class InjectorModelBase {
|
||||||
|
public:
|
||||||
|
void prepare();
|
||||||
|
floatms_t getInjectionDuration(float fuelMassGram) const;
|
||||||
|
|
||||||
|
virtual floatms_t getDeadtime() const = 0;
|
||||||
|
virtual float getInjectorMassFlowRate() const = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
float m_deadtime = 0;
|
||||||
|
float m_massFlowRate = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class InjectorModel : public InjectorModelBase {
|
||||||
|
public:
|
||||||
|
DECLARE_ENGINE_PTR;
|
||||||
|
|
||||||
|
floatms_t getDeadtime() const override;
|
||||||
|
float getInjectorMassFlowRate() const override;
|
||||||
|
};
|
|
@ -28,6 +28,7 @@
|
||||||
#include "speed_density_airmass.h"
|
#include "speed_density_airmass.h"
|
||||||
#include "fuel_math.h"
|
#include "fuel_math.h"
|
||||||
#include "fuel_computer.h"
|
#include "fuel_computer.h"
|
||||||
|
#include "injector_model.h"
|
||||||
#include "interpolation.h"
|
#include "interpolation.h"
|
||||||
#include "engine_configuration.h"
|
#include "engine_configuration.h"
|
||||||
#include "allsensors.h"
|
#include "allsensors.h"
|
||||||
|
@ -193,6 +194,7 @@ AirmassModelBase* getAirmassModel(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static FuelComputer fuelComputer(afrMap);
|
static FuelComputer fuelComputer(afrMap);
|
||||||
|
static InjectorModel injectorModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* per-cylinder fuel amount
|
* per-cylinder fuel amount
|
||||||
|
@ -370,7 +372,9 @@ void initFuelMap(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
||||||
INJECT_ENGINE_REFERENCE(&sdAirmass);
|
INJECT_ENGINE_REFERENCE(&sdAirmass);
|
||||||
INJECT_ENGINE_REFERENCE(&mafAirmass);
|
INJECT_ENGINE_REFERENCE(&mafAirmass);
|
||||||
INJECT_ENGINE_REFERENCE(&alphaNAirmass);
|
INJECT_ENGINE_REFERENCE(&alphaNAirmass);
|
||||||
|
|
||||||
INJECT_ENGINE_REFERENCE(&fuelComputer);
|
INJECT_ENGINE_REFERENCE(&fuelComputer);
|
||||||
|
INJECT_ENGINE_REFERENCE(&injectorModel);
|
||||||
|
|
||||||
#if (IGN_LOAD_COUNT == FUEL_LOAD_COUNT) && (IGN_RPM_COUNT == FUEL_RPM_COUNT)
|
#if (IGN_LOAD_COUNT == FUEL_LOAD_COUNT) && (IGN_RPM_COUNT == FUEL_RPM_COUNT)
|
||||||
fuelPhaseMap.init(config->injectionPhase, config->injPhaseLoadBins, config->injPhaseRpmBins);
|
fuelPhaseMap.init(config->injectionPhase, config->injPhaseLoadBins, config->injPhaseRpmBins);
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
#include "engine_test_helper.h"
|
||||||
|
#include "injector_model.h"
|
||||||
|
#include "mocks.h"
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
using ::testing::StrictMock;
|
||||||
|
|
||||||
|
class MockInjectorModel : public InjectorModelBase {
|
||||||
|
public:
|
||||||
|
MOCK_METHOD(floatms_t, getDeadtime, (), (const, override));
|
||||||
|
MOCK_METHOD(float, getInjectorMassFlowRate, (), (const, override));
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(InjectorModel, Prepare) {
|
||||||
|
StrictMock<MockInjectorModel> dut;
|
||||||
|
|
||||||
|
EXPECT_CALL(dut, getDeadtime());
|
||||||
|
EXPECT_CALL(dut, getInjectorMassFlowRate());
|
||||||
|
|
||||||
|
dut.prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(InjectorModel, getInjectionDuration) {
|
||||||
|
StrictMock<MockInjectorModel> dut;
|
||||||
|
|
||||||
|
EXPECT_CALL(dut, getDeadtime())
|
||||||
|
.WillRepeatedly(Return(2.0f));
|
||||||
|
EXPECT_CALL(dut, getInjectorMassFlowRate())
|
||||||
|
.WillRepeatedly(Return(4.8f)); // 400cc/min
|
||||||
|
|
||||||
|
dut.prepare();
|
||||||
|
|
||||||
|
EXPECT_NEAR(dut.getInjectionDuration(0.01f), 10 / 4.8f + 2.0f, EPS4D);
|
||||||
|
EXPECT_NEAR(dut.getInjectionDuration(0.02f), 20 / 4.8f + 2.0f, EPS4D);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(InjectorModel, Deadtime) {
|
||||||
|
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
|
||||||
|
|
||||||
|
// Some test data in the injector correction table
|
||||||
|
for (size_t i = 0; i < efi::size(engineConfiguration->injector.battLagCorr); i++) {
|
||||||
|
CONFIG(injector.battLagCorr)[i] = 2 * i;
|
||||||
|
CONFIG(injector.battLagCorrBins)[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
InjectorModel dut;
|
||||||
|
INJECT_ENGINE_REFERENCE(&dut);
|
||||||
|
|
||||||
|
engine->sensors.vBatt = 3;
|
||||||
|
EXPECT_EQ(dut.getDeadtime(), 6);
|
||||||
|
|
||||||
|
engine->sensors.vBatt = 7;
|
||||||
|
EXPECT_EQ(dut.getDeadtime(), 14);
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ TESTS_SRC_CPP = \
|
||||||
tests/ignition_injection/test_ignition_scheduling.cpp \
|
tests/ignition_injection/test_ignition_scheduling.cpp \
|
||||||
tests/ignition_injection/test_fuelCut.cpp \
|
tests/ignition_injection/test_fuelCut.cpp \
|
||||||
tests/ignition_injection/test_fuel_computer.cpp \
|
tests/ignition_injection/test_fuel_computer.cpp \
|
||||||
|
tests/ignition_injection/test_injector_model.cpp \
|
||||||
tests/test_util.cpp \
|
tests/test_util.cpp \
|
||||||
tests/test_ion.cpp \
|
tests/test_ion.cpp \
|
||||||
tests/test_aux_valves.cpp \
|
tests/test_aux_valves.cpp \
|
||||||
|
|
Loading…
Reference in New Issue