From 97b755b436b25bb816874f8811db8d6e4fcd83cc Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Thu, 14 Nov 2019 23:05:51 -0800 Subject: [PATCH 1/3] added set_address() and example usage --- adafruit_vl53l0x.py | 18 +++++++ docs/examples.rst | 7 +++ examples/vl53l0x_multiple_sensors.py | 71 ++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 examples/vl53l0x_multiple_sensors.py diff --git a/adafruit_vl53l0x.py b/adafruit_vl53l0x.py index 9ea8311..8efec11 100644 --- a/adafruit_vl53l0x.py +++ b/adafruit_vl53l0x.py @@ -453,3 +453,21 @@ 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 8-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 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. The "SHDN" pin is usually labeled "XSHUT" on + non-Adafruit breakout boards. + """ + 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..72a3721 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -6,3 +6,10 @@ 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 +-------------------------------- + +.. 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..78f73b3 --- /dev/null +++ b/examples/vl53l0x_multiple_sensors.py @@ -0,0 +1,71 @@ +""" +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 +import busio +from digitalio import DigitalInOut +from adafruit_vl53l0x import VL53L0X + +# declare the singleton variable for the default I2C bus +i2c = busio.I2C(board.SCL, board.SDA) + +# declare the digital output pins connected to the "SHDN" pin on each VL53L0X sensor (this +# pin is labeled "XSHUT" on non-Adafruit breakout boards). Default behavior upon +# instantiation is (direction=INPUT) + (pull=None) = LOW output signal +x_shut = [ + DigitalInOut(board.D7), + DigitalInOut(board.D9) + ] +# idealy you might want to use an IO extender as these pins are only used to control the +# VL53L0X's power state. + +for power_pin in x_shut: + # make sure these pins are an 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. + # (value=False) = LOW output signal; LOW output disables/shutsdown the VL53L0X +# 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(x_shut): + # turn on the sensor to allow hardware check + power_pin.value = True + # instantiate the VL53L0X sensors on the I2C bus & insert it into the "vl53" list + vl53.insert(i, VL53L0X(i2c)) # also performs hardware check + # don't need to change the address of the last VL53L0X sensor + if i < len(x_shut) - 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 outdated/incomplete. +# you can scan for all I2C devices and detirmine their addresses using: +# "i2cdetect 1 -y" (without quotes) on a Raspberry Pi terminal or +# In the python REPR, execute the following commands: +# >>> import busio +# >>> i2c = busio.I2C(board.SCL, board.SDA) +# >>> i2c.try_lock() # if False is returned: something else is using the i2c bus +# >>> [hex(x) for x in i2c.scan()] +# >>> i2c.unlock() # free up the bus for something else to use it + +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""") From d16485b4d56edb656d5858fc1249f408d089e4ce Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 15 Nov 2019 02:01:31 -0800 Subject: [PATCH 2/3] (-) comments & (+) instructions to examples.rst --- docs/examples.rst | 2 ++ examples/vl53l0x_multiple_sensors.py | 43 ++++++++++++---------------- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/docs/examples.rst b/docs/examples.rst index 72a3721..789581b 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -10,6 +10,8 @@ Ensure your device works with this simple test. 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 index 78f73b3..bf15cd7 100644 --- a/examples/vl53l0x_multiple_sensors.py +++ b/examples/vl53l0x_multiple_sensors.py @@ -7,56 +7,50 @@ """ import time import board -import busio from digitalio import DigitalInOut from adafruit_vl53l0x import VL53L0X -# declare the singleton variable for the default I2C bus -i2c = busio.I2C(board.SCL, board.SDA) +# 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 (this -# pin is labeled "XSHUT" on non-Adafruit breakout boards). Default behavior upon -# instantiation is (direction=INPUT) + (pull=None) = LOW output signal -x_shut = [ +# declare the digital output pins connected to the "SHDN" pin on each VL53L0X sensor +xshut = [ DigitalInOut(board.D7), DigitalInOut(board.D9) + # add more sensors by defining their SHDN pins here ] -# idealy you might want to use an IO extender as these pins are only used to control the -# VL53L0X's power state. -for power_pin in x_shut: - # make sure these pins are an digital output, not a digital input +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. - # (value=False) = LOW output signal; LOW output disables/shutsdown the VL53L0X # 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(x_shut): +for i, power_pin in enumerate(xshut): # turn on the sensor to allow hardware check power_pin.value = True # instantiate the VL53L0X sensors on the I2C bus & insert it into the "vl53" list vl53.insert(i, VL53L0X(i2c)) # also performs hardware check # don't need to change the address of the last VL53L0X sensor - if i < len(x_shut) - 1: + 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 outdated/incomplete. -# you can scan for all I2C devices and detirmine their addresses using: -# "i2cdetect 1 -y" (without quotes) on a Raspberry Pi terminal or -# In the python REPR, execute the following commands: +# 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 busio # >>> i2c = busio.I2C(board.SCL, board.SDA) -# >>> i2c.try_lock() # if False is returned: something else is using the i2c bus -# >>> [hex(x) for x in i2c.scan()] -# >>> i2c.unlock() # free up the bus for something else to use it +# >>> if i2c.try_lock(): # i2c.scan() requires a lock on the I2C bus +# >>> [hex(x) for x in i2c.scan()] +# >>> i2c.unlock() # free up the bus for something else to use it def detect_range(count=5): """ take count=5 samples """ @@ -66,6 +60,5 @@ def detect_range(count=5): time.sleep(1.0) count -= 1 -print("""\ - multiple VL53L0X sensors' addresses are assigned properly\n\ - execute detect_range() to read each sensors range readings""") +print("Multiple VL53L0X sensors' addresses are assigned properly\n" + "execute detect_range() to read each sensors range readings") From 1a170ad56443601cec26b69a232145a8df73d254 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 15 Nov 2019 02:27:41 -0800 Subject: [PATCH 3/3] removed explicit mentions of "XSHUT" pin --- adafruit_vl53l0x.py | 9 ++++----- examples/vl53l0x_multiple_sensors.py | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/adafruit_vl53l0x.py b/adafruit_vl53l0x.py index 8efec11..9a28f72 100644 --- a/adafruit_vl53l0x.py +++ b/adafruit_vl53l0x.py @@ -459,15 +459,14 @@ def set_address(self, new_address): multiple VL53L0X sensors on the same I2C bus (SDA & SCL pins). See also the `example `_ for proper usage. - :param int new_address: The 8-bit `int` that is to be assigned to the VL53L0X sensor. + :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 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. The "SHDN" pin is usually labeled "XSHUT" on - non-Adafruit breakout boards. + 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/examples/vl53l0x_multiple_sensors.py b/examples/vl53l0x_multiple_sensors.py index bf15cd7..04277ca 100644 --- a/examples/vl53l0x_multiple_sensors.py +++ b/examples/vl53l0x_multiple_sensors.py @@ -16,8 +16,8 @@ # declare the digital output pins connected to the "SHDN" pin on each VL53L0X sensor xshut = [ DigitalInOut(board.D7), - DigitalInOut(board.D9) - # add more sensors by defining their SHDN pins here + DigitalInOut(board.D9), + # add more VL53L0X sensors by defining their SHDN pins here ] for power_pin in xshut: @@ -33,11 +33,11 @@ # now change the addresses of the VL53L0X sensors for i, power_pin in enumerate(xshut): - # turn on the sensor to allow hardware check + # turn on the VL53L0X to allow hardware check power_pin.value = True - # instantiate the VL53L0X sensors on the I2C bus & insert it into the "vl53" list - vl53.insert(i, VL53L0X(i2c)) # also performs hardware check - # don't need to change the address of the last VL53L0X sensor + # 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 @@ -46,11 +46,11 @@ # 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 busio -# >>> i2c = busio.I2C(board.SCL, board.SDA) -# >>> if i2c.try_lock(): # i2c.scan() requires a lock on the I2C bus +# >>> import board +# >>> i2c = board.I2C() +# >>> if i2c.try_lock(): # >>> [hex(x) for x in i2c.scan()] -# >>> i2c.unlock() # free up the bus for something else to use it +# >>> i2c.unlock() def detect_range(count=5): """ take count=5 samples """