Usar vários VL53L0X com endereços I2C diferentes

De modo a desenvolver um lidar rotativo com vários sensores de distância laser VL53L0X ou VL53L1X para os meus robots, para o qual já imprimi umas peças na impressora 3D é necessário alterar os endereços I2C dos vários VL53LXX no bus I2C.

Essa alteração de endereço tem um procedimento especial, para o qual é necessário usar um pino digital do Arduino ligado ao pino XSHUT de cada VL53LXX no bus I2c.

Como o Arduino funciona com um nivel lógico de 5V, e o pino XSHUT não tem conversor de nivel lógico, é necessário colocar um conversor externo em cada pino.

Hardware

Arduino, e dois VL53L0X, um VL53L0X da Pololu e outro VL53L0X sem marca.

Esquema das ligações do Arduino com os dois VL53L0X
Esquema das ligações do Arduino com os dois VL53L0X

 

Software

Programa de teste que define os novos endereços para dois sensores de distancia VL53L0X e depois faz um varrimento ao bus I2C à procura de dispositivos.

vl53l0x_change_address_test_v1

#include <Wire.h>
#include <VL53L0X.h>

VL53L0X sensor;
VL53L0X sensor2;

#define PIN1 7
#define PIN2 8

void setup() {

pinMode(PIN1, OUTPUT);
pinMode(PIN2, OUTPUT);
digitalWrite(PIN1, LOW);
digitalWrite(PIN2, LOW);

delay(500);
Wire.begin();

Serial.begin (115200);

pinMode(PIN1, INPUT);
delay(150);
Serial.println("00");
sensor.init(true);

Serial.println("01");
delay(100);
sensor.setAddress((uint8_t)22);
Serial.println("02");

pinMode(PIN2, INPUT);
delay(150);
sensor2.init(true);
Serial.println("03");
delay(100);
sensor2.setAddress((uint8_t)25);
Serial.println("04");

Serial.println("addresses set");

}

void loop() {
Serial.println ("I2C scanner. Scanning ...");
byte count = 0;

for (byte i = 1; i < 120; i++) {

Wire.beginTransmission (i);
if (Wire.endTransmission () == 0) {
Serial.print ("Found address: ");
Serial.print (i, DEC);
Serial.print (" (0x");
Serial.print (i, HEX);
Serial.println (")");
count++;
delay (1); // maybe unneeded?
} // end of good response
} // end of for loop
Serial.println ("Done.");
Serial.print ("Found ");
Serial.print (count, DEC);
Serial.println (" device(s).");

delay(3000);
}

Resultado

Foto do ecran ao detectar os dois VL53L0X 

Programa de teste que define os novos endereços para dois sensores de distancia VL53L0X e apresenta os dispositivos existentes no bus I2C, passando a exibir as leituras dos dois sensores.

vl53l0x_multiple_test_v1

#include <Wire.h>
#include <VL53L0X.h>

VL53L0X sensor1;
VL53L0X sensor2;

#define PIN1 7
#define PIN2 8

void setup() {

pinMode(PIN1, OUTPUT);
pinMode(PIN2, OUTPUT);
digitalWrite(PIN1, LOW);
digitalWrite(PIN2, LOW);

delay(500);
Wire.begin();

Serial.begin (115200);

pinMode(PIN1, INPUT);
delay(150);
Serial.println("00");
sensor1.init(true);

Serial.println("01");
delay(100);
sensor1.setAddress((uint8_t)22);
Serial.println("02");

pinMode(PIN2, INPUT);
delay(150);
sensor2.init(true);
Serial.println("03");
delay(100);
sensor2.setAddress((uint8_t)25);
Serial.println("04");

Serial.println("addresses set");

// end configuration
sensor1.setTimeout(500);
sensor2.setTimeout(500);
sensor1.startContinuous();
sensor2.startContinuous();

// scan i2c
Serial.println ("I2C scanner. Scanning ...");
byte count = 0;

for (byte i = 1; i < 120; i++) {

Wire.beginTransmission (i);
if (Wire.endTransmission () == 0) {
Serial.print ("Found address: ");
Serial.print (i, DEC);
Serial.print (" (0x");
Serial.print (i, HEX);
Serial.println (")");
count++;
delay (1); // maybe unneeded?
} // end of good response
} // end of for loop
Serial.println ("Done.");
Serial.print ("Found ");
Serial.print (count, DEC);
Serial.println (" device(s).");
}

void loop() {
Serial.print(sensor1.readRangeContinuousMillimeters());
if (sensor1.timeoutOccurred()) { Serial.print(" TIMEOUT S1"); }
Serial.print("\t");
Serial.print(sensor2.readRangeContinuousMillimeters());
if (sensor2.timeoutOccurred()) { Serial.print(" TIMEOUT S2"); }
Serial.println();
}