mirror of https://github.com/FOME-Tech/fome-fw.git
implement "ford mode" injector correction (#4686)
* implement "ford mode" * missed the enum value
This commit is contained in:
parent
c51e54ee2b
commit
890a8e0fed
|
@ -10,14 +10,46 @@
|
||||||
#include "fuel_computer.h"
|
#include "fuel_computer.h"
|
||||||
|
|
||||||
void InjectorModelBase::prepare() {
|
void InjectorModelBase::prepare() {
|
||||||
m_massFlowRate = getInjectorMassFlowRate();
|
float flowRatio = getInjectorFlowRatio();
|
||||||
|
|
||||||
|
// "large pulse" flow rate
|
||||||
|
m_massFlowRate = flowRatio * getBaseFlowRate();
|
||||||
m_deadtime = getDeadtime();
|
m_deadtime = getDeadtime();
|
||||||
|
|
||||||
|
if (getNonlinearMode() == INJ_FordModel) {
|
||||||
|
m_smallPulseFlowRate = flowRatio * getSmallPulseFlowRate();
|
||||||
|
m_smallPulseBreakPoint = getSmallPulseBreakPoint();
|
||||||
|
|
||||||
|
// amount added to small pulses to correct for the "kink" from low flow region
|
||||||
|
m_smallPulseOffset = 1000 * ((m_smallPulseBreakPoint / m_massFlowRate) - (m_smallPulseBreakPoint / m_smallPulseFlowRate));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr float convertToGramsPerSecond(float ccPerMinute) {
|
constexpr float convertToGramsPerSecond(float ccPerMinute) {
|
||||||
return ccPerMinute * (fuelDensity / 60.f);
|
return ccPerMinute * (fuelDensity / 60.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float InjectorModel::getBaseFlowRate() const {
|
||||||
|
if (engineConfiguration->injectorFlowAsMassFlow) {
|
||||||
|
return engineConfiguration->injector.flow;
|
||||||
|
} else {
|
||||||
|
return convertToGramsPerSecond(engineConfiguration->injector.flow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float InjectorModel::getSmallPulseFlowRate() const {
|
||||||
|
return engineConfiguration->fordInjectorSmallPulseSlope;
|
||||||
|
}
|
||||||
|
|
||||||
|
float InjectorModel::getSmallPulseBreakPoint() const {
|
||||||
|
// convert milligrams -> grams
|
||||||
|
return 0.001f * engineConfiguration->fordInjectorSmallPulseBreakPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
InjectorNonlinearMode InjectorModel::getNonlinearMode() const {
|
||||||
|
return engineConfiguration->injectorNonlinearMode;
|
||||||
|
}
|
||||||
|
|
||||||
expected<float> InjectorModel::getAbsoluteRailPressure() const {
|
expected<float> InjectorModel::getAbsoluteRailPressure() const {
|
||||||
switch (engineConfiguration->injectorCompensationMode) {
|
switch (engineConfiguration->injectorCompensationMode) {
|
||||||
case ICM_FixedRailPressure:
|
case ICM_FixedRailPressure:
|
||||||
|
@ -79,15 +111,6 @@ float InjectorModel::getInjectorFlowRatio() {
|
||||||
return flowRatio;
|
return flowRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
float InjectorModel::getInjectorMassFlowRate() {
|
|
||||||
// TODO: injector flow dependent upon temperature/ethanol content?
|
|
||||||
auto injectorVolumeFlow = engineConfiguration->injector.flow;
|
|
||||||
|
|
||||||
float flowRatio = getInjectorFlowRatio();
|
|
||||||
|
|
||||||
return flowRatio * convertToGramsPerSecond(injectorVolumeFlow);
|
|
||||||
}
|
|
||||||
|
|
||||||
float InjectorModel::getDeadtime() const {
|
float InjectorModel::getDeadtime() const {
|
||||||
return interpolate2d(
|
return interpolate2d(
|
||||||
Sensor::get(SensorType::BatteryVoltage).value_or(VBAT_FALLBACK_VALUE),
|
Sensor::get(SensorType::BatteryVoltage).value_or(VBAT_FALLBACK_VALUE),
|
||||||
|
@ -97,18 +120,15 @@ float InjectorModel::getDeadtime() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
float InjectorModelBase::getInjectionDuration(float fuelMassGram) const {
|
float InjectorModelBase::getInjectionDuration(float fuelMassGram) const {
|
||||||
// TODO: support injector nonlinearity correction
|
if (fuelMassGram <= 0) {
|
||||||
|
// If 0 mass, don't do any math, just skip the injection.
|
||||||
floatms_t baseDuration = fuelMassGram / m_massFlowRate * 1000;
|
|
||||||
|
|
||||||
if (baseDuration <= 0) {
|
|
||||||
// If 0 duration, don't correct or add deadtime, just skip the injection.
|
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Correct short pulses (if enabled)
|
// Get the no-offset duration
|
||||||
baseDuration = correctShortPulse(baseDuration);
|
float baseDuration = getBaseDurationImpl(fuelMassGram);
|
||||||
|
|
||||||
|
// Add deadtime offset
|
||||||
return baseDuration + m_deadtime;
|
return baseDuration + m_deadtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,8 +137,18 @@ float InjectorModelBase::getFuelMassForDuration(floatms_t duration) const {
|
||||||
return duration * m_massFlowRate * 0.001f;
|
return duration * m_massFlowRate * 0.001f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float InjectorModel::correctShortPulse(float baseDuration) const {
|
float InjectorModelBase::getBaseDurationImpl(float fuelMassGram) const {
|
||||||
switch (engineConfiguration->injectorNonlinearMode) {
|
floatms_t baseDuration = fuelMassGram / m_massFlowRate * 1000;
|
||||||
|
|
||||||
|
switch (getNonlinearMode()) {
|
||||||
|
case INJ_FordModel:
|
||||||
|
if (fuelMassGram < m_smallPulseBreakPoint) {
|
||||||
|
// Small pulse uses a different slope, and adds the "zero fuel pulse" offset
|
||||||
|
return (fuelMassGram / m_smallPulseFlowRate * 1000) + m_smallPulseOffset;
|
||||||
|
} else {
|
||||||
|
// Large pulse
|
||||||
|
return baseDuration;
|
||||||
|
}
|
||||||
case INJ_PolynomialAdder:
|
case INJ_PolynomialAdder:
|
||||||
return correctInjectionPolynomial(baseDuration);
|
return correctInjectionPolynomial(baseDuration);
|
||||||
case INJ_None:
|
case INJ_None:
|
||||||
|
@ -127,7 +157,7 @@ float InjectorModel::correctShortPulse(float baseDuration) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float InjectorModel::correctInjectionPolynomial(float baseDuration) const {
|
float InjectorModelBase::correctInjectionPolynomial(float baseDuration) const {
|
||||||
if (baseDuration > engineConfiguration->applyNonlinearBelowPulse) {
|
if (baseDuration > engineConfiguration->applyNonlinearBelowPulse) {
|
||||||
// Large pulse, skip correction.
|
// Large pulse, skip correction.
|
||||||
return baseDuration;
|
return baseDuration;
|
||||||
|
|
|
@ -17,26 +17,48 @@ public:
|
||||||
floatms_t getInjectionDuration(float fuelMassGram) const override;
|
floatms_t getInjectionDuration(float fuelMassGram) const override;
|
||||||
float getFuelMassForDuration(floatms_t duration) const override;
|
float getFuelMassForDuration(floatms_t duration) const override;
|
||||||
|
|
||||||
virtual float getInjectorMassFlowRate() = 0;
|
|
||||||
virtual float getInjectorFlowRatio() = 0;
|
virtual float getInjectorFlowRatio() = 0;
|
||||||
virtual expected<float> getAbsoluteRailPressure() const = 0;
|
virtual expected<float> getAbsoluteRailPressure() const = 0;
|
||||||
virtual float correctShortPulse(float baseDuration) const = 0;
|
|
||||||
|
virtual float getBaseFlowRate() const = 0;
|
||||||
|
|
||||||
|
virtual InjectorNonlinearMode getNonlinearMode() const = 0;
|
||||||
|
float getBaseDurationImpl(float baseDuration) const;
|
||||||
|
virtual float correctInjectionPolynomial(float baseDuration) const;
|
||||||
|
|
||||||
|
// Ford small pulse model
|
||||||
|
virtual float getSmallPulseFlowRate() const = 0;
|
||||||
|
virtual float getSmallPulseBreakPoint() const = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Mass flow rate for large-pulse flow, g/s
|
||||||
float m_massFlowRate = 0;
|
float m_massFlowRate = 0;
|
||||||
|
|
||||||
|
// Break point below which the "small pulse" slope is used, grams
|
||||||
|
float m_smallPulseBreakPoint = 0;
|
||||||
|
|
||||||
|
// Flow rate for small pulses, g/s
|
||||||
|
float m_smallPulseFlowRate = 0;
|
||||||
|
|
||||||
|
// Correction adder for small pulses to correct for small/large pulse kink, ms
|
||||||
|
float m_smallPulseOffset = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InjectorModel : public InjectorModelBase {
|
class InjectorModel : public InjectorModelBase {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
floatms_t getDeadtime() const override;
|
floatms_t getDeadtime() const override;
|
||||||
float getInjectorMassFlowRate() override;
|
float getBaseFlowRate() const override;
|
||||||
float getInjectorFlowRatio() override;
|
float getInjectorFlowRatio() override;
|
||||||
expected<float> getAbsoluteRailPressure() const override;
|
expected<float> getAbsoluteRailPressure() const override;
|
||||||
|
|
||||||
|
InjectorNonlinearMode getNonlinearMode() const override;
|
||||||
|
|
||||||
|
// Ford small pulse model
|
||||||
|
float getSmallPulseFlowRate() const override;
|
||||||
|
float getSmallPulseBreakPoint() const override;
|
||||||
|
|
||||||
// Small pulse correction logic
|
// Small pulse correction logic
|
||||||
float correctShortPulse(float baseDuration) const override;
|
|
||||||
virtual float correctInjectionPolynomial(float baseDuration) const;
|
|
||||||
|
|
||||||
using interface_t = IInjectorModel; // Mock interface
|
using interface_t = IInjectorModel; // Mock interface
|
||||||
};
|
};
|
||||||
|
|
|
@ -620,6 +620,7 @@ typedef enum __attribute__ ((__packed__)) {
|
||||||
typedef enum __attribute__ ((__packed__)) {
|
typedef enum __attribute__ ((__packed__)) {
|
||||||
INJ_None = 0,
|
INJ_None = 0,
|
||||||
INJ_PolynomialAdder = 1,
|
INJ_PolynomialAdder = 1,
|
||||||
|
INJ_FordModel = 2,
|
||||||
} InjectorNonlinearMode;
|
} InjectorNonlinearMode;
|
||||||
|
|
||||||
typedef enum __attribute__ ((__packed__)) {
|
typedef enum __attribute__ ((__packed__)) {
|
||||||
|
|
|
@ -742,7 +742,9 @@ pin_input_mode_e throttlePedalUpPinMode;
|
||||||
float compressionRatio;Just for reference really, not taken into account by any logic at this point;"CR", 1, 0, 0, 300, 1
|
float compressionRatio;Just for reference really, not taken into account by any logic at this point;"CR", 1, 0, 0, 300, 1
|
||||||
|
|
||||||
Gpio[TRIGGER_SIMULATOR_PIN_COUNT iterate] triggerSimulatorPins;Each rusEFI piece can provide synthetic trigger signal for external ECU. Sometimes these wires are routed back into trigger inputs of the same rusEFI board.\nSee also directSelfStimulation which is different.
|
Gpio[TRIGGER_SIMULATOR_PIN_COUNT iterate] triggerSimulatorPins;Each rusEFI piece can provide synthetic trigger signal for external ECU. Sometimes these wires are routed back into trigger inputs of the same rusEFI board.\nSee also directSelfStimulation which is different.
|
||||||
uint16_t unusedTrig
|
|
||||||
|
uint16_t autoscale fordInjectorSmallPulseSlope;;"g/s", 0.001, 0, 0, 65, 3
|
||||||
|
|
||||||
pin_output_mode_e[TRIGGER_SIMULATOR_PIN_COUNT iterate] triggerSimulatorPinModes;
|
pin_output_mode_e[TRIGGER_SIMULATOR_PIN_COUNT iterate] triggerSimulatorPinModes;
|
||||||
uint8_t unusedTrigMode
|
uint8_t unusedTrigMode
|
||||||
output_pin_e o2heaterPin;Narrow band o2 heater, not used for CJ125. 'ON' if engine is running, 'OFF' if stopped or cranking. See wboHeaterPin
|
output_pin_e o2heaterPin;Narrow band o2 heater, not used for CJ125. 'ON' if engine is running, 'OFF' if stopped or cranking. See wboHeaterPin
|
||||||
|
@ -817,7 +819,7 @@ output_pin_e acFanPin;Optional Radiator Fan used with A/C
|
||||||
|
|
||||||
brain_input_pin_e vehicleSpeedSensorInputPin;
|
brain_input_pin_e vehicleSpeedSensorInputPin;
|
||||||
switch_input_pin_e clutchUpPin;Some vehicles have a switch to indicate that clutch pedal is all the way up
|
switch_input_pin_e clutchUpPin;Some vehicles have a switch to indicate that clutch pedal is all the way up
|
||||||
custom InjectorNonlinearMode 1 bits, U08, @OFFSET@, [0:0], "None", "Polynomial"
|
custom InjectorNonlinearMode 1 bits, U08, @OFFSET@, [0:1], "None", "Polynomial", "Ford (dual slope)"
|
||||||
InjectorNonlinearMode injectorNonlinearMode
|
InjectorNonlinearMode injectorNonlinearMode
|
||||||
pin_input_mode_e clutchUpPinMode;
|
pin_input_mode_e clutchUpPinMode;
|
||||||
|
|
||||||
|
@ -1212,7 +1214,7 @@ int16_t tps2Max;Full throttle#2. tpsMax value as 10 bit ADC value. Not Voltage!\
|
||||||
bit stepperDcInvertedPins;Enable if DC-motor driver (H-bridge) inverts the signals (eg. RZ7899 on Hellen boards)
|
bit stepperDcInvertedPins;Enable if DC-motor driver (H-bridge) inverts the signals (eg. RZ7899 on Hellen boards)
|
||||||
bit canOpenBLT; Allow OpenBLT on Primary CAN
|
bit canOpenBLT; Allow OpenBLT on Primary CAN
|
||||||
bit can2OpenBLT; Allow OpenBLT on Secondary CAN
|
bit can2OpenBLT; Allow OpenBLT on Secondary CAN
|
||||||
bit unused1740b2
|
bit injectorFlowAsMassFlow,"mass flow","volumetric flow";Select whether to configure injector flow in volumetric flow (defualt, cc/min) or mass flow (g/s).
|
||||||
bit unused1127
|
bit unused1127
|
||||||
bit unused1128
|
bit unused1128
|
||||||
bit unused1129
|
bit unused1129
|
||||||
|
@ -1444,7 +1446,9 @@ tChargeMode_e tChargeMode;
|
||||||
uint8_t autoscale dfcoDelay;Delay before cutting fuel. Set to 0 to cut immediately with no delay. May cause rumbles and pops out of your exhaust...;"sec", 0.1, 0, 0, 10, 1
|
uint8_t autoscale dfcoDelay;Delay before cutting fuel. Set to 0 to cut immediately with no delay. May cause rumbles and pops out of your exhaust...;"sec", 0.1, 0, 0, 10, 1
|
||||||
uint8_t autoscale acDelay;Delay before engaging the AC compressor. Set to 0 to engage immediately with no delay. Use this to prevent bogging at idle when AC engages.;"sec", 0.1, 0, 0, 10, 1
|
uint8_t autoscale acDelay;Delay before engaging the AC compressor. Set to 0 to engage immediately with no delay. Use this to prevent bogging at idle when AC engages.;"sec", 0.1, 0, 0, 10, 1
|
||||||
|
|
||||||
int8_t[9] unused4080;;"", 1, 0, 0, 0, 0
|
uint16_t autoscale fordInjectorSmallPulseBreakPoint;;"mg", 0.001, 0, 0, 65, 3
|
||||||
|
|
||||||
|
int8_t[5] unused4080;;"", 1, 0, 0, 0, 0
|
||||||
|
|
||||||
! Someday there will be a 6th option for BMW S55 that uses a separate shaft just for HPFP
|
! Someday there will be a 6th option for BMW S55 that uses a separate shaft just for HPFP
|
||||||
#define hpfp_cam_e_enum "NONE", "Intake 1", "Exhaust 1", "Intake 2", "Exhaust 2"
|
#define hpfp_cam_e_enum "NONE", "Intake 1", "Exhaust 1", "Intake 2", "Exhaust 2"
|
||||||
|
|
|
@ -2222,7 +2222,8 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_
|
||||||
|
|
||||||
; Engine->Injection Settings
|
; Engine->Injection Settings
|
||||||
dialog = injChars, "Injector Settings", yAxis
|
dialog = injChars, "Injector Settings", yAxis
|
||||||
field = "Injector Flow", injector_flow, {isInjectionEnabled == 1}
|
field = "Injector flow", injector_flow, {isInjectionEnabled == 1}
|
||||||
|
field = "Injector flow units", injectorFlowAsMassFlow, {isInjectionEnabled == 1}
|
||||||
field = "Fuel rail pressure sensor", injectorPressureType, { isInjectionEnabled && (highPressureFuel_hwChannel || lowPressureFuel_hwChannel) }
|
field = "Fuel rail pressure sensor", injectorPressureType, { isInjectionEnabled && (highPressureFuel_hwChannel || lowPressureFuel_hwChannel) }
|
||||||
field = "Injector flow compensation mode", injectorCompensationMode, { isInjectionEnabled }
|
field = "Injector flow compensation mode", injectorCompensationMode, { isInjectionEnabled }
|
||||||
field = "Injector reference pressure", fuelReferencePressure, { isInjectionEnabled && injectorCompensationMode != 0 }
|
field = "Injector reference pressure", fuelReferencePressure, { isInjectionEnabled && injectorCompensationMode != 0 }
|
||||||
|
@ -2273,9 +2274,16 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_
|
||||||
field = "x^6", injectorCorrectionPolynomial7
|
field = "x^6", injectorCorrectionPolynomial7
|
||||||
field = "x^7", injectorCorrectionPolynomial8
|
field = "x^7", injectorCorrectionPolynomial8
|
||||||
|
|
||||||
|
dialog = injectorNonlinearFord, "Ford-model Small Pulse Correction", yAxis
|
||||||
|
field = "Small pulse slope (ALOSL)", fordInjectorSmallPulseSlope
|
||||||
|
field = "Set this to 'mass flow'", injectorFlowAsMassFlow
|
||||||
|
field = "Large pulse slope (AHISL)", injector_flow
|
||||||
|
field = "Small pulse breakpoint (FUEL_BKPT)", fordInjectorSmallPulseBreakPoint
|
||||||
|
|
||||||
dialog = injectorNonlinear
|
dialog = injectorNonlinear
|
||||||
field = "Small pulse correction mode", injectorNonlinearMode
|
field = "Small pulse correction mode", injectorNonlinearMode
|
||||||
panel = injectorNonlinearPolynomial, {1}, { injectorNonlinearMode != 0 }
|
panel = injectorNonlinearPolynomial, {1}, { injectorNonlinearMode == 1 }
|
||||||
|
panel = injectorNonlinearFord, {1}, { injectorNonlinearMode == 2 }
|
||||||
|
|
||||||
dialog = testLuaOut, "Lua Out Test"
|
dialog = testLuaOut, "Lua Out Test"
|
||||||
commandButton = "Lua Out #1", cmd_test_lua1
|
commandButton = "Lua Out #1", cmd_test_lua1
|
||||||
|
|
|
@ -7,17 +7,21 @@ using ::testing::StrictMock;
|
||||||
class MockInjectorModel : public InjectorModelBase {
|
class MockInjectorModel : public InjectorModelBase {
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD(floatms_t, getDeadtime, (), (const, override));
|
MOCK_METHOD(floatms_t, getDeadtime, (), (const, override));
|
||||||
MOCK_METHOD(float, getInjectorMassFlowRate, (), (override));
|
MOCK_METHOD(float, getBaseFlowRate, (), (const, override));
|
||||||
MOCK_METHOD(float, getInjectorFlowRatio, (), (override));
|
MOCK_METHOD(float, getInjectorFlowRatio, (), (override));
|
||||||
MOCK_METHOD(expected<float>, getAbsoluteRailPressure, (), (const, override));
|
MOCK_METHOD(expected<float>, getAbsoluteRailPressure, (), (const, override));
|
||||||
MOCK_METHOD(float, correctShortPulse, (float baseDuration), (const, override));
|
MOCK_METHOD(float, getSmallPulseFlowRate, (), (const, override));
|
||||||
|
MOCK_METHOD(float, getSmallPulseBreakPoint, (), (const, override));
|
||||||
|
MOCK_METHOD(InjectorNonlinearMode, getNonlinearMode, (), (const, override));
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(InjectorModel, Prepare) {
|
TEST(InjectorModel, Prepare) {
|
||||||
StrictMock<MockInjectorModel> dut;
|
StrictMock<MockInjectorModel> dut;
|
||||||
|
|
||||||
EXPECT_CALL(dut, getDeadtime());
|
EXPECT_CALL(dut, getDeadtime());
|
||||||
EXPECT_CALL(dut, getInjectorMassFlowRate());
|
EXPECT_CALL(dut, getBaseFlowRate());
|
||||||
|
EXPECT_CALL(dut, getNonlinearMode());
|
||||||
|
EXPECT_CALL(dut, getInjectorFlowRatio());
|
||||||
|
|
||||||
dut.prepare();
|
dut.prepare();
|
||||||
}
|
}
|
||||||
|
@ -27,11 +31,12 @@ TEST(InjectorModel, getInjectionDuration) {
|
||||||
|
|
||||||
EXPECT_CALL(dut, getDeadtime())
|
EXPECT_CALL(dut, getDeadtime())
|
||||||
.WillOnce(Return(2.0f));
|
.WillOnce(Return(2.0f));
|
||||||
EXPECT_CALL(dut, getInjectorMassFlowRate())
|
EXPECT_CALL(dut, getInjectorFlowRatio())
|
||||||
|
.WillOnce(Return(1.0f));
|
||||||
|
EXPECT_CALL(dut, getBaseFlowRate())
|
||||||
.WillOnce(Return(4.8f)); // 400cc/min
|
.WillOnce(Return(4.8f)); // 400cc/min
|
||||||
EXPECT_CALL(dut, correctShortPulse(_))
|
EXPECT_CALL(dut, getNonlinearMode())
|
||||||
.Times(2)
|
.WillRepeatedly(Return(INJ_None));
|
||||||
.WillRepeatedly([](float b) { return b; });
|
|
||||||
|
|
||||||
dut.prepare();
|
dut.prepare();
|
||||||
|
|
||||||
|
@ -39,23 +44,65 @@ TEST(InjectorModel, getInjectionDuration) {
|
||||||
EXPECT_NEAR(dut.getInjectionDuration(0.02f), 20 / 4.8f + 2.0f, EPS4D);
|
EXPECT_NEAR(dut.getInjectionDuration(0.02f), 20 / 4.8f + 2.0f, EPS4D);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InjectorModel, getInjectionDurationNonlinear) {
|
TEST(InjectorModel, getInjectionDurationWithFlowRatio) {
|
||||||
StrictMock<MockInjectorModel> dut;
|
StrictMock<MockInjectorModel> dut;
|
||||||
|
|
||||||
EXPECT_CALL(dut, getDeadtime())
|
EXPECT_CALL(dut, getDeadtime())
|
||||||
.WillOnce(Return(2.0f));
|
.WillOnce(Return(2.0f));
|
||||||
EXPECT_CALL(dut, getInjectorMassFlowRate())
|
EXPECT_CALL(dut, getInjectorFlowRatio())
|
||||||
|
.WillOnce(Return(1.1f));
|
||||||
|
EXPECT_CALL(dut, getBaseFlowRate())
|
||||||
.WillOnce(Return(4.8f)); // 400cc/min
|
.WillOnce(Return(4.8f)); // 400cc/min
|
||||||
|
EXPECT_CALL(dut, getNonlinearMode())
|
||||||
// Dummy nonlinearity correction: just doubles the pulse
|
.WillRepeatedly(Return(INJ_None));
|
||||||
EXPECT_CALL(dut, correctShortPulse(_))
|
|
||||||
.Times(2)
|
|
||||||
.WillRepeatedly([](float b) { return 2 * b; });
|
|
||||||
|
|
||||||
dut.prepare();
|
dut.prepare();
|
||||||
|
|
||||||
EXPECT_NEAR(dut.getInjectionDuration(0.01f), 2 * 10 / 4.8f + 2.0f, EPS4D);
|
EXPECT_NEAR(dut.getInjectionDuration(0.01f), 10 / (4.8f * 1.1f) + 2.0f, EPS4D);
|
||||||
EXPECT_NEAR(dut.getInjectionDuration(0.02f), 2 * 20 / 4.8f + 2.0f, EPS4D);
|
EXPECT_NEAR(dut.getInjectionDuration(0.02f), 20 / (4.8f * 1.1f) + 2.0f, EPS4D);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(InjectorModel, nonLinearFordMode) {
|
||||||
|
StrictMock<MockInjectorModel> dut;
|
||||||
|
|
||||||
|
EXPECT_CALL(dut, getDeadtime())
|
||||||
|
.WillOnce(Return(0));
|
||||||
|
EXPECT_CALL(dut, getInjectorFlowRatio())
|
||||||
|
.WillOnce(Return(1.0f));
|
||||||
|
|
||||||
|
// 2005 F150 injectors
|
||||||
|
EXPECT_CALL(dut, getBaseFlowRate())
|
||||||
|
.WillRepeatedly(Return(2.979f));
|
||||||
|
EXPECT_CALL(dut, getSmallPulseFlowRate())
|
||||||
|
.WillRepeatedly(Return(3.562f));
|
||||||
|
EXPECT_CALL(dut, getSmallPulseBreakPoint())
|
||||||
|
.WillRepeatedly(Return(0.00627f));
|
||||||
|
EXPECT_CALL(dut, getNonlinearMode())
|
||||||
|
.WillRepeatedly(Return(INJ_FordModel));
|
||||||
|
|
||||||
|
dut.prepare();
|
||||||
|
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.000f), 0.344f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.001f), 0.625f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.002f), 0.906f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.003f), 1.187f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.004f), 1.467f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.005f), 1.748f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.006f), 2.029f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.007f), 2.350f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.008f), 2.685f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.009f), 3.021f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.010f), 3.357f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.011f), 3.693f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.012f), 4.028f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.013f), 4.364f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.014f), 4.700f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.015f), 5.035f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.016f), 5.371f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.017f), 5.707f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.018f), 6.042f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.019f), 6.378f, 1e-3);
|
||||||
|
EXPECT_NEAR(dut.getBaseDurationImpl(0.020f), 6.714f, 1e-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InjectorModel, nonlinearPolynomial) {
|
TEST(InjectorModel, nonlinearPolynomial) {
|
||||||
|
@ -117,22 +164,6 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
::testing::Values(0.1f, 0.5f, 1.0f, 2.0f, 10.0f)
|
::testing::Values(0.1f, 0.5f, 1.0f, 2.0f, 10.0f)
|
||||||
);
|
);
|
||||||
|
|
||||||
TEST_P(FlowRateFixture, FlowRateRatio) {
|
|
||||||
float flowRatio = GetParam();
|
|
||||||
|
|
||||||
StrictMock<TesterGetFlowRate> dut;
|
|
||||||
EXPECT_CALL(dut, getInjectorFlowRatio()).WillOnce(Return(flowRatio));
|
|
||||||
|
|
||||||
EngineTestHelper eth(TEST_ENGINE);
|
|
||||||
engineConfiguration->injector.flow = 500;
|
|
||||||
|
|
||||||
// 500 cc/min = 6g/s
|
|
||||||
float expectedFlow = flowRatio * 6.0f;
|
|
||||||
|
|
||||||
// Check that flow is adjusted correctly
|
|
||||||
EXPECT_FLOAT_EQ(expectedFlow, dut.getInjectorMassFlowRate());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_P(FlowRateFixture, PressureRatio) {
|
TEST_P(FlowRateFixture, PressureRatio) {
|
||||||
float pressureRatio = GetParam();
|
float pressureRatio = GetParam();
|
||||||
// Flow ratio should be the sqrt of pressure ratio
|
// Flow ratio should be the sqrt of pressure ratio
|
||||||
|
|
Loading…
Reference in New Issue