From a3f0551cfea9a480b9d4cd6022226886e7729857 Mon Sep 17 00:00:00 2001 From: Bill Daigle Date: Thu, 17 Mar 2022 10:12:29 -0600 Subject: [PATCH 1/9] Added a function to update the i2c address so multiple sensor can be used on the same bus --- adafruit_vl53l1x.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/adafruit_vl53l1x.py b/adafruit_vl53l1x.py index dba0c9f..01b9aa6 100644 --- a/adafruit_vl53l1x.py +++ b/adafruit_vl53l1x.py @@ -301,3 +301,19 @@ def _read_register(self, address, length=1): i2c.write(struct.pack(">H", address)) i2c.readinto(data) return data + + def set_address(self, i2c, 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 VL53L1X 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``. + """ + new_addres_as_byte_string = new_address.to_bytes(1, 'little') + self._write_register(0x01,new_addres_as_byte_string) + self.i2c_device = i2c_device.I2CDevice(i2c,new_address) \ No newline at end of file From f70ab272ea1cb4a9a089553f0e2418935955d0e6 Mon Sep 17 00:00:00 2001 From: Bill Daigle Date: Thu, 17 Mar 2022 10:13:01 -0600 Subject: [PATCH 2/9] Added an example of how to use multiple sensors on the same bus --- examples/vl53l1x_multiple_on_same_i2c_bus.py | 70 ++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 examples/vl53l1x_multiple_on_same_i2c_bus.py diff --git a/examples/vl53l1x_multiple_on_same_i2c_bus.py b/examples/vl53l1x_multiple_on_same_i2c_bus.py new file mode 100644 index 0000000..b5a3f73 --- /dev/null +++ b/examples/vl53l1x_multiple_on_same_i2c_bus.py @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: MIT + +""" +Example of how to use the adafruit_vl53l1x library to change the assigned address of +multiple VL53L1X sensors on the same I2C bus. This example only focuses on 2 VL53L1X +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_vl53l1x import VL53L1X + +# declare the singleton variable for the default I2C bus +i2c = board.I2C() + +# declare the digital output pins connected to the "SHDN" pin on each VL53L1X sensor +xshut = [ + DigitalInOut(board.D16), + DigitalInOut(board.D17), + # add more VL53L1X 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 VL53L1X sensor is off. + # if the output signal is HIGH, then the VL53L1X sensor is on. +# all VL53L1X sensors are now off + +# initialize a list to be used for the array of VL53L1X sensors +vl53 = [] + +# now change the addresses of the VL53L1X sensors +for i, power_pin in enumerate(xshut): + # turn on the VL53L1X to allow hardware check + power_pin.value = True + # instantiate the VL53L1X sensor on the I2C bus & insert it into the "vl53" list + vl53.insert(i, VL53L1X(i2c)) # also performs VL53L1X hardware check + # no need to change the address of the last VL53L1X sensor + if i < len(xshut) - 1: + # default address is 0x29. Change that to something else + vl53[i].set_address(i2c,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.distance)) + time.sleep(1.0) + count -= 1 + +detect_range() +print( + "Multiple VL53L1X sensors' addresses are assigned properly\n" + "execute detect_range() to read each sensors range readings" +) \ No newline at end of file From c83ff779925c310a2e8b574a8bb2c492afce7989 Mon Sep 17 00:00:00 2001 From: Bill Daigle Date: Thu, 17 Mar 2022 10:32:37 -0600 Subject: [PATCH 3/9] Updated copywrite --- examples/vl53l1x_multiple_on_same_i2c_bus.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/vl53l1x_multiple_on_same_i2c_bus.py b/examples/vl53l1x_multiple_on_same_i2c_bus.py index b5a3f73..2fefcf3 100644 --- a/examples/vl53l1x_multiple_on_same_i2c_bus.py +++ b/examples/vl53l1x_multiple_on_same_i2c_bus.py @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2021 wrdaigle for Adafruit Industries +# # SPDX-License-Identifier: MIT """ From a37ffc8c9d0ac83b678077729eed41f1622f44bf Mon Sep 17 00:00:00 2001 From: Bill Daigle Date: Thu, 17 Mar 2022 12:00:53 -0600 Subject: [PATCH 4/9] After running pre-commit --- adafruit_vl53l1x.py | 8 ++++---- examples/vl53l1x_multiple_on_same_i2c_bus.py | 9 ++++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/adafruit_vl53l1x.py b/adafruit_vl53l1x.py index 01b9aa6..279fb80 100644 --- a/adafruit_vl53l1x.py +++ b/adafruit_vl53l1x.py @@ -301,7 +301,7 @@ def _read_register(self, address, length=1): i2c.write(struct.pack(">H", address)) i2c.readinto(data) return data - + def set_address(self, i2c, 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 @@ -314,6 +314,6 @@ def set_address(self, i2c, new_address): 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``. """ - new_addres_as_byte_string = new_address.to_bytes(1, 'little') - self._write_register(0x01,new_addres_as_byte_string) - self.i2c_device = i2c_device.I2CDevice(i2c,new_address) \ No newline at end of file + new_addres_as_byte_string = new_address.to_bytes(1, "little") + self._write_register(0x01, new_addres_as_byte_string) + self.i2c_device = i2c_device.I2CDevice(i2c, new_address) diff --git a/examples/vl53l1x_multiple_on_same_i2c_bus.py b/examples/vl53l1x_multiple_on_same_i2c_bus.py index 2fefcf3..4a64e14 100644 --- a/examples/vl53l1x_multiple_on_same_i2c_bus.py +++ b/examples/vl53l1x_multiple_on_same_i2c_bus.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2021 wrdaigle for Adafruit Industries -# +# # SPDX-License-Identifier: MIT """ @@ -44,7 +44,9 @@ # no need to change the address of the last VL53L1X sensor if i < len(xshut) - 1: # default address is 0x29. Change that to something else - vl53[i].set_address(i2c,i + 0x30) # address assigned should NOT be already in use + vl53[i].set_address( + i2c, 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. @@ -65,8 +67,9 @@ def detect_range(count=5): time.sleep(1.0) count -= 1 + detect_range() print( "Multiple VL53L1X sensors' addresses are assigned properly\n" "execute detect_range() to read each sensors range readings" -) \ No newline at end of file +) From f7f2c58569531e8f77188dc06c99f677302dd27e Mon Sep 17 00:00:00 2001 From: Bill Daigle Date: Thu, 17 Mar 2022 12:13:36 -0600 Subject: [PATCH 5/9] Simplify docstring for sphinx --- adafruit_vl53l1x.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/adafruit_vl53l1x.py b/adafruit_vl53l1x.py index 279fb80..48a1680 100644 --- a/adafruit_vl53l1x.py +++ b/adafruit_vl53l1x.py @@ -303,16 +303,10 @@ def _read_register(self, address, length=1): return data def set_address(self, i2c, new_address): - """Set a new I2C address to the instantaited object. This is only called when using + """ + 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 VL53L1X 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``. """ new_addres_as_byte_string = new_address.to_bytes(1, "little") self._write_register(0x01, new_addres_as_byte_string) From 6fc9415bdbeff50ac355ab64fc7d453847e2a839 Mon Sep 17 00:00:00 2001 From: Bill Daigle Date: Sun, 20 Mar 2022 17:53:21 -0600 Subject: [PATCH 6/9] Reused i2c from init --- adafruit_vl53l1x.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/adafruit_vl53l1x.py b/adafruit_vl53l1x.py index 48a1680..da65d1e 100644 --- a/adafruit_vl53l1x.py +++ b/adafruit_vl53l1x.py @@ -77,6 +77,7 @@ class VL53L1X: def __init__(self, i2c, address=41): self.i2c_device = i2c_device.I2CDevice(i2c, address) + self._i2c = i2c model_id, module_type, mask_rev = self.model_info if model_id != 0xEA or module_type != 0xCC or mask_rev != 0x10: raise RuntimeError("Wrong sensor ID or type!") @@ -302,7 +303,7 @@ def _read_register(self, address, length=1): i2c.readinto(data) return data - def set_address(self, i2c, new_address): + 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 @@ -310,4 +311,4 @@ def set_address(self, i2c, new_address): """ new_addres_as_byte_string = new_address.to_bytes(1, "little") self._write_register(0x01, new_addres_as_byte_string) - self.i2c_device = i2c_device.I2CDevice(i2c, new_address) + self.i2c_device = i2c_device.I2CDevice(self._i2c, new_address) From 7f764c5fcf7b779dd0a40f9e1558f1ba66cd290f Mon Sep 17 00:00:00 2001 From: Bill Daigle Date: Sun, 20 Mar 2022 17:55:54 -0600 Subject: [PATCH 7/9] Updated example without passing i2c --- examples/vl53l1x_multiple_on_same_i2c_bus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/vl53l1x_multiple_on_same_i2c_bus.py b/examples/vl53l1x_multiple_on_same_i2c_bus.py index 4a64e14..6db91d6 100644 --- a/examples/vl53l1x_multiple_on_same_i2c_bus.py +++ b/examples/vl53l1x_multiple_on_same_i2c_bus.py @@ -45,7 +45,7 @@ if i < len(xshut) - 1: # default address is 0x29. Change that to something else vl53[i].set_address( - i2c, i + 0x30 + 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 From ef5228aee2e2f819d7d74df23da2979c023ba46f Mon Sep 17 00:00:00 2001 From: Bill Daigle Date: Fri, 25 Mar 2022 23:00:39 -0600 Subject: [PATCH 8/9] Added _VL53L1X_I2C_SLAVE_DEVICE_ADDRESS const and used struct.pack to convert int to bytes --- adafruit_vl53l1x.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/adafruit_vl53l1x.py b/adafruit_vl53l1x.py index da65d1e..e48f08a 100644 --- a/adafruit_vl53l1x.py +++ b/adafruit_vl53l1x.py @@ -34,6 +34,7 @@ # imports__version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_VL53L1X.git" +_VL53L1X_I2C_SLAVE_DEVICE_ADDRESS = const(0x0001) _VL53L1X_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND = const(0x0008) _GPIO_HV_MUX__CTRL = const(0x0030) _GPIO__TIO_HV_STATUS = const(0x0031) @@ -309,6 +310,7 @@ def set_address(self, new_address): multiple VL53L0X sensors on the same I2C bus (SDA & SCL pins). See also the `example `_ for proper usage. """ - new_addres_as_byte_string = new_address.to_bytes(1, "little") - self._write_register(0x01, new_addres_as_byte_string) + self._write_register( + _VL53L1X_I2C_SLAVE_DEVICE_ADDRESS, struct.pack(">B", new_address) + ) self.i2c_device = i2c_device.I2CDevice(self._i2c, new_address) From eff8538eaacc6f180d070782c71d62b09679df16 Mon Sep 17 00:00:00 2001 From: Bill Daigle Date: Fri, 25 Mar 2022 23:18:24 -0600 Subject: [PATCH 9/9] Date mod --- examples/vl53l1x_multiple_on_same_i2c_bus.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/vl53l1x_multiple_on_same_i2c_bus.py b/examples/vl53l1x_multiple_on_same_i2c_bus.py index 6db91d6..fd42fd4 100644 --- a/examples/vl53l1x_multiple_on_same_i2c_bus.py +++ b/examples/vl53l1x_multiple_on_same_i2c_bus.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021 wrdaigle for Adafruit Industries +# SPDX-FileCopyrightText: 2022 wrdaigle for Adafruit Industries # # SPDX-License-Identifier: MIT @@ -44,9 +44,7 @@ # no need to change the address of the last VL53L1X 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 + 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.