KurtE
Senior Member+
Glad things are working.
A quick FYI - As I mentioned up on the Pololu forum (and github), I have been hacking up the Adafruit library to extend some of the APIS as well..
My test case is starting to work. Still more things to extend and cleanup.
But the WIP version is up at: https://github.com/KurtE/Adafruit_VL53L0X/tree/extend_apis
Partially converted test case for 4 sensors But easy to extend to however many as just need to add items to table...
I have not yet implemented nor started testing the continuous mode stuff.
A quick FYI - As I mentioned up on the Pololu forum (and github), I have been hacking up the Adafruit library to extend some of the APIS as well..
My test case is starting to work. Still more things to extend and cleanup.
But the WIP version is up at: https://github.com/KurtE/Adafruit_VL53L0X/tree/extend_apis
Partially converted test case for 4 sensors But easy to extend to however many as just need to add items to table...
Code:
#include <Wire.h>
#include <Adafruit_VL53L0X.h>
// Setup mode for doing reads
typedef enum {RUN_MODE_DEFAULT = 1, RUN_MODE_ASYNC, RUN_MODE_GPIO, RUN_MODE_CONT} runmode_t;
runmode_t run_mode = RUN_MODE_DEFAULT;
uint8_t show_command_list = 1;
typedef enum {SENSE_DEFAULT = 0, SENSE_LONG_RANGE, SENSE_HIGH_SPEED, SENSE_HIGH_ACCURACY} sensorSense_t;
typedef struct {
Adafruit_VL53L0X *psensor; // pointer to object
TwoWire *pwire;
int id; // id for the sensor
int shutdown_pin; // which pin for shutdown;
int interrupt_pin; // which pin to use for interrupts.
sensorSense_t init_options; // options for how to use the sensor
} sensorList_t;
// Actual object, could probalby include in structure above
Adafruit_VL53L0X sensor1;
Adafruit_VL53L0X sensor2;
Adafruit_VL53L0X sensor3;
Adafruit_VL53L0X sensor4;
// Setup for 4 sensors
sensorList_t sensors[] = {
{&sensor1, &Wire, 0x30, 0, 1, SENSE_DEFAULT},
{&sensor2, &Wire, 0x31, 2, 3, SENSE_DEFAULT},
{&sensor3, &Wire1, 0x32, 4, 5, SENSE_DEFAULT},
{&sensor4, &Wire1, 0x33, 6, 7, SENSE_DEFAULT}
};
const int COUNT_SENSORS = sizeof(sensors) / sizeof(sensors[0]);
/*
Reset all sensors by setting all of their XSHUT pins low for delay(10), then set all XSHUT high to bring out of reset
Keep sensor #1 awake by keeping XSHUT pin high
Put all other sensors into shutdown by pulling XSHUT pins low
Initialize sensor #1 with lox.begin(new_i2c_address) Pick any number but 0x29 and it must be under 0x7F. Going with 0x30 to 0x3F is probably OK.
Keep sensor #1 awake, and now bring sensor #2 out of reset by setting its XSHUT pin high.
Initialize sensor #2 with lox.begin(new_i2c_address) Pick any number but 0x29 and whatever you set the first sensor to
*/
void Initialize_sensors() {
bool found_any_sensors = false;
// Set all shutdown pins low to shutdown sensors
for (int i = 0; i < COUNT_SENSORS; i++) digitalWrite(sensors[i].shutdown_pin, LOW);
delay(10);
for (int i = 0; i < COUNT_SENSORS; i++) {
// one by one enable sensors and set their ID
digitalWrite(sensors[i].shutdown_pin, HIGH);
delay(10); // give time to wake up.
if (sensors[i].psensor->begin(sensors[i].id, false, sensors[i].pwire)) {
#if 0
switch (sensors[i].init_options) {
case SENSE_DEFAULT:
break;
case SENSE_LONG_RANGE:
// lower the return signal rate limit (default is 0.25 MCPS)
sensors[i].psensor->setSignalRateLimit(0.1);
// increase laser pulse periods (defaults are 14 and 10 PCLKs)
sensors[i].psensor->setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
sensors[i].psensor->setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
break;
case SENSE_HIGH_SPEED:
sensors[i].psensor->setMeasurementTimingBudget(20000);
break;
case SENSE_HIGH_ACCURACY:
// increase timing budget to 200 ms
sensors[i].psensor->setMeasurementTimingBudget(200000);
}
#endif
found_any_sensors = true;
}
else {
Serial.print(i, DEC);
Serial.print(": failed to start\n");
}
}
if (!found_any_sensors) {
Serial.println("No valid sensors found");
while (1) ;
}
}
//====================================================================
// Simple Sync read sensors.
//====================================================================
void read_sensors() {
// First use simple function
uint16_t ranges_mm[COUNT_SENSORS];
bool timeouts[COUNT_SENSORS];
uint32_t stop_times[COUNT_SENSORS];
uint32_t start_time = millis();
for (int i = 0; i < COUNT_SENSORS; i++) {
ranges_mm[i] = sensors[i].psensor->readRange();
timeouts[i] = sensors[i].psensor->timeoutOccurred();
stop_times[i] = millis();
}
uint32_t delta_time = millis() - start_time;
Serial.print(delta_time, DEC);
Serial.print(" ");
for (int i = 0; i < COUNT_SENSORS; i++) {
Serial.print(i, DEC);
Serial.print(":");
Serial.print(ranges_mm[i], DEC);
Serial.print(" ");
Serial.print(stop_times[i] - start_time, DEC);
if (timeouts[i]) Serial.print("(TIMEOUT) ");
else Serial.print(" ");
start_time = stop_times[i];
}
Serial.println();
}
//====================================================================
// ASync read sensors.
//====================================================================
void timed_async_read_sensors() {
// First use simple function
uint16_t ranges_mm[COUNT_SENSORS];
bool timeouts[COUNT_SENSORS];
uint32_t stop_times[COUNT_SENSORS];
uint32_t start_time = millis();
// Tell all sensors to start.
for (int i = 0; i < COUNT_SENSORS; i++) {
ranges_mm[i] = sensors[i].psensor->startRange();
}
// We could call to see if done, but this version the readRange will wait until ready
for (int i = 0; i < COUNT_SENSORS; i++) {
ranges_mm[i] = sensors[i].psensor->readRangeResult();
timeouts[i] = sensors[i].psensor->timeoutOccurred();
stop_times[i] = millis();
}
uint32_t delta_time = millis() - start_time;
Serial.print(delta_time, DEC);
Serial.print(" ");
for (int i = 0; i < COUNT_SENSORS; i++) {
Serial.print(i, DEC);
Serial.print(":");
Serial.print(ranges_mm[i], DEC);
Serial.print(" ");
Serial.print(stop_times[i] - start_time, DEC);
if (timeouts[i]) Serial.print("(TIMEOUT) ");
else Serial.print(" ");
start_time = stop_times[i];
}
Serial.println();
}
//====================================================================
// Setup
//====================================================================
void setup() {
Serial.begin(115200);
Wire.begin();
Wire1.begin();
// wait until serial port opens ... For 5 seconds max
while (! Serial && millis() < 5000) ;
// initialize all of the pins.
Serial.println("VL53LOX_multi start, initialize IO pins");
for (int i = 0; i < COUNT_SENSORS; i++) {
pinMode(sensors[i].shutdown_pin, OUTPUT);
digitalWrite(sensors[i].shutdown_pin, LOW);
if (sensors[i].interrupt_pin >= 0) pinMode(sensors[i].interrupt_pin, INPUT_PULLUP);
}
Serial.println("Starting...");
Initialize_sensors();
}
//====================================================================
// loop
//====================================================================
void loop() {
if (Serial.available()) {
uint8_t ch = Serial.read();
while (Serial.read() != -1) ; // remove the rest
runmode_t prev_run_mode = run_mode;
// See what the user typed in
switch (ch) {
case 'd':
case 'D':
run_mode = RUN_MODE_DEFAULT;
break;
case 'a':
case 'A':
run_mode = RUN_MODE_ASYNC;
break;
#ifdef GPIO_LOX1
case 'g':
case 'G':
run_mode = RUN_MODE_GPIO;
break;
#endif
case 'c':
case 'C':
run_mode = RUN_MODE_CONT;
break;
default:
show_command_list = 1;
run_mode = RUN_MODE_DEFAULT;
}
if (run_mode != prev_run_mode) {
// if previous mode was continuous mode, shut it down
//if (prev_run_mode == RUN_MODE_CONT) stop_continuous_range();
//if (run_mode == RUN_MODE_CONT) start_continuous_range();
}
}
if (show_command_list) {
Serial.println("\nSet run mode by entering one of the following letters");
Serial.println(" D - Default mode");
Serial.println(" A - Asynchronous mode - Try starting all three at once");
Serial.println(" G - Asynchronous mode - Like above use GPIO pins");
Serial.println(" C - Continuous mode - Try starting all three at once");
show_command_list = 0;
}
switch (run_mode) {
case RUN_MODE_DEFAULT:
read_sensors();
break;
case RUN_MODE_ASYNC:
timed_async_read_sensors();
break;
case RUN_MODE_GPIO:
//timed_async_read_gpio();
break;
case RUN_MODE_CONT:
//Process_continuous_range();
break;
}
delay(100);
}