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
I had never seen any reference to the Teensy world before in this file, so I was curious and opened "WireKinetis.h" to find
And a bit further down...
Whoa! does this mean I could simply change
To
or
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:
And my modified Adafruit_VL53L0X.h file
And some of the output, with the V53L0X physically connected to a Teensy 3.5 on pins 37 & 38 (SCL1,SDA1)
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:
Am I missing anything here?
TIA,
Frank
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