Interactions between Wire1 & Wire2 I2C busses on Teensy 3.5?

Status
Not open for further replies.
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...

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);
}
I have not yet implemented nor started testing the continuous mode stuff.
 
Not sure but may start a new thread on this?

But right now playing around some more with the Adafruit library and adding some functionality.

With the test sketch reading 4 sensors, with two on Wire and two on Wire1 (T4 in this case). Note: You are not getting any speed benefit from using the two wire busses as any time we are doing any Inputs our outputs the code is sitting waiting for the transfers to complete.

With the default reading, where I simply call the API one after another in Synchronous mode it looks like:
screenshot.jpg

I have new code now that allows me to start up a range operation without waiting for the operation to complete. SO I startup all 4 and then wait for each GPIO pin to signal that it completed and then do a query. Right now when all of the sensors have nothing in range they all signal in same order as when I started them. What is also interesting is when something is within range it at times takes longer for the sensor to signal completion...

Note: the blue line (second from bottom) I am not showing the third sensor, but instead timing of the operation. As this took up all 8 signals of this LA... Could grab my older 16 channel one, but... good enough for now.

You can see how in this case it may reorder when the ones signal.
screenshot.jpg

What is also interesting is just how much data is being transferred to read in one range operation and reset the interrupt. You can see one of these transfers here:
screenshot2.jpg

Again wondering if some of this can be streamlined, but maybe not worth it.

Anyway just playing around.
 
In case anyone wishes to play around, I have competing Pull Requests to support the VL53L0x sensors, especially when wish to maybe use some different I2C other than Wire object.

I think the main one I am going to continue to try to improve is the Adafruit one: I currently have a Pull Request: https://github.com/adafruit/Adafruit_VL53L0X/pull/43
Where I am trying to extend the Adafruit library to support things like continuous updates and the ability to start a range operation without having to wait.

Probably still lots to fix up. But I also included new example sketch showing the Work In Progress. It is setup to use a table to define how many sensors and how they are configured. My example has 4 sensors, 2 on Wire 2 or Wire1..

I also have one up on the Pololu library: https://github.com/pololu/vl53l0x-arduino/pull/45
Which added support for different Wire objects. Turns out to be the third such PR for similar requests, and that one is simple and ones like it have been sitting there for a couple of years. So not sure how easy it will be to get them to take more extensive changes.

But again if any wishes to play along, that would be great.

Again I think for now I will concentrate on the Adafruit library. I think my example needs some cleanup, plus maybe want to add more to the Adafruit top level library that allows you to have more control over the sensors.

But for now back to playing
 
In case anyone is interested. I did finish this round of hopefully enhancements for the Adafruit VL53L0X sensor library to allow you to get to more of the sensor settings, plus add another API and another optional parameter to begin, that allows you (Hopefully) to configure the sensor in a few of the different ways (like long range, high speed...) that the ST library for this sensor had example programs for.

There are probably lots more that can be done, but until I actually need to use these devices, may not do much more.

The good news is, my update Pull Requests has now been merged in.

Now probably back to other diversions.
 
Status
Not open for further replies.
Back
Top