1
+ /* !
2
+ * @file WipperSnapper_I2C_Driver_VL53L4CX.h
3
+ *
4
+ * Device driver for the VL53L4CX ToF 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) 2022 Tyeth Gundry for Adafruit Industries
11
+ *
12
+ * MIT license, all text here must be included in any redistribution.
13
+ *
14
+ */
15
+ #ifndef WipperSnapper_I2C_Driver_VL53L4CX_H
16
+ #define WipperSnapper_I2C_Driver_VL53L4CX_H
17
+
18
+ #include " WipperSnapper_I2C_Driver.h"
19
+ #include < vl53l4cx_class.h>
20
+ #include < vl53l4cx_def.h>
21
+
22
+ /* *************************************************************************/
23
+ /* !
24
+ @brief Class that provides a driver interface for a VL53L4CX sensor.
25
+ */
26
+ /* *************************************************************************/
27
+ class WipperSnapper_I2C_Driver_VL53L4CX : public WipperSnapper_I2C_Driver {
28
+ public:
29
+ /* ******************************************************************************/
30
+ /* !
31
+ @brief Constructor for a VL53L4CX sensor.
32
+ @param i2c
33
+ The I2C interface.
34
+ @param sensorAddress
35
+ 7-bit device address.
36
+ */
37
+ /* ******************************************************************************/
38
+ WipperSnapper_I2C_Driver_VL53L4CX (TwoWire *i2c, uint16_t sensorAddress)
39
+ : WipperSnapper_I2C_Driver(i2c, sensorAddress) {
40
+ _i2c = i2c;
41
+ _sensorAddress = sensorAddress;
42
+ }
43
+
44
+ /* ******************************************************************************/
45
+ /* !
46
+ @brief Destructor for an VL53L4CX sensor.
47
+ */
48
+ /* ******************************************************************************/
49
+ ~WipperSnapper_I2C_Driver_VL53L4CX () {
50
+ // Called when a VL53L4CX component is deleted.
51
+ delete _VL53L4CX;
52
+ }
53
+
54
+ /* *************************************************************************/
55
+ /* !
56
+ @brief Gets a human-readable description of a VL53L4CX status code.
57
+ @param statusCode
58
+ The status code to describe.
59
+ @returns A human-readable description of the status code.
60
+ */
61
+ const char *getVL53L4CXStatusDescription (int statusCode) {
62
+ switch (statusCode) {
63
+ case VL53L4CX_RANGESTATUS_RANGE_VALID:
64
+ return " VL53L4CX_RANGESTATUS_RANGE_VALID" ;
65
+ case VL53L4CX_RANGESTATUS_SIGMA_FAIL:
66
+ return " VL53L4CX_RANGESTATUS_SIGMA_FAIL" ;
67
+ case VL53L4CX_RANGESTATUS_RANGE_VALID_MIN_RANGE_CLIPPED:
68
+ return " VL53L4CX_RANGESTATUS_RANGE_VALID_MIN_RANGE_CLIPPED" ;
69
+ case VL53L4CX_RANGESTATUS_OUTOFBOUNDS_FAIL:
70
+ return " VL53L4CX_RANGESTATUS_OUTOFBOUNDS_FAIL" ;
71
+ case VL53L4CX_RANGESTATUS_HARDWARE_FAIL:
72
+ return " VL53L4CX_RANGESTATUS_HARDWARE_FAIL" ;
73
+ case VL53L4CX_RANGESTATUS_RANGE_VALID_NO_WRAP_CHECK_FAIL:
74
+ return " VL53L4CX_RANGESTATUS_RANGE_VALID_NO_WRAP_CHECK_FAIL" ;
75
+ case VL53L4CX_RANGESTATUS_WRAP_TARGET_FAIL:
76
+ return " VL53L4CX_RANGESTATUS_WRAP_TARGET_FAIL" ;
77
+ case VL53L4CX_RANGESTATUS_PROCESSING_FAIL:
78
+ return " VL53L4CX_RANGESTATUS_PROCESSING_FAIL" ;
79
+ case VL53L4CX_RANGESTATUS_XTALK_SIGNAL_FAIL:
80
+ return " VL53L4CX_RANGESTATUS_XTALK_SIGNAL_FAIL" ;
81
+ case VL53L4CX_RANGESTATUS_SYNCRONISATION_INT:
82
+ return " VL53L4CX_RANGESTATUS_SYNCRONISATION_INT" ;
83
+ case VL53L4CX_RANGESTATUS_RANGE_VALID_MERGED_PULSE:
84
+ return " VL53L4CX_RANGESTATUS_RANGE_VALID_MERGED_PULSE" ;
85
+ case VL53L4CX_RANGESTATUS_TARGET_PRESENT_LACK_OF_SIGNAL:
86
+ return " VL53L4CX_RANGESTATUS_TARGET_PRESENT_LACK_OF_SIGNAL" ;
87
+ case VL53L4CX_RANGESTATUS_MIN_RANGE_FAIL:
88
+ return " VL53L4CX_RANGESTATUS_MIN_RANGE_FAIL" ;
89
+ case VL53L4CX_RANGESTATUS_RANGE_INVALID:
90
+ return " VL53L4CX_RANGESTATUS_RANGE_INVALID" ;
91
+ case VL53L4CX_RANGESTATUS_NONE:
92
+ return " VL53L4CX_RANGESTATUS_NONE" ;
93
+ default :
94
+ return ((" UNKNOWN STATUS: " ) + String (statusCode)).c_str ();
95
+ }
96
+ }
97
+
98
+ /* ******************************************************************************/
99
+ /* !
100
+ @brief Initializes the VL53L4CX sensor and begins I2C.
101
+ @returns True if initialized successfully, False otherwise.
102
+ */
103
+ /* ******************************************************************************/
104
+ bool begin () {
105
+ _VL53L4CX = new VL53L4CX (_i2c, -1 );
106
+
107
+ /* Reinstate if shutdown pin utilised
108
+ * // Configure VL53L4CX satellite component.
109
+ * _VL53L4CX->begin();
110
+ *
111
+ * // Switch off VL53L4CX satellite component.
112
+ * _VL53L4CX->VL53L4CX_Off();
113
+ */
114
+
115
+ if (_VL53L4CX->InitSensor ((uint8_t )_sensorAddress) != VL53L4CX_ERROR_NONE) {
116
+ WS_DEBUG_PRINTLN (" Failed to initialize VL53L4CX sensor!" );
117
+ return false ;
118
+ }
119
+ // // Program the highest possible TimingBudget, no interval time
120
+ // if (_VL53L4CX-> VL53L4CX_SetRangeTiming(200, 0) != VL53L4CX_ERROR_NONE) {
121
+ // WS_DEBUG_PRINTLN("Failed to set VL53L4CX timing!");
122
+ // return false;
123
+ // }
124
+
125
+ // uint16_t signalThreshold = -1;
126
+ // if (_VL53L4CX->VL53L4CX_GetSignalThreshold(&signalThreshold) !=
127
+ // VL53L4CX_ERROR_NONE) {
128
+ // WS_DEBUG_PRINTLN("Failed to get VL53L4CX signal threshold!");
129
+ // } else {
130
+ // WS_DEBUG_PRINT("VL53L4CX old signal threshold: ");
131
+ // WS_DEBUG_PRINTLN(signalThreshold);
132
+ // }
133
+ // if (_VL53L4CX->VL53L4CX_SetSignalThreshold(50) != VL53L4CX_ERROR_NONE) {
134
+ // WS_DEBUG_PRINTLN("Failed to set VL53L4CX signal threshold!");
135
+ // } else {
136
+ // WS_DEBUG_PRINT("VL53L4CX new signal threshold: ");
137
+ // WS_DEBUG_PRINTLN(8);
138
+ // }
139
+
140
+ // uint16_t sigmaThreshold = -1;
141
+ // if (_VL53L4CX->VL53L4CX_GetSigmaThreshold(&sigmaThreshold) !=
142
+ // VL53L4CX_ERROR_NONE) {
143
+ // WS_DEBUG_PRINTLN("Failed to get VL53L4CX sigma threshold!");
144
+ // } else {
145
+ // WS_DEBUG_PRINT("VL53L4CX old sigma threshold: ");
146
+ // WS_DEBUG_PRINTLN(sigmaThreshold);
147
+ // }
148
+ // if (_VL53L4CX->VL53L4CX_SetSigmaThreshold(100) != VL53L4CX_ERROR_NONE) {
149
+ // WS_DEBUG_PRINTLN("Failed to set VL53L4CX sigma threshold!");
150
+ // } else {
151
+ // WS_DEBUG_PRINT("VL53L4CX new sigma threshold: ");
152
+ // WS_DEBUG_PRINTLN(100);
153
+ // }
154
+
155
+ if (_VL53L4CX->VL53L4CX_StartMeasurement () != VL53L4CX_ERROR_NONE) {
156
+ WS_DEBUG_PRINTLN (" Failed to start VL53L4CX ranging!" );
157
+ return false ;
158
+ }
159
+ return true ;
160
+ }
161
+
162
+ /* ******************************************************************************/
163
+ /* !
164
+ @brief Gets the VL53L4CX's current proximity for first object if found.
165
+ @param proximityEvent
166
+ Pointer to an Adafruit_Sensor event.
167
+ @returns True if the proximity was obtained successfully, False
168
+ otherwise.
169
+ */
170
+ /* ******************************************************************************/
171
+ bool getEventProximity (sensors_event_t *proximityEvent) {
172
+ return getProximity (proximityEvent, 0 );
173
+ }
174
+
175
+
176
+ /* ******************************************************************************/
177
+ /* !
178
+ @brief Gets the VL53L4CX's current proximity for second object if found.
179
+ @param proximityEvent
180
+ Pointer to an Adafruit_Sensor event.
181
+ @returns True if the proximity was obtained successfully, False
182
+ otherwise.
183
+ */
184
+ /* ******************************************************************************/
185
+ bool getEventRaw (sensors_event_t *proximityEvent) {
186
+ return getProximity (proximityEvent, 1 );
187
+ }
188
+
189
+
190
+ /* ******************************************************************************/
191
+ /* !
192
+ @brief Gets the VL53L4CX's current proximity (first or second object).
193
+ @param proximityEvent
194
+ Pointer to an Adafruit_Sensor event.
195
+ @param index
196
+ Index of the proximity to get (0 or 1).
197
+ @returns True if the proximity was obtained successfully, False
198
+ otherwise.
199
+ */
200
+ /* ******************************************************************************/
201
+ bool getProximity (sensors_event_t *proximityEvent, int index = 0 ) {
202
+ VL53L4CX_MultiRangingData_t MultiRangingData;
203
+ VL53L4CX_MultiRangingData_t *pMultiRangingData = &MultiRangingData;
204
+ uint8_t NewDataReady = 0 ;
205
+ int no_of_object_found = 0 ;
206
+ int j = 0 ;
207
+ int status;
208
+ // Start fresh reading, seemed to be accepting stale value
209
+ status = _VL53L4CX->VL53L4CX_ClearInterruptAndStartMeasurement ();
210
+ WS_DEBUG_PRINT (" Waiting for VL53L4CX data ready..." );
211
+ delay (250 );
212
+
213
+ for (uint8_t i = 0 ;
214
+ (status = _VL53L4CX->VL53L4CX_GetMeasurementDataReady (&NewDataReady)) &&
215
+ !NewDataReady && i < 3 ;
216
+ i++)
217
+ {
218
+ delay (300 );
219
+ WS_DEBUG_PRINT (" ." );
220
+ }
221
+ WS_DEBUG_PRINTLN (" " );
222
+ if ((status == VL53L4CX_ERROR_NONE) && (NewDataReady != 0 )) {
223
+ status = _VL53L4CX->VL53L4CX_GetMultiRangingData (pMultiRangingData);
224
+ no_of_object_found = pMultiRangingData->NumberOfObjectsFound ;
225
+
226
+ for (j = 0 ; j < no_of_object_found; j++) {
227
+ if (pMultiRangingData->RangeData [j].RangeStatus == VL53L4CX_RANGESTATUS_RANGE_VALID ||
228
+ pMultiRangingData->RangeData [j].RangeStatus == VL53L4CX_RANGESTATUS_RANGE_VALID_MERGED_PULSE) {
229
+ int16_t mm = pMultiRangingData->RangeData [j].RangeMilliMeter ;
230
+ if (j == index) {
231
+ proximityEvent->data [0 ] = (float )mm;
232
+ return true ;
233
+ }
234
+ }
235
+ }
236
+ // TODO: Once I2C sensors fire all data points during a single call, we
237
+ // can return both distances and other metrics like the std deviation
238
+ } else {
239
+ WS_DEBUG_PRINTLN (" VL53L4CX Error: " + String (getVL53L4CXStatusDescription (status)));
240
+ }
241
+ return false ;
242
+ }
243
+
244
+ protected:
245
+ VL53L4CX *_VL53L4CX = nullptr ; // /< Pointer to VL53L4CX temperature sensor object
246
+ };
247
+
248
+ #endif // WipperSnapper_I2C_Driver_VL53L4CX
0 commit comments