I2C Getting Started

I am looking for a tutorial regarding the robot hat on my Picar-X to use the two I2C sets of pins.

For my first example I have a VL53L0X ToF distance ranging sensor, which I am using to track walls while traveling a hallway.

This sensor requires drivers and there are several repositories with Python code. This for example, http://www.pibits.net/code/raspberry-pi-and-vl53l0x-time-of-flight-example.php. But it does not work and seems like I need to modify this code specifically for the robot hat.

This repo seems to work.

The first step is to wire the sensor correctly to the Robot-Hat I2C pins.
Next is to run i2cdetect -y 1 which queries bus 1 to find the correct address. Seems like 0x29 is the default address.

Running their basic example which already has the proper default address.

tof = VL53L0X.VL53L0X(i2c_bus=1,i2c_address=0x29)

VL53L0X Start Ranging Address 0x29
VL53L0X_GetDeviceInfo:
Device Name : VL53L0X ES1 or later
Device Type : VL53L0X
Device ID : VL53L0CXV0DH/1$C
ProductRevisionMajor : 1
ProductRevisionMinor : 1
API Status: 0 : No Error
VL53L0X_BETTER_ACCURACY_MODE
API Status: 0 : No Error
Timing 66 ms 
....

I get good results with this.

Next up, find out how to use 2 sensors so the Picar-X can travel down the center of the hallway by reading distance from both the left and right side walls.

There are 2 sets of physical pins on the Robot-Hat. Port0 and Port1. Both will show the sensor as address 0x29 on bus 1 and plugging into either works. Plugging both sensors at the same time appears to interfere and results are not usable.

The repo example here suggests that it is possible to directly connect the Raspberry Pi GPIO to both sensors simultaneously. This is done by using each sensor’s interrupt/shutdown pin to set a unique i2c address. My question to @SunFounder_Moderator would be:

can I use any two free pins on the robot hat (ADC, Digital, PWM) as a GPIO to send this “high/low” signal?

According to this repo, there is another way to use two sensors at the same time. The “TCA9548A I2C Multiplexer” shown at the bottom of the repo’s Readme.
At first, I thought the 2 sets of I2C pins on the Robot Hat, meant that it acted as a similar multiplexer, but both seems to be on the same Bus 1. Attempting to i2cdetect on bus 0 or bus 2 does not work, fails to read. Why have two sets of i2c pins on the Robot Hat, if it doesn’t present as two buses?

Thanks.

The Robot Hat documentation (a bit hard to find), had the clues for the next steps.

I measured 3.3v on Digital Pins 0 and 1, which were available (ultrasonic is using D3,D4).
Using the Pin API on the Robot Hat, it was easy to control the shutoff for the VL53L0X sensor.
The sensor’s datasheet was helpful in confirming that the XSHUT pin could handle a max of 3.6v so I was careful not to connect it to 5v.

Here is my modified VL53L0X_multi_example.py:

#!/usr/bin/python

import time
import VL53L0X
from robot_hat import Pin

pin0 = Pin("D0")
pin1 = Pin("D1")

# Set all shutdown pins low to turn off each VL53L0X
pin0.value(0)
pin1.value(0)
time.sleep(0.50)

# Turn on first VL53L0X sensor and set a new I2C address
pin0.value(1)
tof = VL53L0X.VL53L0X(i2c_bus=1,i2c_address=0x29)
tof.change_address(0x32)
tof.open()

time.sleep(0.50)

# Turn on second VL53L0X using default I2C address
pin1.value(1)
tof1 = VL53L0X.VL53L0X(i2c_bus=1,i2c_address=0x29)
tof1.open()

time.sleep(0.50)
tof.start_ranging(VL53L0X.Vl53l0xAccuracyMode.BETTER)
tof1.start_ranging(VL53L0X.Vl53l0xAccuracyMode.BETTER)

timing = tof.get_timing()
if timing < 20000:
    timing = 20000
print("Timing %d ms" % (timing/1000))

for count in range(1,501):
    distance = tof.get_distance()
    if distance > 0:
        print("%d : Left %d cm" % (count, (distance/10)), end='\t')
    else:
        print("%d - Error" % 1, end='\t')

    distance = tof1.get_distance()
    if distance > 0:
        print("Right - %d cm" % ((distance/10)), end='\r')
    else:
        print("%d - Error" % 2, end='\r')

    time.sleep(timing/1000000.00)

tof1.stop_ranging()
pin0.value(0)
tof.stop_ranging()
pin1.value(0)

tof.close()
tof1.close()

With this example code as a base, I can include wall following with the obstacle avoidance code.

The two I2Cs are the same bus, we just provide two different interfaces to facilitate different usage scenarios.
Yes, you can use the Pin library to control the GPIO of Raspberry Pi to control your sensors. There is nothing wrong with your code.

1 Like