Forum Rule: Always post complete source code & details to reproduce any issue!
Page 2 of 2 FirstFirst 1 2
Results 26 to 27 of 27

Thread: Interactions between Wire1 & Wire2 I2C busses on Teensy 3.5?

  1. #26
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,106
    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_VL...ee/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.

  2. #27
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,106
    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:
    Click image for larger version. 

Name:	screenshot.jpg 
Views:	2 
Size:	64.5 KB 
ID:	21277

    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.
    Click image for larger version. 

Name:	screenshot.jpg 
Views:	2 
Size:	59.5 KB 
ID:	21280

    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:
    Click image for larger version. 

Name:	screenshot2.jpg 
Views:	2 
Size:	41.2 KB 
ID:	21281

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

    Anyway just playing around.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •