diff --git a/firmware/controllers/algo/fuel/injector_model.cpp b/firmware/controllers/algo/fuel/injector_model.cpp index bdb8045f0c..1b904c896c 100644 --- a/firmware/controllers/algo/fuel/injector_model.cpp +++ b/firmware/controllers/algo/fuel/injector_model.cpp @@ -50,20 +50,49 @@ InjectorNonlinearMode InjectorModel::getNonlinearMode() const { return engineConfiguration->injectorNonlinearMode; } -expected InjectorModel::getAbsoluteRailPressure() const { +expected InjectorModel::getFuelDifferentialPressure() const { + auto map = Sensor::get(SensorType::Map); + float baro = Sensor::get(SensorType::BarometricPressure).value_or(101.325f); + switch (engineConfiguration->injectorCompensationMode) { case ICM_FixedRailPressure: // Add barometric pressure, as "fixed" really means "fixed pressure above atmosphere" - return engineConfiguration->fuelReferencePressure + Sensor::get(SensorType::BarometricPressure).value_or(101.325f); - case ICM_SensedRailPressure: + return + engineConfiguration->fuelReferencePressure + + baro + - map.value_or(101.325); + case ICM_SensedRailPressure: { if (!Sensor::hasSensor(SensorType::FuelPressureInjector)) { firmwareError(OBD_PCM_Processor_Fault, "Fuel pressure compensation is set to use a pressure sensor, but none is configured."); return unexpected; } + auto fps = Sensor::get(SensorType::FuelPressureInjector); + // TODO: what happens when the sensor fails? - return Sensor::get(SensorType::FuelPressureInjector); - default: return unexpected; + if (!fps) { + return unexpected; + } + + switch (engineConfiguration->fuelPressureSensorMode) { + case FPM_Differential: + // This sensor directly measures delta-P, no math needed! + return fps.Value; + case FPM_Gauge: + if (!map) { + return unexpected; + } + + return fps.Value + baro - map.Value; + case FPM_Absolute: + default: + if (!map) { + return unexpected; + } + + return fps.Value - map.Value; + } + } default: return unexpected; } } @@ -82,21 +111,14 @@ float InjectorModel::getInjectorFlowRatio() { return 1.0f; } - expected absRailPressure = getAbsoluteRailPressure(); + expected diffPressure = getFuelDifferentialPressure(); // If sensor failed, best we can do is disable correction - if (!absRailPressure) { + if (!diffPressure) { return 1.0f; } - auto map = Sensor::get(SensorType::Map); - - // Map has failed, assume nominal pressure - if (!map) { - return 1.0f; - } - - pressureDelta = absRailPressure.Value - map.Value; + pressureDelta = diffPressure.Value; // Somehow pressure delta is less than 0, assume failed sensor and return default flow if (pressureDelta <= 0) { diff --git a/firmware/controllers/algo/fuel/injector_model.h b/firmware/controllers/algo/fuel/injector_model.h index 3c37b7deaa..db41c0ce6a 100644 --- a/firmware/controllers/algo/fuel/injector_model.h +++ b/firmware/controllers/algo/fuel/injector_model.h @@ -18,7 +18,7 @@ public: float getFuelMassForDuration(floatms_t duration) const override; virtual float getInjectorFlowRatio() = 0; - virtual expected getAbsoluteRailPressure() const = 0; + virtual expected getFuelDifferentialPressure() const = 0; virtual float getBaseFlowRate() const = 0; @@ -50,7 +50,7 @@ public: floatms_t getDeadtime() const override; float getBaseFlowRate() const override; float getInjectorFlowRatio() override; - expected getAbsoluteRailPressure() const override; + expected getFuelDifferentialPressure() const override; InjectorNonlinearMode getNonlinearMode() const override; diff --git a/unit_tests/tests/ignition_injection/test_injector_model.cpp b/unit_tests/tests/ignition_injection/test_injector_model.cpp index a504cc866c..1ef3f43e00 100644 --- a/unit_tests/tests/ignition_injection/test_injector_model.cpp +++ b/unit_tests/tests/ignition_injection/test_injector_model.cpp @@ -9,7 +9,7 @@ public: MOCK_METHOD(floatms_t, getDeadtime, (), (const, override)); MOCK_METHOD(float, getBaseFlowRate, (), (const, override)); MOCK_METHOD(float, getInjectorFlowRatio, (), (override)); - MOCK_METHOD(expected, getAbsoluteRailPressure, (), (const, override)); + MOCK_METHOD(expected, getFuelDifferentialPressure, (), (const, override)); MOCK_METHOD(float, getSmallPulseFlowRate, (), (const, override)); MOCK_METHOD(float, getSmallPulseBreakPoint, (), (const, override)); MOCK_METHOD(InjectorNonlinearMode, getNonlinearMode, (), (const, override)); @@ -152,7 +152,7 @@ struct TesterGetFlowRate : public InjectorModel { }; struct TesterGetRailPressure : public InjectorModel { - MOCK_METHOD(expected, getAbsoluteRailPressure, (), (const, override)); + MOCK_METHOD(expected, getFuelDifferentialPressure, (), (const, override)); }; class FlowRateFixture : public ::testing::TestWithParam { @@ -168,22 +168,18 @@ TEST_P(FlowRateFixture, PressureRatio) { float pressureRatio = GetParam(); // Flow ratio should be the sqrt of pressure ratio float expectedFlowRatio = sqrtf(pressureRatio); - float fakeMap = 35.0f; StrictMock dut; - EXPECT_CALL(dut, getAbsoluteRailPressure()).WillOnce(Return(400 * pressureRatio + fakeMap)); + EXPECT_CALL(dut, getFuelDifferentialPressure()).WillOnce(Return(400 * pressureRatio)); EngineTestHelper eth(TEST_ENGINE); // Use injector compensation engineConfiguration->injectorCompensationMode = ICM_SensedRailPressure; - // Reference pressure is 400kPa + // Reference pressure is 400kPa engineConfiguration->fuelReferencePressure = 400.0f; - // MAP sensor always reads 35 kpa - Sensor::setMockValue(SensorType::Map, fakeMap); - // Should return the expected ratio EXPECT_FLOAT_EQ(expectedFlowRatio, dut.getInjectorFlowRatio()); } @@ -196,12 +192,10 @@ TEST(InjectorModel, NegativePressureDelta) { // Use injector compensation engineConfiguration->injectorCompensationMode = ICM_SensedRailPressure; - // Reference pressure is 400kPa + // Reference pressure is 400kPa engineConfiguration->fuelReferencePressure = 400.0f; - EXPECT_CALL(dut, getAbsoluteRailPressure()).WillOnce(Return(50)); - // MAP sensor reads more pressure than fuel rail - Sensor::setMockValue(SensorType::Map, 100); + EXPECT_CALL(dut, getFuelDifferentialPressure()).WillOnce(Return(-50)); // Flow ratio defaults to 1.0 in this case EXPECT_FLOAT_EQ(1.0f, dut.getInjectorFlowRatio()); @@ -214,7 +208,7 @@ TEST(InjectorModel, VariableInjectorFlowModeNone) { engineConfiguration->injectorCompensationMode = ICM_None; - // This shoudn't call getAbsoluteRailPressure, it should just return 1.0 + // This shoudn't call getFuelDifferentialPressure, it should just return 1.0 EXPECT_FLOAT_EQ(1, dut.getInjectorFlowRatio()); } @@ -227,25 +221,73 @@ TEST(InjectorModel, RailPressureFixed) { engineConfiguration->fuelReferencePressure = 350; engineConfiguration->injectorCompensationMode = ICM_FixedRailPressure; - // Should be reference pressure + 1 atm - EXPECT_FLOAT_EQ(101.325f + 350.0f, dut.getAbsoluteRailPressure().value_or(0)); + // MAP is 75kPa + Sensor::setMockValue(SensorType::Map, 75); + + // Baro is 100kpa + Sensor::setMockValue(SensorType::BarometricPressure, 100); + + // Should be reference pressure + 1 atm - 75kpa -> 375kPa + EXPECT_FLOAT_EQ(375.0f, dut.getFuelDifferentialPressure().value_or(0)); } -TEST(InjectorModel, RailPressureSensed) { +TEST(InjectorModel, RailPressureSensedAbsolute) { InjectorModel dut; EngineTestHelper eth(TEST_ENGINE); // Reference pressure is 350kpa engineConfiguration->injectorCompensationMode = ICM_SensedRailPressure; + engineConfiguration->fuelPressureSensorMode = FPM_Absolute; + + Sensor::setMockValue(SensorType::Map, 50); + + // Should just return rail sensor value - MAP + Sensor::setMockValue(SensorType::FuelPressureInjector, 100); + EXPECT_FLOAT_EQ(100 - 50, dut.getFuelDifferentialPressure().value_or(-1)); + Sensor::setMockValue(SensorType::FuelPressureInjector, 200); + EXPECT_FLOAT_EQ(200 - 50, dut.getFuelDifferentialPressure().value_or(-1)); + Sensor::setMockValue(SensorType::FuelPressureInjector, 300); + EXPECT_FLOAT_EQ(300 - 50, dut.getFuelDifferentialPressure().value_or(-1)); +} + +TEST(InjectorModel, RailPressureSensedGauge) { + InjectorModel dut; + + EngineTestHelper eth(TEST_ENGINE); + + // Reference pressure is 350kpa + engineConfiguration->injectorCompensationMode = ICM_SensedRailPressure; + engineConfiguration->fuelPressureSensorMode = FPM_Gauge; + + Sensor::setMockValue(SensorType::BarometricPressure, 110); + Sensor::setMockValue(SensorType::Map, 50); + + // Should just return rail sensor value + baro - MAP + Sensor::setMockValue(SensorType::FuelPressureInjector, 100); + EXPECT_FLOAT_EQ(100 + 110 - 50, dut.getFuelDifferentialPressure().value_or(-1)); + Sensor::setMockValue(SensorType::FuelPressureInjector, 200); + EXPECT_FLOAT_EQ(200 + 110 - 50, dut.getFuelDifferentialPressure().value_or(-1)); + Sensor::setMockValue(SensorType::FuelPressureInjector, 300); + EXPECT_FLOAT_EQ(300 + 110 - 50, dut.getFuelDifferentialPressure().value_or(-1)); +} + +TEST(InjectorModel, RailPressureSensedDifferential) { + InjectorModel dut; + + EngineTestHelper eth(TEST_ENGINE); + + // Reference pressure is 350kpa + engineConfiguration->injectorCompensationMode = ICM_SensedRailPressure; + engineConfiguration->fuelPressureSensorMode = FPM_Differential; // Should just return rail sensor value Sensor::setMockValue(SensorType::FuelPressureInjector, 100); - EXPECT_FLOAT_EQ(100, dut.getAbsoluteRailPressure().value_or(-1)); + EXPECT_FLOAT_EQ(100, dut.getFuelDifferentialPressure().value_or(-1)); Sensor::setMockValue(SensorType::FuelPressureInjector, 200); - EXPECT_FLOAT_EQ(200, dut.getAbsoluteRailPressure().value_or(-1)); + EXPECT_FLOAT_EQ(200, dut.getFuelDifferentialPressure().value_or(-1)); Sensor::setMockValue(SensorType::FuelPressureInjector, 300); - EXPECT_FLOAT_EQ(300, dut.getAbsoluteRailPressure().value_or(-1)); + EXPECT_FLOAT_EQ(300, dut.getFuelDifferentialPressure().value_or(-1)); } TEST(InjectorModel, FailedPressureSensor) {