VL53L0X Sensor and multiple I2C Buses

Hi,

I have a need to use the Wire1 & Wire2 I2C buses on a Teensy 3.5, but I don’t see any way to do that with the current Pololu library. I do see there was a pull request from 3 years ago on this subject, but it apparently never made it into the master repo.

Any idea when/if this is going to happen?

TIA,

Frank

@paynterf - KurtE from PJRC forum,

I made a version of the library which allows this, and put up a Pull Request:

To allow you to specify which wire object to use. Right now playing around with example sketch with 4 of these sensors (Note my are generic ones)…

My test sketch running on T4:

#include <Wire.h>
#include <VL53L0X.h>

typedef enum {SENSE_DEFAULT = 0, SENSE_LONG_RANGE, SENSE_HIGH_SPEED, SENSE_HIGH_ACCURACY} sensorSense_t;
typedef struct {
  VL53L0X *psensor;           // pointer to object
  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
VL53L0X sensor1(&Wire);
VL53L0X sensor2(&Wire);
VL53L0X sensor3(&Wire1);
VL53L0X sensor4(&Wire1);

// Setup for 4 sensors
sensorList_t sensors[] = {
  {&sensor1, 0x30, 0, 1, SENSE_DEFAULT},
  {&sensor2, 0x31, 2, 3, SENSE_DEFAULT},
  {&sensor3, 0x32, 4, 5, SENSE_DEFAULT},
  {&sensor4, 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->init()) {
      sensors[i].psensor->setAddress(sensors[i].id);
      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);
      }
      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) ;
  }
}

void read_sensors() {
  // First use simple function
  for (int i = 0; i < COUNT_SENSORS; i++) {
    uint16_t range_mm = sensors[i].psensor->readRangeSingleMillimeters();
    Serial.print(i, DEC);
    Serial.print(":");
    Serial.print(range_mm, DEC);
    if (sensors[i].psensor->timeoutOccurred()) Serial.print("(TIMEOUT) ");
    else Serial.print("          ");
  }
  Serial.println();
}

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();

}

void loop() {

  read_sensors();
  delay(100);
}

Which appears to be giving me results. Also hooked up to Logic Analyzer

The top 4 lines are are the two Wire busses. The 4 other pins are ones connected up to the GPIO pin, which looks like I am seeing with VL6… Which I then added methods to the Adafruit library to allow me to start up a Range operation and had methods to query to see if done and/or wait for done and then function to get results. Also have version of code that instead of doing SPI to find out if query complete it checks these IO pins. Will probably play with VL5… to do same. Question is in this library or in the Adafruit library?

Hi, Frank.

It seems like quite a few people would like this feature. I’m not sure when we are going to be able to incorporate it, so in the meantime, you could consider using someone’s PR by downloading it from GitHub. For example, you could download @KurtE’s PR from:

https://github.com/pololu/vl53l0x-arduino/archive/9bc65ea7f4cc28d516d470a8cf7a8d99ff18468b.zip

Then you can follow the manual installation instructions in the README file, except use 9bc65ea7f4cc28d516d470a8cf7a8d99ff18468b instead of master. (9bc65ea7f4cc28d516d470a8cf7a8d99ff18468b is the git commit revision for his commit which can be found on the GitHub website.)

Sincerely,
Ryan Mulligan

Looks like there is also other pending Pull Requests with the same or similar changes.

From about 3 years ago:

And a newer one:

Which also appears to maybe add the other functionality I was adding in another branch including the ability to NOT wait for a query to complete, also to be able to check GPIO pin for completion…

Wondering if any of these will be merged in and released? Or should we adapt this additional functionality to other libraries? Example the Adafruit version libraries already support the ability to set which Wire object to use. But there current exported methods are pretty minimal, but they do have full ST library built into the library.

Hi, @KurtE.

Wondering if any of these will be merged in and released? Or should we adapt this additional functionality to other libraries?

Thanks for your contributions and the push to do better with GitHub responses. I’m hoping we can respond to your PR and the others you mention within a few days.

Sincerely,
Ryan Mulligan