Closed ZanzyTHEbar closed 1 year ago
Are you following the general code example as shown here? https://learn.adafruit.com/working-with-multiple-i2c-devices/arduino-3
Of course. I am a c++ developer, i wrote my own multiplexer class (which work's fine in all other tested scenario's). I narrowed the actual issue down to the fact that this Adafruit lib calls the begin method on the twowire object, when the multiplexer has already done this.
#include "multiplexer.hpp"
I2C_Multiplexer::I2C_Multiplexer(TwoWire* pWire, uint8_t addr)
: _pWire(pWire), _I2CMultiplexer_addr(addr) {}
I2C_Multiplexer::~I2C_Multiplexer() {}
void I2C_Multiplexer::begin(void) {
_pWire->begin();
}
uint8_t* I2C_Multiplexer::scan(uint8_t port) {
static uint8_t dev[127] = {0};
memset(dev, 0, sizeof(dev));
uint8_t i = 0;
selectPort(port);
byte error, address;
for (address = 1; address < 127; address++) {
if (address == _I2CMultiplexer_addr)
continue;
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
dev[i] = address;
i++;
}
}
return dev;
}
void I2C_Multiplexer::selectPort(uint8_t port) {
// To prevent multiple expansion modules from colliding, add a parameter to
// close all channels
if (port > 8)
return;
Wire.beginTransmission(_I2CMultiplexer_addr);
Wire.write((1 << port) & 0xFF);
Wire.endTransmission();
}
void I2C_Multiplexer::write(uint8_t port,
uint8_t addr,
uint8_t reg,
uint8_t* buf,
uint8_t len) {
selectPort(port);
Wire.beginTransmission(addr);
Wire.write(reg);
uint8_t i = 0;
for (i = 0; i < len; i++) {
Wire.write(*buf);
buf++;
}
Wire.endTransmission();
}
uint8_t I2C_Multiplexer::read(uint8_t port,
uint8_t addr,
uint8_t reg,
uint8_t* data,
uint8_t len) {
selectPort(port);
int i = 0;
Wire.beginTransmission(addr);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom(addr, len, false);
while (Wire.available()) {
data[i++] = Wire.read();
}
return i;
}
Don't currently have access to multiple VL53L0X's. However, connecting a single VL53L0X though a TCA9548 muxer works with this example sketch on a Feather ESP32 S3:
#include <Adafruit_VL53L0X.h>
#define TCAADDR 0x70
Adafruit_VL53L0X lox = Adafruit_VL53L0X();
// Helper function for changing TCA output channel
void tcaselect(uint8_t channel) {
if (channel > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << channel);
Wire.endTransmission();
}
void setup() {
Serial.begin(115200);
while(!Serial);
Serial.println("ESP32 S3 + VL53L0X + TCA Test");
// NOTE!!! VERY IMPORTANT!!!
// Must call this once manually before first call to tcaselect()
Wire.begin();
// Before using any BME280, call tcaselect to set the channel.
tcaselect(0); // TCA channel for bme1
lox.begin(); // use the default address
}
void loop() {
VL53L0X_RangingMeasurementData_t measure;
Serial.print("Reading a measurement... ");
tcaselect(0);
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);
}
Here is the output in the Serial Monitor:
Reading a measurement... Distance (mm): 457
Reading a measurement... Distance (mm): 302
Reading a measurement... Distance (mm): 180
Reading a measurement... Distance (mm): 117
Reading a measurement... Distance (mm): 135
Reading a measurement... Distance (mm): 175
Reading a measurement... Distance (mm): 288
Reading a measurement... Distance (mm): 443
So it seems like it's something other than the call the Wire.begin()
. All Adafruit Arduino libraries that use I2C make this call internally.
Try using the above example sketch and expand it to two (or more) VL53L0X's and see what happens.
Alright, i will do so. The issue is harder to pinpoint than i thought. I figured it was caused by multiple calls to begin()
causing a IO timeout issue - i'll try the Adafruit example sketch and then dig a little deeper.
After some extensive testing, the example code works, until i add another sensor. Then, i get the same error as with my code.
This is the exact line of code that fails for me:
void Tof::begin() {
if (!psensor->begin(id)) {
log_e("[TOF Sensor]: Failed to boot VL53L0X: 0x%02X", id);
log_e("[TOF Sensor]: Pausing execution until reset");
while (1)
;
}
}
psensor
being the lox sensor itself. weirdly, if i leave out the id
param - the sensor fails to initialize everytime. Even if there is only one of them.
This is my begin statement.
void EventManager::begin(void) {
//* initialize multiplexer and i2c bus
multiplexer.begin();
log_d("[Event Manager]: Multiplexer initialized");
log_d("[Event Manager]: Scanning for connected sensors");
// scan for sensors
for (uint8_t port = 0; port < 8; port++) {
Serial.printf("Scanning Port: %d \n", port);
uint8_t* dev = multiplexer.scan(port);
while (*dev) {
Serial.printf("Found Device at i2c addr: 0x%02X \n", *dev);
//* add sensor to the vector
_tof_sensors.emplace_back(
new Tof(new Adafruit_VL53L0X(), WIRE_OBJECT, *dev, 0, 1));
Serial.println("Adding sensor to vector");
//* initialize sensor
multiplexer.selectPort(port);
_tof_sensors.back()->begin();
dev++;
}
Serial.printf("Size of vector: %d \n", _tof_sensors.size());
Serial.println();
}
}
If i comment out _tof_sensors.back()->begin();
the error goes away - but obviously the sensors don't start up. So the issue is absolutely to do with the VL53L0x class' -ican't seem to make more than one of them.
i have done more debugging - turns out the issue was another library. i removed a USBHID library (in favour of another), and the issue went away. Apologies. multiple sensors work fine now.
Thank you for opening an issue on an Adafruit Arduino library repository. To improve the speed of resolution please review the following guidelines and common troubleshooting steps below before creating the issue:
Do not use GitHub issues for troubleshooting projects and issues. Instead use the forums at http://forums.adafruit.com to ask questions and troubleshoot why something isn't working as expected. In many cases the problem is a common issue that you will more quickly receive help from the forum community. GitHub issues are meant for known defects in the code. If you don't know if there is a defect in the code then start with troubleshooting on the forum first.
If following a tutorial or guide be sure you didn't miss a step. Carefully check all of the steps and commands to run have been followed. Consult the forum if you're unsure or have questions about steps in a guide/tutorial.
For Arduino projects check these very common issues to ensure they don't apply:
For uploading sketches or communicating with the board make sure you're using a USB data cable and not a USB charge-only cable. It is sometimes very hard to tell the difference between a data and charge cable! Try using the cable with other devices or swapping to another cable to confirm it is not the problem.
Be sure you are supplying adequate power to the board. Check the specs of your board and plug in an external power supply. In many cases just plugging a board into your computer is not enough to power it and other peripherals.
Double check all soldering joints and connections. Flakey connections cause many mysterious problems. See the guide to excellent soldering for examples of good solder joints.
Ensure you are using an official Arduino or Adafruit board. We can't guarantee a clone board will have the same functionality and work as expected with this code and don't support them.
If you're sure this issue is a defect in the code and checked the steps above please fill in the following fields to provide enough troubleshooting information. You may delete the guideline and text above to just leave the following details:
Arduino board:
esp32-s3
Arduino IDE version (found in Arduino -> About Arduino menu):
latest - Platformio
List the steps to reproduce the problem below (if possible attach a sketch or copy the sketch code in too):
Steps to reproduce:
Adafruit_VL53L0X
onesp32-s3
.This library calls
begin()
on theTwowire
object, which is an issue when running the sensors on an I2C multiplexer, as the multiplexer needs to callbegin()
on theTwoWire
object itself. This causes the I/O read timeout error to occur.