1
+ /* !
2
+ * @file drvMlx90632.h
3
+ *
4
+ * Device driver for the Melexis MLX90632 Far Infrared temp sensor
5
+ *
6
+ * Adafruit invests time and resources providing this open source code,
7
+ * please support Adafruit and open-source hardware by purchasing
8
+ * products from Adafruit!
9
+ *
10
+ * Copyright (c) Tyeth Gundry 2025 for Adafruit Industries.
11
+ *
12
+ * MIT license, all text here must be included in any redistribution.
13
+ *
14
+ */
15
+ #ifndef DRV_MLX90632_H
16
+ #define DRV_MLX90632_H
17
+
18
+ #include " drvBase.h"
19
+ #include < Adafruit_MLX90632.h>
20
+
21
+ /* !
22
+ @brief Class that provides a driver interface for an MLX90632 sensor.
23
+ */
24
+ class drvMLX90632 : public drvBase {
25
+ public:
26
+ /* ******************************************************************************/
27
+ /* !
28
+ @brief Constructor for an MLX90632 sensor.
29
+ @param i2c
30
+ The I2C interface.
31
+ @param sensorAddress
32
+ The 7-bit I2C address of the sensor.
33
+ @param mux_channel
34
+ The I2C multiplexer channel.
35
+ @param driver_name
36
+ The name of the driver.
37
+ */
38
+ /* ******************************************************************************/
39
+ drvMLX90632 (TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel,
40
+ const char *driver_name)
41
+ : drvBase(i2c, sensorAddress, mux_channel, driver_name) {
42
+ _mlx90632 = nullptr ;
43
+ _deviceTemp = NAN;
44
+ _objectTemp = NAN;
45
+ _lastRead = 0 ;
46
+ }
47
+
48
+ /* ******************************************************************************/
49
+ /* !
50
+ @brief Destructor for an MLX90632 sensor.
51
+ */
52
+ /* ******************************************************************************/
53
+ ~drvMLX90632 () {
54
+ if (_mlx90632) {
55
+ delete _mlx90632;
56
+ _mlx90632 = nullptr ;
57
+ }
58
+ }
59
+
60
+ /* ******************************************************************************/
61
+ /* !
62
+ @brief Initializes the MLX90632 sensor and begins I2C.
63
+ @returns True if initialized successfully, False otherwise.
64
+ */
65
+ /* ******************************************************************************/
66
+ bool begin () override {
67
+ if (_mlx90632) {
68
+ delete _mlx90632;
69
+ _mlx90632 = nullptr ;
70
+ }
71
+ _mlx90632 = new Adafruit_MLX90632 ();
72
+ if (!_mlx90632->begin (_address, _i2c)) {
73
+ return false ;
74
+ }
75
+
76
+ return ConfigureAndPrintSensorInfo ();
77
+ }
78
+
79
+ /* ******************************************************************************/
80
+ /* !
81
+ @brief Configures the MLX90632 sensor and prints its information.
82
+ @param extendedInsteadOfMedicalRange
83
+ If true, configures the sensor for extended temperature
84
+ range/acc.
85
+ @returns True if configuration fetching and setting were successful.
86
+ */
87
+ /* ******************************************************************************/
88
+ bool ConfigureAndPrintSensorInfo (bool extendedInsteadOfMedicalRange = false ) {
89
+ // Reset the device
90
+ if (!_mlx90632->reset ()) {
91
+ WS_DEBUG_PRINTLN (F (" Device reset failed" ));
92
+ return false ;
93
+ }
94
+
95
+ uint16_t productCode = _mlx90632->getProductCode ();
96
+ // Decode product code bits
97
+ uint8_t accuracy = productCode & 0x1F ;
98
+
99
+ if (!_mlx90632->setMode (MLX90632_MODE_CONTINUOUS)) {
100
+ WS_DEBUG_PRINTLN (F (" Failed to set mode" ));
101
+ return false ;
102
+ }
103
+
104
+ // set accuracy mode based on medical if detected
105
+ if (accuracy == 1 ) {
106
+ // Set and get measurement select (medical)
107
+ if (!extendedInsteadOfMedicalRange &&
108
+ !_mlx90632->setMeasurementSelect (MLX90632_MEAS_MEDICAL)) {
109
+ WS_DEBUG_PRINTLN (F (" Failed to set measurement select to Medical" ));
110
+ return false ;
111
+ } else if (extendedInsteadOfMedicalRange &&
112
+ !_mlx90632->setMeasurementSelect (
113
+ MLX90632_MEAS_EXTENDED_RANGE)) {
114
+ WS_DEBUG_PRINTLN (
115
+ F (" Failed to set measurement select to Extended Range" ));
116
+ return false ;
117
+ }
118
+ }
119
+
120
+ // Set and get refresh rate (default to 2Hz)
121
+ if (!_mlx90632->setRefreshRate (MLX90632_REFRESH_2HZ)) {
122
+ WS_DEBUG_PRINTLN (F (" Failed to set refresh rate to 2Hz" ));
123
+ return false ;
124
+ }
125
+
126
+ if (!_mlx90632->resetNewData ()) {
127
+ WS_DEBUG_PRINTLN (F (" Failed to reset new data flag" ));
128
+ return false ;
129
+ }
130
+ return true ;
131
+ }
132
+
133
+ /* ******************************************************************************/
134
+ /* !
135
+ @brief Checks if sensor was read within last 1s, or is the first read.
136
+ @returns True if the sensor was recently read, False otherwise.
137
+ */
138
+ /* ******************************************************************************/
139
+ bool HasBeenReadInLast200ms () {
140
+ return _lastRead != 0 && millis () - _lastRead < 200 ;
141
+ }
142
+
143
+ /* ******************************************************************************/
144
+ /* !
145
+ @brief Reads the sensor.
146
+ @returns True if the sensor was read successfully, False otherwise.
147
+ */
148
+ /* ******************************************************************************/
149
+ bool ReadSensorData () {
150
+ bool result = false ;
151
+ if (HasBeenReadInLast200ms ()) {
152
+ WS_DEBUG_PRINTLN (F (" Sensor was read recently, using cached data" ));
153
+ return true ;
154
+ }
155
+
156
+ // Check if we need to trigger a new measurement for step modes
157
+ mlx90632_mode_t currentMode = _mlx90632->getMode ();
158
+ if (currentMode == MLX90632_MODE_STEP ||
159
+ currentMode == MLX90632_MODE_SLEEPING_STEP) {
160
+ // Trigger single measurement (SOC bit) for step modes
161
+ if (!_mlx90632->startSingleMeasurement ()) {
162
+ WS_DEBUG_PRINTLN (F (" Failed to start single measurement" ));
163
+ return false ;
164
+ }
165
+ delay (510 ); // Wait for measurement to complete @ 2Hz
166
+ }
167
+
168
+ // Only check new data flag - much more efficient for continuous mode
169
+ if (_mlx90632->isNewData ()) {
170
+ _deviceTemp = _mlx90632->getAmbientTemperature ();
171
+ _objectTemp = _mlx90632->getObjectTemperature ();
172
+ if (isnan (_objectTemp)) {
173
+ WS_DEBUG_PRINTLN (F (" NaN (invalid cycle position)" ));
174
+ return false ;
175
+ }
176
+ result = true ;
177
+ _lastRead = millis ();
178
+ // Reset new data flag after reading
179
+ if (!_mlx90632->resetNewData ()) {
180
+ WS_DEBUG_PRINTLN (F (" Failed to reset new data flag" ));
181
+ }
182
+ } else {
183
+ WS_DEBUG_PRINTLN (F (" No new data available, skipping read" ));
184
+ }
185
+
186
+ return result;
187
+ }
188
+
189
+ /* ******************************************************************************/
190
+ /* !
191
+ @brief Gets the MLX90632's current temperature.
192
+ @param tempEvent
193
+ Pointer to an Adafruit_Sensor event.
194
+ @returns True if the temperature was obtained successfully, False
195
+ otherwise.
196
+ */
197
+ /* ******************************************************************************/
198
+ bool getEventAmbientTemp (sensors_event_t *tempEvent) {
199
+ if (ReadSensorData () && _deviceTemp != NAN) {
200
+ tempEvent->temperature = _deviceTemp;
201
+ return true ;
202
+ }
203
+ return false ; // sensor not read recently, return false
204
+ }
205
+
206
+ /* ******************************************************************************/
207
+ /* !
208
+ @brief Gets the MLX90632's object temperature.
209
+ @param tempEvent
210
+ Pointer to an Adafruit_Sensor event.
211
+ @returns True if the temperature was obtained successfully, False
212
+ otherwise.
213
+ */
214
+ /* ******************************************************************************/
215
+ bool getEventObjectTemp (sensors_event_t *tempEvent) {
216
+ if (ReadSensorData () && _objectTemp != NAN) {
217
+ tempEvent->temperature = _objectTemp;
218
+ return true ;
219
+ }
220
+ return false ; // sensor not read recently, return false
221
+ }
222
+
223
+ void ConfigureDefaultSensorTypes () override {
224
+ _default_sensor_types_count = 4 ;
225
+ _default_sensor_types[0 ] =
226
+ wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE;
227
+ _default_sensor_types[1 ] =
228
+ wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE;
229
+ _default_sensor_types[2 ] =
230
+ wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT;
231
+ _default_sensor_types[3 ] =
232
+ wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE_FAHRENHEIT;
233
+ }
234
+
235
+ protected:
236
+ double _deviceTemp; // /< Device temperature in Celsius
237
+ double _objectTemp; // /< Object temperature in Celsius
238
+ uint32_t _lastRead; // /< Last time the sensor was read in milliseconds
239
+ Adafruit_MLX90632 *_mlx90632; // /< Pointer to MLX90632 sensor object
240
+ };
241
+
242
+ #endif // drvMLX90632
0 commit comments