diff --git a/adafruit_vl53l0x.py b/adafruit_vl53l0x.py index 9ea8311..9a28f72 100644 --- a/adafruit_vl53l0x.py +++ b/adafruit_vl53l0x.py @@ -453,3 +453,20 @@ def range(self): range_mm = self._read_u16(_RESULT_RANGE_STATUS + 10) self._write_u8(_SYSTEM_INTERRUPT_CLEAR, 0x01) return range_mm + + def set_address(self, new_address): + """Set a new I2C address to the instantaited object. This is only called when using + multiple VL53L0X sensors on the same I2C bus (SDA & SCL pins). See also the + `example `_ for proper usage. + + :param int new_address: The 7-bit `int` that is to be assigned to the VL53L0X sensor. + The address that is assigned should NOT be already in use by another device on the + I2C bus. + + .. important:: To properly set the address to an individual VL53L0X sensor, you must + first ensure that all other VL53L0X sensors (using the default address of ``0x29``) + on the same I2C bus are in their off state by pulling the "SHDN" pins LOW. When the + "SHDN" pin is pulled HIGH again the default I2C address is ``0x29``. + """ + self._write_u8(_I2C_SLAVE_DEVICE_ADDRESS, new_address & 0x7f) + self._device.device_address = new_address diff --git a/docs/examples.rst b/docs/examples.rst index 5d801dc..789581b 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -6,3 +6,12 @@ Ensure your device works with this simple test. .. literalinclude:: ../examples/vl53l0x_simpletest.py :caption: examples/vl53l0x_simpletest.py :linenos: + +Multiple VL53L0X on Same I2C Bus +-------------------------------- + +Copy "../examples/vl53l0x_multiple_sensors.py" to your "CIRCUITPY" drive, then run the script with ``from vl53l0x_multiple_sensors import *`` + +.. literalinclude:: ../examples/vl53l0x_multiple_sensors.py + :caption: examples/vl53l0x_multiple_sensors.py + :linenos: diff --git a/examples/vl53l0x_multiple_sensors.py b/examples/vl53l0x_multiple_sensors.py new file mode 100644 index 0000000..04277ca --- /dev/null +++ b/examples/vl53l0x_multiple_sensors.py @@ -0,0 +1,64 @@ +""" +Example of how to use the adafruit_vl53l0x library to change the assigned address of +multiple VL53L0X sensors on the same I2C bus. This example only focuses on 2 VL53L0X +sensors, but can be modified for more. BE AWARE: a multitude of sensors may require +more current than the on-board 3V regulator can output (typical current consumption during +active range readings is about 19 mA per sensor). +""" +import time +import board +from digitalio import DigitalInOut +from adafruit_vl53l0x import VL53L0X + +# declare the singleton variable for the default I2C bus +i2c = board.I2C() + +# declare the digital output pins connected to the "SHDN" pin on each VL53L0X sensor +xshut = [ + DigitalInOut(board.D7), + DigitalInOut(board.D9), + # add more VL53L0X sensors by defining their SHDN pins here + ] + +for power_pin in xshut: + # make sure these pins are a digital output, not a digital input + power_pin.switch_to_output(value=False) + # These pins are active when Low, meaning: + # if the output signal is LOW, then the VL53L0X sensor is off. + # if the output signal is HIGH, then the VL53L0X sensor is on. +# all VL53L0X sensors are now off + +# initialize a list to be used for the array of VL53L0X sensors +vl53 = [] + +# now change the addresses of the VL53L0X sensors +for i, power_pin in enumerate(xshut): + # turn on the VL53L0X to allow hardware check + power_pin.value = True + # instantiate the VL53L0X sensor on the I2C bus & insert it into the "vl53" list + vl53.insert(i, VL53L0X(i2c)) # also performs VL53L0X hardware check + # no need to change the address of the last VL53L0X sensor + if i < len(xshut) - 1: + # default address is 0x29. Change that to something else + vl53[i].set_address(i + 0x30) # address assigned should NOT be already in use +# there is a helpful list of pre-designated I2C addresses for various I2C devices at +# https://learn.adafruit.com/i2c-addresses/the-list +# According to this list 0x30-0x34 are available, although the list may be incomplete. +# In the python REPR, you can scan for all I2C devices that are attached and detirmine +# their addresses using: +# >>> import board +# >>> i2c = board.I2C() +# >>> if i2c.try_lock(): +# >>> [hex(x) for x in i2c.scan()] +# >>> i2c.unlock() + +def detect_range(count=5): + """ take count=5 samples """ + while count: + for index, sensor in enumerate(vl53): + print('Sensor {} Range: {}mm'.format(index + 1, sensor.range)) + time.sleep(1.0) + count -= 1 + +print("Multiple VL53L0X sensors' addresses are assigned properly\n" + "execute detect_range() to read each sensors range readings")