Skip to content

Commit 7f81e4f

Browse files
authored
Merge pull request #19 from KurtE/continuous_range
Add continuous range support also updated example sketch
2 parents eabe639 + fc64f01 commit 7f81e4f

File tree

4 files changed

+245
-11
lines changed

4 files changed

+245
-11
lines changed

Adafruit_VL6180X.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
#include "Arduino.h"
3131
#include <Wire.h>
3232

33+
// Define some additional registers mentioned in application notes and we use
34+
///! period between each measurement when in continuous mode
35+
#define SYSRANGE__INTERMEASUREMENT_PERIOD 0x001b // P19 application notes
36+
3337
/**************************************************************************/
3438
/*!
3539
@brief Instantiates a new VL6180X class
@@ -150,7 +154,8 @@ void Adafruit_VL6180X::loadSettings(void) {
150154
// of the ranging sensor
151155

152156
// Optional: Public registers - See data sheet for more detail
153-
write8(0x001b, 0x09); // Set default ranging inter-measurement
157+
write8(SYSRANGE__INTERMEASUREMENT_PERIOD,
158+
0x09); // Set default ranging inter-measurement
154159
// period to 100ms
155160
write8(0x003e, 0x31); // Set default ALS inter-measurement period
156161
// to 500ms
@@ -261,6 +266,41 @@ uint8_t Adafruit_VL6180X::readRangeResult(void) {
261266
return range;
262267
}
263268

269+
/**************************************************************************/
270+
/*!
271+
@brief Start continuous ranging
272+
@param period_ms Optional Period between ranges in ms. Values will
273+
be rounded down to 10ms units with minimum of 10ms. Default is 50
274+
*/
275+
/**************************************************************************/
276+
277+
void Adafruit_VL6180X::startRangeContinuous(uint16_t period_ms) {
278+
uint8_t period_reg = 0;
279+
if (period_ms > 10) {
280+
if (period_ms < 2550)
281+
period_reg = (period_ms / 10) - 1;
282+
else
283+
period_reg = 254;
284+
}
285+
// Set ranging inter-measurement
286+
write8(SYSRANGE__INTERMEASUREMENT_PERIOD, period_reg);
287+
288+
// Start a continuous range measurement
289+
write8(VL6180X_REG_SYSRANGE_START, 0x03);
290+
}
291+
292+
/**************************************************************************/
293+
/*!
294+
@brief stop continuous range operation.
295+
*/
296+
/**************************************************************************/
297+
298+
void Adafruit_VL6180X::stopRangeContinuous(void) {
299+
// stop the continuous range operation, by setting the range register
300+
// back to 1, Page 7 of appication notes
301+
write8(VL6180X_REG_SYSRANGE_START, 0x01);
302+
}
303+
264304
/**************************************************************************/
265305
/*!
266306
@brief Request ranging success/error message (retreive after ranging)

Adafruit_VL6180X.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ class Adafruit_VL6180X {
9292
boolean waitRangeComplete(void);
9393
uint8_t readRangeResult(void);
9494

95+
void startRangeContinuous(uint16_t period_ms = 50);
96+
void stopRangeContinuous(void);
97+
// readRangeResult and isRangeComplete apply here is well
98+
9599
private:
96100
void loadSettings(void);
97101

examples/vl6180x_triple/vl6180x_triple.ino

Lines changed: 198 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,37 @@
1010
#define SHT_LOX2 6
1111
#define SHT_LOX3 5
1212

13+
// Optional define GPIO pins to check to see if complete
14+
#define GPIO_LOX1 4
15+
#define GPIO_LOX2 3
16+
#define GPIO_LOX3 2
17+
18+
#define TIMING_PIN 13
19+
1320
// objects for the VL6180X
1421
Adafruit_VL6180X lox1 = Adafruit_VL6180X();
1522
Adafruit_VL6180X lox2 = Adafruit_VL6180X();
1623
Adafruit_VL6180X lox3 = Adafruit_VL6180X();
1724

1825
// Setup mode for doing reads
19-
typedef enum {RUN_MODE_DEFAULT, RUN_MODE_TIMED, RUN_MODE_ASYNC} runmode_t;
26+
typedef enum {RUN_MODE_DEFAULT, RUN_MODE_TIMED, RUN_MODE_ASYNC, RUN_MODE_GPIO, RUN_MODE_CONT} runmode_t;
2027

2128
runmode_t run_mode = RUN_MODE_DEFAULT;
29+
uint8_t show_command_list = 1;
30+
31+
//==========================================================================
32+
// Define some globals used in the continuous range mode
33+
// Note: going to start table drive this part, may back up and do the rest later
34+
Adafruit_VL6180X *sensors[] = {&lox1, &lox2, &lox3};
35+
const uint8_t COUNT_SENSORS = sizeof(sensors) / sizeof(sensors[0]);
36+
const int sensor_gpios[COUNT_SENSORS] = {GPIO_LOX1, GPIO_LOX2, GPIO_LOX3}; // if any are < 0 will poll instead
37+
38+
uint8_t sensor_ranges[COUNT_SENSORS];
39+
uint8_t sensor_status[COUNT_SENSORS];
40+
// Could do with uint8_t for 8 sensors, but just in case...
41+
const uint16_t ALL_SENSORS_PENDING = ((1 << COUNT_SENSORS) - 1);
42+
uint16_t sensors_pending = ALL_SENSORS_PENDING;
43+
uint32_t sensor_last_cycle_time;
2244

2345

2446
/*
@@ -130,6 +152,7 @@ void read_sensors() {
130152
}
131153

132154
void timed_read_sensors() {
155+
digitalWrite(TIMING_PIN, HIGH);
133156
uint32_t start_time = millis();
134157
uint8_t range_lox1 = lox1.readRange();
135158
uint8_t status_lox1 = lox1.readRangeStatus();
@@ -138,6 +161,7 @@ void timed_read_sensors() {
138161
uint8_t range_lox3 = lox3.readRange();
139162
uint8_t status_lox3 = lox3.readRangeStatus();
140163
uint32_t delta_time = millis() - start_time;
164+
digitalWrite(TIMING_PIN, LOW);
141165
Serial.print(delta_time, DEC);
142166
Serial.print(" : ");
143167
if (status_lox1 == VL6180X_ERROR_NONE) Serial.print(range_lox1, DEC);
@@ -153,25 +177,27 @@ void timed_read_sensors() {
153177
}
154178

155179
void timed_async_read_sensors() {
180+
digitalWrite(TIMING_PIN, HIGH);
156181
uint32_t start_time = millis();
157182

158183
// lets start up all three
159184
lox1.startRange();
160185
lox2.startRange();
161186
lox3.startRange();
162-
187+
163188
// wait for each of them to complete
164189
lox1.waitRangeComplete();
165190
lox2.waitRangeComplete();
166191
lox3.waitRangeComplete();
167-
192+
168193
uint8_t range_lox1 = lox1.readRangeResult();
169194
uint8_t status_lox1 = lox1.readRangeStatus();
170195
uint8_t range_lox2 = lox2.readRangeResult();
171196
uint8_t status_lox2 = lox2.readRangeStatus();
172197
uint8_t range_lox3 = lox3.readRangeResult();
173198
uint8_t status_lox3 = lox3.readRangeStatus();
174199
uint32_t delta_time = millis() - start_time;
200+
digitalWrite(TIMING_PIN, LOW);
175201
Serial.print(delta_time, DEC);
176202
Serial.print(" : ");
177203
if (status_lox1 == VL6180X_ERROR_NONE) Serial.print(range_lox1, DEC);
@@ -184,10 +210,130 @@ void timed_async_read_sensors() {
184210
else Serial.print("###");
185211

186212
Serial.println();
187-
213+
214+
}
215+
216+
void timed_async_read_gpio() {
217+
#ifdef GPIO_LOX1
218+
uint8_t range_lox1 = 0;
219+
uint8_t status_lox1 = VL6180X_ERROR_NONE;
220+
uint8_t range_lox2 = 0;
221+
uint8_t status_lox2 = VL6180X_ERROR_NONE;
222+
uint8_t range_lox3 = 0;
223+
uint8_t status_lox3 = VL6180X_ERROR_NONE;
224+
225+
226+
digitalWrite(TIMING_PIN, HIGH);
227+
uint8_t pending_sensors = 0x7;
228+
uint32_t start_time = millis();
229+
230+
// lets start up all three
231+
lox1.startRange();
232+
lox2.startRange();
233+
lox3.startRange();
234+
235+
while (pending_sensors && ((millis() - start_time) < 1000)) {
236+
if ((pending_sensors & 0x1) && !digitalRead(GPIO_LOX1)) {
237+
range_lox1 = lox1.readRangeResult();
238+
status_lox1 = lox1.readRangeStatus();
239+
pending_sensors ^= 0x1;
240+
}
241+
if ((pending_sensors & 0x2) && !digitalRead(GPIO_LOX2)) {
242+
range_lox2 = lox2.readRangeResult();
243+
status_lox2 = lox2.readRangeStatus();
244+
pending_sensors ^= 0x2;
245+
}
246+
if ((pending_sensors & 0x4) && !digitalRead(GPIO_LOX3)) {
247+
range_lox3 = lox3.readRangeResult();
248+
status_lox3 = lox3.readRangeStatus();
249+
pending_sensors ^= 0x4;
250+
}
251+
}
252+
uint32_t delta_time = millis() - start_time;
253+
digitalWrite(TIMING_PIN, LOW);
254+
Serial.print(delta_time, DEC);
255+
Serial.print("(");
256+
Serial.print(pending_sensors, DEC);
257+
Serial.print(") : ");
258+
if (status_lox1 == VL6180X_ERROR_NONE) Serial.print(range_lox1, DEC);
259+
else Serial.print("###");
260+
Serial.print(" : ");
261+
if (status_lox2 == VL6180X_ERROR_NONE) Serial.print(range_lox2, DEC);
262+
else Serial.print("###");
263+
Serial.print(" : ");
264+
if (status_lox3 == VL6180X_ERROR_NONE) Serial.print(range_lox3, DEC);
265+
else Serial.print("###");
266+
267+
Serial.println();
268+
#endif
269+
}
270+
271+
//===============================================================
272+
// Continuous range test code
273+
//===============================================================
274+
void start_continuous_range() {
275+
Serial.println("start Continuous range mode");
276+
for (uint8_t i = 0; i < COUNT_SENSORS; i++) {
277+
sensors[i]->startRangeContinuous();
278+
}
279+
sensors_pending = ALL_SENSORS_PENDING;
280+
sensor_last_cycle_time = millis();
188281
}
189282

283+
void stop_continuous_range() {
284+
Serial.println("Stop Continuous range mode");
285+
for (uint8_t i = 0; i < COUNT_SENSORS; i++) {
286+
sensors[i]->stopRangeContinuous();
287+
}
288+
delay(100); // give time for it to complete.
289+
}
290+
291+
292+
void Process_continuous_range() {
293+
294+
uint16_t mask = 1;
295+
for (uint8_t i = 0; i < COUNT_SENSORS; i++) {
296+
bool range_complete = false;
297+
if (sensors_pending & mask) {
298+
if (sensor_gpios[i] >= 0)
299+
range_complete = !digitalRead(sensor_gpios[i]);
300+
else
301+
range_complete = sensors[i]->isRangeComplete();
302+
if (range_complete) {
303+
sensor_ranges[i] = sensors[i]->readRangeResult();
304+
sensor_status[i] = sensors[i]->readRangeStatus();
305+
sensors_pending ^= mask;
306+
}
307+
}
308+
mask <<= 1; // setup to test next one
309+
}
310+
// See if we have all of our sensors read OK
311+
uint32_t delta_time = millis() - sensor_last_cycle_time;
312+
if (!sensors_pending || (delta_time > 1000)) {
313+
Serial.print(delta_time, DEC);
314+
Serial.print("(");
315+
Serial.print(sensors_pending, HEX);
316+
Serial.print(")");
317+
mask = 1;
318+
for (uint8_t i = 0; i < COUNT_SENSORS; i++) {
319+
Serial.print(" : ");
320+
if (sensors_pending & mask) Serial.print("TTT"); // show timeout in this one
321+
else if (sensor_status[i] == VL6180X_ERROR_NONE) Serial.print(sensor_ranges[i], DEC);
322+
else {
323+
Serial.print("#");
324+
Serial.print(sensor_status[i], DEC);
325+
}
326+
}
327+
// setup for next pass
328+
Serial.println();
329+
sensor_last_cycle_time = millis();
330+
sensors_pending = ALL_SENSORS_PENDING;
331+
}
332+
}
190333

334+
//===============================================================
335+
// Setup
336+
//===============================================================
191337
void setup() {
192338
Serial.begin(115200);
193339

@@ -200,12 +346,22 @@ void setup() {
200346
pinMode(SHT_LOX2, OUTPUT);
201347
pinMode(SHT_LOX3, OUTPUT);
202348

349+
// Enable timing pin so easy to see when pass starts and ends
350+
pinMode(TIMING_PIN, OUTPUT);
351+
352+
#ifdef GPIO_LOX1
353+
// If we defined GPIO pins, enable them as PULL UP
354+
pinMode(GPIO_LOX1, INPUT_PULLUP);
355+
pinMode(GPIO_LOX2, INPUT_PULLUP);
356+
pinMode(GPIO_LOX3, INPUT_PULLUP);
357+
#endif
358+
203359
Serial.println("Shutdown pins inited...");
204360

205361
digitalWrite(SHT_LOX1, LOW);
206362
digitalWrite(SHT_LOX2, LOW);
207363
digitalWrite(SHT_LOX3, LOW);
208-
364+
digitalWrite(TIMING_PIN, LOW);
209365
Serial.println("All in reset mode...(pins are low)");
210366

211367

@@ -214,11 +370,14 @@ void setup() {
214370

215371
}
216372

373+
//===============================================================
374+
// Loop
375+
//===============================================================
217376
void loop() {
218377
if (Serial.available()) {
219378
uint8_t ch = Serial.read();
220379
while (Serial.read() != -1) ; // remove the rest
221-
380+
runmode_t prev_run_mode = run_mode;
222381
// See what the user typed in
223382
switch (ch) {
224383
case 'd':
@@ -233,13 +392,37 @@ void loop() {
233392
case 'A':
234393
run_mode = RUN_MODE_ASYNC;
235394
break;
395+
#ifdef GPIO_LOX1
396+
case 'g':
397+
case 'G':
398+
run_mode = RUN_MODE_GPIO;
399+
break;
400+
#endif
401+
case 'c':
402+
case 'C':
403+
run_mode = RUN_MODE_CONT;
404+
break;
405+
236406
default:
237-
Serial.println("\nSet run mode by entering one of the following letters");
238-
Serial.println(" D - Default mode");
239-
Serial.println(" T - Timed mode - Reads done one after another");
240-
Serial.println(" A - Asynchronous mode - Try starting all three at once");
407+
show_command_list = 1;
241408
run_mode = RUN_MODE_DEFAULT;
242409
}
410+
if (run_mode != prev_run_mode) {
411+
// if previous mode was continuous mode, shut it down
412+
if (prev_run_mode == RUN_MODE_CONT) stop_continuous_range();
413+
if (run_mode == RUN_MODE_CONT) start_continuous_range();
414+
}
415+
}
416+
if (show_command_list) {
417+
Serial.println("\nSet run mode by entering one of the following letters");
418+
Serial.println(" D - Default mode");
419+
Serial.println(" T - Timed mode - Reads done one after another");
420+
Serial.println(" A - Asynchronous mode - Try starting all three at once");
421+
#ifdef GPIO_LOX1
422+
Serial.println(" G - Asynchronous mode - Like above use GPIO pins");
423+
#endif
424+
Serial.println(" C - Continuous mode - Try starting all three at once");
425+
show_command_list = 0;
243426
}
244427
switch (run_mode) {
245428
case RUN_MODE_DEFAULT:
@@ -251,6 +434,11 @@ void loop() {
251434
case RUN_MODE_ASYNC:
252435
timed_async_read_sensors();
253436
break;
437+
case RUN_MODE_GPIO:
438+
timed_async_read_gpio();
439+
break;
440+
case RUN_MODE_CONT:
441+
Process_continuous_range();
254442
}
255443
delay(100);
256444
}

keywords.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ startRange KEYWORD2
99
isRangeComplete KEYWORD2
1010
waitRangeComplete KEYWORD2
1111
readRangeResult KEYWORD2
12+
startRangeContinuous KEYWORD2
13+
stopRangeContinuous KEYWORD2

0 commit comments

Comments
 (0)