Micromouse Lab 3

Micromouse
ToF Sensors

I\(^{2}\)C

I\(^{2}\)C (Inter-Integrated Circuit) is a protocol that allows a “master” (leader) device to talk to multiple “slave” (follower) devices using only two wires.

In our case, the Arduino is the master device and the distance sensors are slave devices. The two wires are known as SDA (“serial data”) and SCL (“serial clock”). Each slave device needs to have a unique address.

I2C Timing Diagram
I\(^{2}\)C Timing Diagram

Our distance sensors (VL53L0X) use I2C. We will be using an Arduino library to interface with the sensors, so we don’t have to worry about how most of I2C works.

First, let’s install the VL53L0X library! In the Arduino IDE, open the Library Manager via Sketch > Include Library > Library Manager. You’ll want the VL53L0X library by Pololu.

Package Manager

The following code demonstrates how to use the VL53L0X library for one sensor. Please read and try to understand this code before answering the checkoff questions and moving to the next checkoff. As extra clarification you do not need to change any code for this checkoff.

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

VL53L0X distance_sensor_center;

void setup() {
  Serial.begin(9600);
  
  // Disable left and right sensors
  pinMode(PIN_TOF_LEFT_RESET, OUTPUT);
  pinMode(PIN_TOF_RIGHT_RESET, OUTPUT);
  digitalWrite(PIN_TOF_LEFT_RESET, LOW);
  digitalWrite(PIN_TOF_RIGHT_RESET, LOW);

  // Initialize I2C -- this is the protocol the VL53L0X sensor library uses
  Wire.begin();

  // Set up center sensor with address 0x01
  configureDistanceSensor(&distance_sensor_center, 0x01);
}

void loop() {
	// Read a distance and store it in the distance variable
	Serial.println("Center Distance : ");
	Serial.print(distance_sensor_center.readRangeContinuousMillimeters());
	Serial.print(" mm");
}

//////////////////////
// Helper functions //
//////////////////////

void configureDistanceSensor(VL53L0X* sensor, uint8_t addr) {
	delay(100);
	sensor->setAddress(addr);
	sensor->init();
	sensor->setTimeout(500);
	sensor->startContinuous(100);
}

Checkoff #1

  1. Following the labels on your sensor and PCB, wire up a distance sensor.
  2. Show that all three of your sensors work (independently)
  3. Since the ToF sensors are identical, the code above might have issues if we plug in 2 ToF sensors into the I2C bus instead of just one.
    • What issue might we have
    • Why does this make it more difficult to use multiple TOF sensors?
I\(^{2}\)C With Multiple Sensors

Each sensor needs to have a different address so we can talk to each one separately. Unfortunately, the VL53L0X sensors all use the same address by default.

It turns out that the VL53L0X supports changing its address using an I2C command. If we just send that command, though, all of the sensors will change their address to the same value. We would be back to where we started.

We need to take advantage of the reset signal on the sensors as well. Many chips, including the VL53L0X, have a reset signal that causes the chip to ignore commands (and reset itself). The reset signal on the VL53L0X sensor is labeled “XSHUT”. There are also pins for I2C (SCL and SDA) and power.

VL53L0X sensor
VL53L0X Sensor

We can assign all of the sensors unique addresses using the following method:

  • Turn off left and right sensors (pull left/right XSHUT pin low (and setup them as outputs). Register the center XSHUT pin as an input (the ToF sensor will internally pull the center pin high, turning it on. This does not happen when XSHUT is setup as an output.)) DO NOT digitalWrite(XSHUT, HIGH)! It might break the sensor. Just use one of either:
    1. pinMode(XSHUT, OUTPUT) with digitalWrite(XSHUT, LOW); to turn a ToF sensor off
    2. pinMode(XSHUT, INPUT); to turn the ToF sensor back on
  • Set the center sensor’s address to 0x01
    1. Do this with:
      configureDistanceSensor(&distance_sensor_center, 0x01);
      //Remember the & symbol - this is important!
  • Take the left sensor out of reset (setup the left XSHUT pin as an input)
  • Set the left sensor’s address to 0x02
  • Take the right sensor out of reset (setup the right XSHUT pin as an input)
  • Set the right sensor’s address to 0x03

Once we are done, all three sensors should have different addresses.

In the following code fill in the blanks of SetupAllSensors(), a function that uses configureDistanceSensor()to setup all three distance sensors using the steps 1-6 in the previous lines. Please use the pins provided in the beginning of the code. These lines will be useful when filling out SetupAllSensors().

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

VL53L0X distance_sensor_center;
VL53L0X distance_sensor_left;
VL53L0X distance_sensor_right;

//Use these pins for your function!!!!!!!!!!!!!!!
#define PIN_TOF_LEFT_RESET 4
#define PIN_TOF_CENTER_RESET 7
#define PIN_TOF_RIGHT_RESET A0


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

	// Initialize I2C -- this is the protocol the VL53L0X sensor library uses
	Wire.begin();

  	SetupAllSensors();    //Function you are writing
}

void loop() {
  	// Read a distance and store it in the distance variable
    // If you have trouble seeing values on the Serial Plotter, add a delay!
  
	Serial.println("Center Distance : ");
	Serial.print(distance_sensor_center.readRangeContinuousMillimeters());
	Serial.print(" mm");
	Serial.println(" ");

	Serial.println("Left Distance : ");
	Serial.print(distance_sensor_left.readRangeContinuousMillimeters());
	Serial.print(" mm");
	Serial.println(" ");

	Serial.println("Right Distance : ");
	Serial.print(distance_sensor_right.readRangeContinuousMillimeters());
	Serial.print(" mm");
	Serial.println(" ");
	Serial.println("------------------------------");
}

void SetupAllSensors (void) {
	// Set up the three distance sensors.
  	// This is done as follows:
  	// 1) Disable the left and right sensors.

  	// 2) Set up the center sensor with an address of 0x01

  	// 3) Enable the left sensor

  	// 4) Set the left sensor up with an address of 0x02

  	// 5) Enable the right sensor

  	// 6) Set the right sensor up with an address of 0x03

}

//////////////////////
// Helper functions //
//////////////////////

void configureDistanceSensor(VL53L0X* sensor, uint8_t addr) {
  	delay(100);
  	sensor->setAddress(addr);
  	sensor->init();
  	sensor->setTimeout(500);
  	sensor->startContinuous(100);
}

Checkoff #2

  1. Show all sensors working (simultaneously)