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_base.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 "fuel_math.h"
|
||||
#include "fuel_computer.h"
|
||||
#include "injector_model.h"
|
||||
#include "interpolation.h"
|
||||
#include "engine_configuration.h"
|
||||
#include "allsensors.h"
|
||||
|
@ -193,6 +194,7 @@ AirmassModelBase* getAirmassModel(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|||
}
|
||||
|
||||
static FuelComputer fuelComputer(afrMap);
|
||||
static InjectorModel injectorModel;
|
||||
|
||||
/**
|
||||
* per-cylinder fuel amount
|
||||
|
@ -370,7 +372,9 @@ void initFuelMap(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|||
INJECT_ENGINE_REFERENCE(&sdAirmass);
|
||||
INJECT_ENGINE_REFERENCE(&mafAirmass);
|
||||
INJECT_ENGINE_REFERENCE(&alphaNAirmass);
|
||||
|
||||
INJECT_ENGINE_REFERENCE(&fuelComputer);
|
||||
INJECT_ENGINE_REFERENCE(&injectorModel);
|
||||
|
||||
#if (IGN_LOAD_COUNT == FUEL_LOAD_COUNT) && (IGN_RPM_COUNT == FUEL_RPM_COUNT)
|
||||
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_fuelCut.cpp \
|
||||
tests/ignition_injection/test_fuel_computer.cpp \
|
||||
tests/ignition_injection/test_injector_model.cpp \
|
||||
tests/test_util.cpp \
|
||||
tests/test_ion.cpp \
|
||||
tests/test_aux_valves.cpp \
|
||||
|
|
Loading…
Reference in New Issue