From 4f1085a87a4f2d39be55e8c1aed7f0cbb00dad54 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sun, 6 Dec 2020 23:05:06 -0600 Subject: [PATCH] Require redundant tps for ETB (#2037) * mod sensor api * require redundancy * fix tests * check that it fails Co-authored-by: Matthew Kennedy --- .../actuators/electronic_throttle.cpp | 14 +++++++ firmware/controllers/sensors/sensor.cpp | 12 ++++-- firmware/controllers/sensors/sensor.h | 5 +-- unit_tests/tests/test_etb.cpp | 41 +++++++++++++++++-- 4 files changed, 62 insertions(+), 10 deletions(-) diff --git a/firmware/controllers/actuators/electronic_throttle.cpp b/firmware/controllers/actuators/electronic_throttle.cpp index 0c441c0247..63d2f4170c 100644 --- a/firmware/controllers/actuators/electronic_throttle.cpp +++ b/firmware/controllers/actuators/electronic_throttle.cpp @@ -168,6 +168,20 @@ bool EtbController::init(etb_function_e function, DcMotor *motor, pid_s *pidPara m_function = function; m_positionSensor = functionToPositionSensor(function); + + // If we are a throttle, require redundant TPS sensor + if (function == ETB_Throttle1 || function == ETB_Throttle2) { + if (!Sensor::isRedundant(m_positionSensor)) { + firmwareError( + OBD_Throttle_Position_Sensor_Circuit_Malfunction, + "Use of electronic throttle requires %s to be redundant.", + Sensor::getSensorName(m_positionSensor) + ); + + return false; + } + } + m_motor = motor; m_pid.initPidClass(pidParameters); m_pedalMap = pedalMap; diff --git a/firmware/controllers/sensors/sensor.cpp b/firmware/controllers/sensors/sensor.cpp index 957ed1ee93..7b873d2b0c 100644 --- a/firmware/controllers/sensors/sensor.cpp +++ b/firmware/controllers/sensors/sensor.cpp @@ -50,9 +50,10 @@ public: return m_sensor; } - void setMockValue(float value) { + void setMockValue(float value, bool mockRedundant) { m_mockValue = value; m_useMock = true; + m_mockRedundant = mockRedundant; } void resetMock() { @@ -131,11 +132,16 @@ public: return sensor->isRedundant(); } + if (m_useMock) { + return m_mockRedundant; + } + return false; } private: bool m_useMock = false; + bool m_mockRedundant = false; float m_mockValue; Sensor* m_sensor = nullptr; }; @@ -201,11 +207,11 @@ bool Sensor::Register() { return entry ? entry->hasSensor() : false; } -/*static*/ void Sensor::setMockValue(SensorType type, float value) { +/*static*/ void Sensor::setMockValue(SensorType type, float value, bool mockRedundant) { auto entry = getEntryForType(type); if (entry) { - entry->setMockValue(value); + entry->setMockValue(value, mockRedundant); } } diff --git a/firmware/controllers/sensors/sensor.h b/firmware/controllers/sensors/sensor.h index ddaac940f2..e21b4b08c7 100644 --- a/firmware/controllers/sensors/sensor.h +++ b/firmware/controllers/sensors/sensor.h @@ -105,7 +105,7 @@ public: /* * Mock a value for a particular sensor. */ - static void setMockValue(SensorType type, float value); + static void setMockValue(SensorType type, float value, bool mockRedundant = false); /* * Mock a value for a particular sensor. @@ -127,6 +127,7 @@ public: * For example, CLT, IAT, Throttle Position 2, etc. */ const char* getSensorName() { return getSensorName(m_type); } + static const char* getSensorName(SensorType type); // Retrieve the current reading from the sensor. // @@ -155,8 +156,6 @@ protected: explicit Sensor(SensorType type) : m_type(type) {} - static const char* getSensorName(SensorType type); - private: const SensorType m_type; diff --git a/unit_tests/tests/test_etb.cpp b/unit_tests/tests/test_etb.cpp index 4ee8f1cac7..48c12f8ac1 100644 --- a/unit_tests/tests/test_etb.cpp +++ b/unit_tests/tests/test_etb.cpp @@ -120,8 +120,8 @@ TEST(etb, initializationDualThrottle) { Sensor::setMockValue(SensorType::AcceleratorPedal, 0); Sensor::setMockValue(SensorType::AcceleratorPedalPrimary, 0); - // The presence of a second TPS indicates dual throttle - Sensor::setMockValue(SensorType::Tps2, 25.0f); + Sensor::setMockValue(SensorType::Tps1, 25.0f, true); + Sensor::setMockValue(SensorType::Tps2, 25.0f, true); engineConfiguration->etbFunctions[0] = ETB_Throttle1; engineConfiguration->etbFunctions[1] = ETB_Throttle2; @@ -172,6 +172,15 @@ TEST(etb, initializationNoFunction) { dut.setOutput(0.5f); } +TEST(etb, initializationNotRedundantTps) { + EtbController dut; + + // Not redundant, should fail upon init + Sensor::setMockValue(SensorType::Tps1, 0.0f, false); + + EXPECT_FATAL_ERROR(dut.init(ETB_Throttle1, nullptr, nullptr, nullptr)); +} + TEST(etb, idlePlumbing) { StrictMock mocks[ETB_COUNT]; @@ -208,6 +217,9 @@ TEST(etb, testSetpointOnlyPedal) { // Uninitialized ETB must return unexpected (and not deference a null pointer) EXPECT_EQ(etb.getSetpoint(), unexpected); + // Must have TPS initialized for ETB setup + Sensor::setMockValue(SensorType::Tps1, 0.0f, true); + etb.init(ETB_Throttle1, nullptr, nullptr, &pedalMap); // Check endpoints and midpoint @@ -249,6 +261,9 @@ TEST(etb, setpointIdle) { engineConfiguration->useETBforIdleControl = true; engineConfiguration->etbIdleThrottleRange = 0; + // Must have TPS initialized for ETB setup + Sensor::setMockValue(SensorType::Tps1, 0.0f, true); + EtbController etb; INJECT_ENGINE_REFERENCE(&etb); @@ -344,8 +359,8 @@ TEST(etb, setpointWastegateController) { TEST(etb, etbTpsSensor) { // Throw some distinct values on the TPS sensors so we can identify that we're getting the correct one - Sensor::setMockValue(SensorType::Tps1, 25.0f); - Sensor::setMockValue(SensorType::Tps2, 75.0f); + Sensor::setMockValue(SensorType::Tps1, 25.0f, true); + Sensor::setMockValue(SensorType::Tps2, 75.0f, true); Sensor::setMockValue(SensorType::WastegatePosition, 33.0f); Sensor::setMockValue(SensorType::IdlePosition, 66.0f); @@ -397,6 +412,9 @@ TEST(etb, setOutputValid) { WITH_ENGINE_TEST_HELPER(TEST_ENGINE); StrictMock motor; + // Must have TPS initialized for ETB setup + Sensor::setMockValue(SensorType::Tps1, 0.0f, true); + EtbController etb; INJECT_ENGINE_REFERENCE(&etb); etb.init(ETB_Throttle1, &motor, nullptr, nullptr); @@ -413,6 +431,9 @@ TEST(etb, setOutputValid2) { WITH_ENGINE_TEST_HELPER(TEST_ENGINE); StrictMock motor; + // Must have TPS initialized for ETB setup + Sensor::setMockValue(SensorType::Tps1, 0.0f, true); + EtbController etb; INJECT_ENGINE_REFERENCE(&etb); etb.init(ETB_Throttle1, &motor, nullptr, nullptr); @@ -429,6 +450,9 @@ TEST(etb, setOutputOutOfRangeHigh) { WITH_ENGINE_TEST_HELPER(TEST_ENGINE); StrictMock motor; + // Must have TPS initialized for ETB setup + Sensor::setMockValue(SensorType::Tps1, 0.0f, true); + EtbController etb; INJECT_ENGINE_REFERENCE(&etb); etb.init(ETB_Throttle1, &motor, nullptr, nullptr); @@ -445,6 +469,9 @@ TEST(etb, setOutputOutOfRangeLow) { WITH_ENGINE_TEST_HELPER(TEST_ENGINE); StrictMock motor; + // Must have TPS initialized for ETB setup + Sensor::setMockValue(SensorType::Tps1, 0.0f, true); + EtbController etb; INJECT_ENGINE_REFERENCE(&etb); etb.init(ETB_Throttle1, &motor, nullptr, nullptr); @@ -461,6 +488,9 @@ TEST(etb, setOutputPauseControl) { WITH_ENGINE_TEST_HELPER(TEST_ENGINE); StrictMock motor; + // Must have TPS initialized for ETB setup + Sensor::setMockValue(SensorType::Tps1, 0.0f, true); + EtbController etb; INJECT_ENGINE_REFERENCE(&etb); etb.init(ETB_Throttle1, &motor, nullptr, nullptr); @@ -480,6 +510,9 @@ TEST(etb, closedLoopPid) { pid.maxValue = 75; pid.minValue = -60; + // Must have TPS initialized for ETB setup + Sensor::setMockValue(SensorType::Tps1, 0.0f, true); + EtbController etb; etb.init(ETB_Throttle1, nullptr, &pid, nullptr);