Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | /** | |||
2 | * @file sensor.h | |||
3 | * @brief Base class for sensors. Inherit this class to implement a new type of sensor. | |||
4 | * | |||
5 | * This file defines the basis for all sensor inputs to the ECU, and provides a registry | |||
6 | * so that consumers may be agnostic to how each sensor may work. | |||
7 | * | |||
8 | * HOW TO ADD A NEW SENSOR TYPE: | |||
9 | * | |||
10 | * 1. Add an entry to the enum in sensor_type.h. Be sure to add it ABOVE the placeholder | |||
11 | * at the end of the list. | |||
12 | * | |||
13 | * 2. In the init/sensor folder, create/modify logic to create an instance of the new sensor, | |||
14 | * configure it if necessary, and call its Register() function if it should be enabled. | |||
15 | * See init_fluid_pressure.cpp for a minimal example. | |||
16 | * | |||
17 | * 3. Consume the new sensor with Sensor::get(SensorType::MyNewSensor) | |||
18 | * | |||
19 | * Providers: | |||
20 | * Instantiate a subclass of Sensor, and implement the Get() function. | |||
21 | * Call Register() to install the new sensor in the registry, preparing it for use. | |||
22 | * | |||
23 | * Mocking: | |||
24 | * The sensor table supports mocking each sensors value. Call Sensor::SetMockValue to | |||
25 | * set a mock value for a particular sensor, and Sensor::ResetMockValue or | |||
26 | * Sensor::ResetAllMocks to reset one or all stored mock values. | |||
27 | * | |||
28 | * Composite Sensors: | |||
29 | * Some sensors may be implemented as composite sensors, ie sensors that depend on other | |||
30 | * sensors to determine their reading. For example, the throttle pedal may have a pair of | |||
31 | * potentiometers that provide redundancy for the pedal's position. Each one may be its | |||
32 | * own sensor, then with one "master" sensors that combines the results of the others, and | |||
33 | * provides validation of whether the readings agree. | |||
34 | * | |||
35 | * @date September 12, 2019 | |||
36 | * @author Matthew Kennedy, (c) 2019 | |||
37 | */ | |||
38 | ||||
39 | #pragma once | |||
40 | ||||
41 | #include "sensor_type.h" | |||
42 | #include <rusefi/expected.h> | |||
43 | ||||
44 | #include <cstddef> | |||
45 | ||||
46 | using SensorResult = expected<float>; | |||
47 | ||||
48 | // Fwd declare - nobody outside of Sensor.cpp needs to see inside this type | |||
49 | class SensorRegistryEntry; | |||
50 | ||||
51 | class Sensor { | |||
52 | public: | |||
53 | // Register this sensor in the sensor registry. | |||
54 | // Returns true if registration succeeded, or false if | |||
55 | // another sensor of the same type is already registered. | |||
56 | bool Register(); | |||
57 | ||||
58 | // Print information about this sensor | |||
59 | virtual void showInfo(const char* sensorName) const = 0; | |||
60 | ||||
61 | // Print information about all sensors | |||
62 | static void showAllSensorInfo(); | |||
63 | ||||
64 | // Print information about a particular sensor | |||
65 | static void showInfo(SensorType type); | |||
66 | ||||
67 | // Remove all sensors from the sensor registry - tread carefully if you use this outside of a unit test | |||
68 | static void resetRegistry(); | |||
69 | ||||
70 | /* | |||
71 | * Static helper for sensor lookup | |||
72 | */ | |||
73 | static const Sensor *getSensorOfType(SensorType type); | |||
74 | ||||
75 | /* | |||
76 | * Get a reading from the specified sensor. | |||
77 | */ | |||
78 | static SensorResult get(SensorType type); | |||
79 | ||||
80 | /* | |||
81 | * Get a reading from the specified sensor, or zero if unavailable. | |||
82 | */ | |||
83 | 29395800 | static float getOrZero(SensorType type) { | ||
84 |
1/1✓ Branch 2 taken 29395800 times.
|
29395800 | return Sensor::get(type).value_or(0); | |
85 | } | |||
86 | ||||
87 | /* | |||
88 | * Get a raw (unconverted) value from the sensor, if available. | |||
89 | */ | |||
90 | static float getRaw(SensorType type); | |||
91 | ||||
92 | /* | |||
93 | * Get whether a sensor is redundant (a composite of multiple other sensors that can check consistency between them) | |||
94 | */ | |||
95 | static bool isRedundant(SensorType type); | |||
96 | ||||
97 | /* | |||
98 | * Query whether there is a sensor of a particular type currently registered. | |||
99 | */ | |||
100 | static bool hasSensor(SensorType type); | |||
101 | ||||
102 | /* | |||
103 | * Mock a value for a particular sensor. | |||
104 | */ | |||
105 | static void setMockValue(SensorType type, float value, bool mockRedundant = false); | |||
106 | ||||
107 | ||||
108 | static void setInvalidMockValue(SensorType type); | |||
109 | ||||
110 | /* | |||
111 | * Reset mock for a particular sensor. | |||
112 | */ | |||
113 | static void resetMockValue(SensorType type); | |||
114 | ||||
115 | /* | |||
116 | * Reset mocking for all sensors. | |||
117 | */ | |||
118 | static void resetAllMocks(); | |||
119 | ||||
120 | /* | |||
121 | * Inhibit sensor timeouts. Used if you're doing something that will block sensor updates, such as | |||
122 | * erasing flash memory (which stalls the CPU on some MCUs) | |||
123 | */ | |||
124 | static void inhibitTimeouts(bool inhibit); | |||
125 | ||||
126 | /* | |||
127 | * Get a friendly name for the sensor. | |||
128 | * For example, CLT, IAT, Throttle Position 2, etc. | |||
129 | */ | |||
130 | 116 | const char* getSensorName() const { return getSensorName(m_type); } | ||
131 | static const char* getSensorName(SensorType type); | |||
132 | ||||
133 | // Retrieve the current reading from the sensor. | |||
134 | // | |||
135 | // Override this in a particular sensor's implementation. As reading sensors is in many hot paths, | |||
136 | // it is unwise to synchronously read the sensor or do anything otherwise costly here. At the most, | |||
137 | // this should be field lookup and simple math. | |||
138 | virtual SensorResult get() const = 0; | |||
139 | ||||
140 | // Retrieve whether the sensor is present. Some sensors may be registered but not present, i.e. if initialization failed. | |||
141 | 619432 | virtual bool hasSensor() const { | ||
142 | 619432 | return true; | ||
143 | } | |||
144 | ||||
145 | /* | |||
146 | * Get an unconverted value from the sensor, if available. | |||
147 | */ | |||
148 | ✗ | virtual float getRaw() const { | ||
149 | ✗ | return 0; | ||
150 | } | |||
151 | ||||
152 | /* | |||
153 | * Get whether this sensor is redundant (backed by multiple other sensors) | |||
154 | */ | |||
155 | ✗ | virtual bool isRedundant() const { | ||
156 | // By default sensors are not redundant | |||
157 | ✗ | return false; | ||
158 | } | |||
159 | ||||
160 | void unregister(); | |||
161 | ||||
162 | 30 | SensorType type() const { | ||
163 | 30 | return m_type; | ||
164 | } | |||
165 | ||||
166 | protected: | |||
167 | // Protected constructor - only subclasses call this | |||
168 | 1522 | explicit Sensor(SensorType type) | ||
169 | 1522 | : m_type(type) {} | ||
170 | ||||
171 | static bool s_inhibitSensorTimeouts; | |||
172 | ||||
173 | private: | |||
174 | const SensorType m_type; | |||
175 | ||||
176 | // Get this sensor's index in the list | |||
177 | 1539 | constexpr size_t getIndex() { | ||
178 | 1539 | return getIndex(m_type); | ||
179 | } | |||
180 | ||||
181 | // Get the index in the list for a sensor of particular type | |||
182 | 52444516 | static constexpr size_t getIndex(SensorType type) { | ||
183 | 52444516 | return static_cast<size_t>(type); | ||
184 | } | |||
185 | ||||
186 | /* | |||
187 | * Static helper for sensor lookup | |||
188 | */ | |||
189 | static SensorRegistryEntry *getEntryForType(SensorType type); | |||
190 | }; | |||
191 | ||||
192 | SensorType findSensorTypeByName(const char *name); | |||
193 |