Hello! My name is Maia Hirsch, and I’m a PhD student in Robotics at Cornell University with a background in Mechanical Engineering. My main interests are robotics, actuation, sensing, and human–robot interaction. In my free time, I enjoy exploring creative projects that combine engineering and design. You can check out my insta @maiahirschlab to see all the cool things I make.
The VL53L1X ToF sensor has a default 12C address of 0x29 (7-bit), which corresponds to 0 x 52 in the 8-bit addressing convention used in the datasheet. The Arduino Wire library uses 7-bit addressing, so 0x29 is the address I will use in the code.
Both sensors share the same default a dress and this is problematic as they have to be modified to be used simultaneously. I used the XSHUT pin approach: on startup, the XSHUT pin of sensor 2 is pulled LOW to disable it, then sensor 1’s address is changed to 0x30. Sensor 2 is then re-enabled via XSHUT and boots at the default 0x29. Both sensors can now be addressed independently on the same I2C bus at the same time.
For the final robot, I plan to mount one sensor facing forward and one facing on the side. The forward sensor handles the primary obstacle detection for the stop-before-wall task. The side sensor helps detect lateral obstacles during turns. Obstacles will be missed if objects are very low to the ground, below the sensor’s field of view. Objects approaching from behind and objects outside the angular sensitivity cone of each sensor will also be missed, although I do not expect any objects approaching from behind.

Both sensors connect to the QWIIC breakout board via QWIIC cables (SDA, SCL, VCC, GND). Sensor 2 has an additional wire from its XSHIT pin to GPIO pin A0 on the Artemis for shutdown control.


The I2C scan detected the ToF sensor at address 0x29, matching the expected 7-bit address. The IMU was also detected at 0x69. The second I2C port showed no devices since all sensors are connected to the same bus.
I tested both Short and Long distance modes between 100mm and 1000mm, averaging 256 readings at each positions. The results are plotted below:

Interestingly, Long mode tracked the reference line more smoothly throughout the range, while Short mode showed irregularities, particularly a flat region around 500 - 600mm where readings plateaued before catching up. Despite this, I chose Short mode for the final robot for two reasons.

Using the XSHUT addressing approach described in the prelab, both sensors were initialized at different addresses (0x29 and 0x30) and operated simultaneously. The setup code is as follows:
// Disable sensor 2 before anything else
pinMode(SHUTDOWN_PIN, OUTPUT);
digitalWrite(SHUTDOWN_PIN, LOW);
// Init dual ToF sensors
delay(10);
distanceSensor1.setI2CAddress(0x30);
digitalWrite(SHUTDOWN_PIN, HIGH);
delay(50);
distanceSensor1.setDistanceModeShort();
distanceSensor2.setDistanceModeShort();

To maximize loop speed, I used a non-blocking approach with checkForDataReady() rather than waiting for each measurement to complete:
if (distanceSensor1.checkForDataReady()) {
tof1_data[tof_index] = distanceSensor1.getDistance();
distanceSensor1.clearInterrupt();
got1 = true;
}
if (distanceSensor2.checkForDataReady()) {
tof2_data[tof_index] = distanceSensor2.getDistance();
distanceSensor2.clearInterrupt();
got2 = true;

The loop executes every 4-5ms when no sensor data is ready. New ToF data arrives every ~50ms, matching the Short mode ranging time measured earlier. The limiting factor is the sensor’s measurement cycle, not the microcontroller’s processing speed.
ToF data was collected over BLE using a START_IMU flag that simultaneously triggered both ToF sensors and the IMU. Data was stored in arrays and transmitted after collection.

Both sensors respond clearly to objects being moved in front of them, with sensor 1 and sensor 2 tracking different distances simultaneously.
IMU complimentary filter data was collected simultanously and sent over BLE:

Both ToF sensors and IMU complimentary filter were recorded simultaneously using a shared record_imu flag in the main loop. Since the IMU samples faster than the ToF, separate timestamp arrays were maintained for each. The complimentary filter data was collected separately using GET_COMP_DATA.

Sensors can be either passive or active. Passive sensors detect IT emitted by the environment, which are useful for heat detection or proximity sensing; while active sensors emit their own IR and measure the reflection.
Within active sensors there are two main approaches:
Since the ToF sensor operated on IR light, its performance depends on the reflective properties of the target surface. I tested 3 colors and 3 materials at a fixed distance of 300mm to observe how readings varied.
| Colors | Distance Measured (mm) |
|---|---|
| Black | 289 |
| White | 300 |
| Grey | 294 |
| Materials | Distance Measured (mm) |
|---|---|
| Cardboard | 300 |
| Skin | 302 |
| Mirror/glass | 310 |

Color had a noticeabel effect, white returned the most accurate reading at exactly 300mm, which black underestimated by 11mm, liekly because black surfaces absorb more IR light and return a weaker signal.
For materials, flat cardboard performed best, matching ground truth exactly. Skin introduced a small 2mm error, possibly due to partial absorption by organic tissue. Mirror/glass overestimated by 10mm, which is interesting because rather than absorbing IR, reflective surfaces may be scattering the pulse at an angle, cause the sensor to measure a longer path length than the direct distance.
Overall, flat matte light-colored surfaces give the most reliable readings.