Arduino <Wire.h> Now supports Wire1, Wire2 & Wire3?

Status
Not open for further replies.

paynterf

Well-known member
In another post I described my idea for managing an array of VL53L0X ToF sensors using one of the secondary I2C buses available on T3.x devices.

However, that meant I had to once again run the gauntlet of the Wire library's lack of Wire1/Wire2/Wire3 support. After struggling unsuccessfully to modify the Adafruit VL53L0X library (Adafruit_VL53L0X.h), and unsuccessfully trying to implement nox771's 'global' solution, I ran across a curious section in the current Wire.h file at (on my Win10 laptop) C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Wire\Wire.h


Code:
#elif defined(__arm__) && defined(TEENSYDUINO)
#include "WireKinetis.h"

I had never seen any reference to the Teensy world before in this file, so I was curious and opened "WireKinetis.h" to find

Code:
// Teensy LC
#if defined(__MKL26Z64__)
#define WIRE_IMPLEMENT_WIRE
//Wire1 consumes precious memory on Teensy LC
//#define WIRE_IMPLEMENT_WIRE1
#define WIRE_HAS_STOP_INTERRUPT

// Teensy 3.0
#elif defined(__MK20DX128__)
#define WIRE_IMPLEMENT_WIRE

// Teensy 3.1 & 3.2
#elif defined(__MK20DX256__)
#define WIRE_IMPLEMENT_WIRE
#define WIRE_IMPLEMENT_WIRE1

// Teensy 3.5
#elif defined(__MK64FX512__)
#define WIRE_IMPLEMENT_WIRE
#define WIRE_IMPLEMENT_WIRE1
#define WIRE_IMPLEMENT_WIRE2
#define WIRE_HAS_START_INTERRUPT
#define WIRE_HAS_STOP_INTERRUPT

// Teensy 3.6
#elif defined(__MK66FX1M0__)
#define WIRE_IMPLEMENT_WIRE
#define WIRE_IMPLEMENT_WIRE1
#define WIRE_IMPLEMENT_WIRE2
//Wire3 is seldom used on Teensy 3.6
//#define WIRE_IMPLEMENT_WIRE3
#define WIRE_HAS_START_INTERRUPT
#define WIRE_HAS_STOP_INTERRUPT

#endif

And a bit further down...


Code:
#ifdef WIRE_IMPLEMENT_WIRE
extern TwoWire Wire;
#endif
#ifdef WIRE_IMPLEMENT_WIRE1
extern TwoWire Wire1;
#endif
#ifdef WIRE_IMPLEMENT_WIRE2
extern TwoWire Wire2;
#endif
#ifdef WIRE_IMPLEMENT_WIRE3
extern TwoWire Wire3;
#endif


Whoa! does this mean I could simply change


Code:
class Adafruit_VL53L0X {
public:
  boolean begin(uint8_t i2c_addr = VL53L0X_I2C_ADDR, boolean debug = false,
                TwoWire *i2c = &Wire);

To

Code:
class Adafruit_VL53L0X {
public:
  boolean begin(uint8_t i2c_addr = VL53L0X_I2C_ADDR, boolean debug = false,
                TwoWire *i2c = &Wire1);

or

Code:
class Adafruit_VL53L0X {
public:
  boolean begin(uint8_t i2c_addr = VL53L0X_I2C_ADDR, boolean debug = false,
                TwoWire *i2c = &Wire2);

And communicate with my VL53L0X using one of the alternate I2C ports?

Well, I tried this trick, and it seems to work! Here's my VL53L0X demo code:

Code:
/*
    Name:       Teensy_Adafruit_Single_VL53L0X_Demo.ino
    Created:	5/21/2020 7:07:44 PM
    Author:     FRANKNEWXPS15\Frank
*/

//#include <i2c_t3.h>
//#include <T3_I2C_Anything.h>

#include <Wire.h>
#include "Adafruit_VL53L0X.h"

Adafruit_VL53L0X lox = Adafruit_VL53L0X();

void setup() {
    Serial.begin(115200);

    // wait until serial port opens for native USB devices
    while (!Serial) {
        delay(1);
    }

    Serial.println("Adafruit VL53L0X test");
    if (!lox.begin()) {
        Serial.println(F("Failed to boot VL53L0X"));
        while (1);
    }
    // power 
    Serial.println(F("VL53L0X API Simple Ranging example\n\n"));
}


void loop() {
    VL53L0X_RangingMeasurementData_t measure;

    Serial.print("Reading a measurement... ");
    lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!

    if (measure.RangeStatus != 4) {  // phase failures have incorrect data
        Serial.print("Distance (mm): "); Serial.println(measure.RangeMilliMeter);
    }
    else {
        Serial.println(" out of range ");
    }

    delay(100);
}

And my modified Adafruit_VL53L0X.h file

Code:
/*!
 * @file Adafruit_VL53L0X.h

  This is a library for the Adafruit VL53L0X Sensor Breakout

  Designed specifically to work with the VL53L0X sensor from Adafruit
  ----> https://www.adafruit.com/products/3317

  These sensors use I2C to communicate, 2 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#ifndef ADAFRUIT_VL53L0X_H
#define ADAFRUIT_VL53L0X_H

#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include "Wire.h"
#include "vl53l0x_api.h"

#define VL53L0X_I2C_ADDR 0x29 ///< Default sensor I2C address

/**************************************************************************/
/*!
    @brief  Class that stores state and functions for interacting with VL53L0X
   time-of-flight sensor chips
*/
/**************************************************************************/
class Adafruit_VL53L0X {
public:
  boolean begin(uint8_t i2c_addr = VL53L0X_I2C_ADDR, boolean debug = false,
                TwoWire *i2c = &Wire1);
  boolean setAddress(uint8_t newAddr);

  /**************************************************************************/
  /*!
      @brief  get a ranging measurement from the device
      @param  pRangingMeasurementData the pointer to the struct the data will be
     stored in
      @param debug Optional debug flag. If true debug information will print via
     Serial.print during execution. Defaults to false.
      @returns True if address was set successfully, False otherwise
  */
  /**************************************************************************/
  VL53L0X_Error
  rangingTest(VL53L0X_RangingMeasurementData_t *pRangingMeasurementData,
              boolean debug = false) {
    return getSingleRangingMeasurement(pRangingMeasurementData, debug);
  };

  VL53L0X_Error getSingleRangingMeasurement(
      VL53L0X_RangingMeasurementData_t *pRangingMeasurementData,
      boolean debug = false);
  void
  printRangeStatus(VL53L0X_RangingMeasurementData_t *pRangingMeasurementData);

  VL53L0X_Error Status =
      VL53L0X_ERROR_NONE; ///< indicates whether or not the sensor has
                          ///< encountered an error

private:
  VL53L0X_Dev_t MyDevice;
  VL53L0X_Dev_t *pMyDevice = &MyDevice;
  VL53L0X_DeviceInfo_t DeviceInfo;
};

#endif


And some of the output, with the V53L0X physically connected to a Teensy 3.5 on pins 37 & 38 (SCL1,SDA1)

Code:
Opening port
Port open
Reading a measurement... Distance (mm): 66
Reading a measurement... Distance (mm): 66

And it also appears that I can set the 'normal' I2C bus (SCL0, SDA0) to SLAVE mode with the following lines in my main sketch:

Code:
    Wire.begin(0x66); //init as SLAVE
    Wire.setClock(100000);
    Wire.setSCL(19);
    Wire.setSDA(18);

Am I missing anything here?

TIA,

Frank
 
The only thing you are missing is that you don't have to edit the library to change which Wire object you want to call, just add the additional statements to your sketch begin call.

Code:
if (![COLOR="#FF0000"]lox.begin(VL53L0X_I2C_ADDR, false, &Wire1)[/COLOR]) {
        Serial.println(F("Failed to boot VL53L0X"));
        while (1);
    }
 
Status
Not open for further replies.
Back
Top