VL53L1x change address

Hi Folks,

I am trying to change the address of two PiicoDev VL53L1x sensors so I can use 3 on a bus.

I have all 3 with their own XSHUT lines connected to PIOs. I can enable them one at a time.

I enter the parameter PiicoDev_VL53L1X.change.addr(0x2a) to change the address from 0x29, but I get an error message that it needs 2 position arguments. What is the other argument? If I type in (0x29, 0x2a) i get a different error message.

Also, can I address each sensor wthout using the XSHUT control lines using PiicoDev_VL53L1X(0x2a)?

1 Like

Is that your exact code, because you havenā€™t included the name of the class instance (usually ā€˜selfā€™) in the function call? Or is the message actually saying that the new address needs to be at least 2 away from the current address (ie, 0x2b instead of 0x2a) because the device occupies two sequential addresses.

1 Like

Hi Jeff,

Arrghh, brain fade. 0x29 + 2 != 0x2a. Back to school for me.

I cannot give the verbatim error message as I am at work atm, and the catastrophe is at home. I tried other address and got a similar message (memory, as I am at work).

PiicoDev_VL53L1X.change.addr(0x2a) is the actual code. So if I changed it to
PiicoDev_VL53L1X.change.addr(self, 0x2b) do you think it would have a better chance of being accepted?

1 Like

Hi Anthony,

If you could post the error message that displays when you run this parameter that would be really helpful.

Hopefully something in that lets us know what needs to be changed to allow this change to be made.

Thanks,
Sam

1 Like

Hi Sam,

Here is the offending line:
PiicoDev_VL53L1X.change_addr(0x2b)
and here is the error:
Traceback (most recent call last):
File ā€œā€, line 167, in
TypeError: function takes 2 positional arguments but 1 were given

1 Like

Hi @Anthony7497 Anthony - I had a hand in the hardware, code and video production for this module.

It looks like youā€™re using the generic class to try to write the address, rather than an instance of the class.

hereā€™s some minimal example code that will set up 2x units. Youā€™ll have to change your pin numbers to suit of course.
Iā€™ll leave it as an exercise to extend this to 3x units :wink:

from PiicoDev_VL53L1X import PiicoDev_VL53L1X
from PiicoDev_Unified import sleep_ms
from machine import Pin

# Change these pin numbers to the XSHUT pins you are using
shutdownA = Pin(0, Pin.OUT)
shutdownB = Pin(1, Pin.OUT)

# Shutdown all connected sensors
shutdownA.value(0)
shutdownB.value(0)

# Enable A for initialisation
shutdownA.value(1)
sensorA = PiicoDev_VL53L1X() # initialise sensor A with default address
sensorA.change_addr(0x2B)
# sensorA now has a new address

# Enable B for initialisation
shutdownB.value(1)
sensorB = PiicoDev_VL53L1X() # initialise sensor B with default address


# There are now two sensors initialised with separate addresses
# sensorA is at 0x2B
# sensorB is at 0x29 (default)

while True:
    distA = sensorA.read()
    distB = sensorB.read()
    print(f"{distA:4.0f}A, {distB:4.0f}B") # print both distances on same line
    sleep(0.1)

The basic recipe is as follows:

  1. Shutdown all the sensors by setting each XSHUT pin low
  2. Enable one device and initialise it
  3. change that deviceā€™s address
  4. Goto step 2 and repeat for next device

Keep doing this until you reach the last device, there is no need to change the address for the last device but you can if you like.

let me know if this works! I have pretty high confidence in the code as-written but itā€™s untested :grimacing: If we reach a gratifying outcome here Iā€™ll update the repo with an appropriate recipe. This functionality is in the advanced-user-space and so isnā€™t documented as well as it could be

2 Likes

Thank you, Michael!

I will give it a thrashing and report back.

1 Like

Great news, everybody. I have a working program. Many thanks to Michael, who was pretty much on the money.

A couple of traps along the way. Firstly, the compiler didnā€™t like the print statement. Had to replace it with:
print(str(dist_1) + " mm " + str(dist_2) + " mm " + str(dist_3) + " mm ")

All the rest of the traps were my own sweet work, to one extent or the other, In the interests of disclosure, they were:

  • Voltage drop across the breadboard - there was 0.4V difference at the worst. It didnā€™t affect the Oled, but the XL53L1x modules suffered. The furthest one would not initialise

  • The enable pins were in the wrong order. Oops. I had triple checked those, and still got it wrong,

  • I would occasionally get lockups on the centre sensor. The number it locked on would vary, but one it had done it, they only recourse was a power down.

  • The readings would vary by over a metre, sometimes adjacent readings,

I tried it again when I got home, and the last two problems had disappeared. At work, they were sitting on my bench facing up, same as at home. Difference is, at home I donā€™t have LED downlights. The ones at work are controlled by dimmers - they glow up when you walk in the room. I suspect these are the culprits. When I covered them with a book around 600mm away, they stabilised. Thinking back, they were in shadow. Spent two hours on this, and got nowhere.

Thanks for all your help, folks. Appreciated.

For those that lke B-grade horror stories, the code:

from PiicoDev_Unified import sleep_ms
from PiicoDev_SSD1306 import *
from PiicoDev_VL53L1X import PiicoDev_VL53L1X

from time import sleep
from machine import Pin, Timer, PWM, ADC, I2C

import time, ds18x20, onewire

#Led definitions
led_green = Pin(13, Pin.OUT, value=0)
led_red = Pin(12, Pin.OUT, value=0)
led_blue = Pin(18, Pin.OUT, value=0)
led_yellow = Pin(19, Pin.OUT, value=0) 
 
#pwm the white led
led_white = Pin(1, Pin.OUT, value=0)
pwm = PWM(led_white)
pwm.freq(800)

#VL53L1x definitions
GPIO_1 = Pin(15, Pin.IN)                                                 # reading acknowleged from VL53L0x
GPIO_2 = Pin(14, Pin.IN)
GPIO_3 = Pin(11, Pin.IN)
XSHUT_1 = Pin(20, Pin.OUT, value=0)                                      # enable r/w of VL53L0x. 0 = disable
XSHUT_2 = Pin(17, Pin.OUT, value=0)
XSHUT_3 = Pin(16, Pin.OUT, value=0)

ds_loopcount = (0)
ds_pending = (0)
ds_initiated = (0)

#Oled
display = create_PiicoDev_SSD1306()                                      # note address of LCD is 0x3C

# Text and numbers
for counter in range(0,101):                                             # verified demo program for the lcd
    display.fill(0)
    display.text("Goodbye,",27,15, 1)
    display.text("Cruel World",15,30, 1)
    display.text(str(counter),50,45, 1)
    display.show()
sleep_ms(100)

#Timers -RP2
tim1 = Timer()
#tim2 = Timer()
en_tim1 = True
#en_tim2 = True
tim1.init(period=800, mode=Timer.PERIODIC, callback=lambda t:led_green.toggle())     # toggle a LED on every cycle of the timer
#tim2.init(period=87, mode=Timer.PERIODIC, callback=lambda t:led_red.toggle())

Tim750mS = Timer()

#def set_pending(Tim750mS):
#    ds_pending = (5)
#    led_yellow.toggle() 
#    Tim750mS.deinit()

ow = onewire.OneWire(Pin(22))                                            # create a OneWire bus on GPIO22
ow.scan()                                                                # return a list of devices on the bus
ow.reset()                                                               # reset the bus
ow.readbyte()                                                            # read a byte
ow.writebyte(0x22)                                                       # write a byte on the bus

ds = ds18x20.DS18X20(ow)                                                 # set up a DS18x20
roms = ds.scan()
print('Found DS18B20')
ds.convert_temp()
time.sleep_ms(750)
for rom in roms:
    print("Degrees C --> ", ds.read_temp(rom))                           # output the temp reading

# initialise and change the addresses of two sensors
XSHUT_3.value(1)
Sensor_3 = PiicoDev_VL53L1X()                                            # initalise sensor 
Sensor_3.change_addr(0x2D)                                               # change the address to 0x2D

XSHUT_2.value(1)
Sensor_2 = PiicoDev_VL53L1X()                                            # initalise sensor 2
Sensor_2.change_addr(0x2B)                                               # change the address to 0x2B

XSHUT_1.value(1)
Sensor_1 = PiicoDev_VL53L1X()                                            # initalise sensor 1

while True:  
      
    # do 1-wire stuff for temp
    if ds_initiated == 0:                                                # test if we are reading or writing
        ds.convert_temp()                                                # do the conversion
#        Tim750mS.init(mode=Timer.PERIODIC, period=1000, callback=set_pending)
        ds_initiated = 1                                                 # so it only runs once per conversion
#        print("750mS timer set")
        
    if ds_pending == 1:                                                  # it is a 750mS conversion time. Don't wait, get it on the next pass
#        Tim750mS.deinit()
        for rom in roms:                                                 # read the conversion
    # process the temp reading
            print("Degrees C --> ", ds.read_temp(rom))
#        txt1 = f'{ds.read_temp(rom):.2f}'                               # convert the int to a string
        ds_pending = 0                                                   # toggle t0 repeat the process from the top
        ds_initiated = 0
                        
# It's showtime!

    dist_1 = Sensor_1.read()
    sleep(0.05)
    dist_2 = Sensor_2.read()
    sleep(0.05)
    dist_3 = Sensor_3.read()
    
    print(str(dist_1) + " mm     " + str(dist_2) + " mm     " + str(dist_3) + " mm     ") # convert the number to a string and print

#    print(f"{dist_1:4.0f}A, {dist_2:4.0f}B, {dist_3:4.0f}C)             # print all distances on same line
#    sleep(0.1) 
    
    # update the LCD
    display.fill(0)
    display.text("Sensor 1: "+ str(dist_1),10,12, 1)
    display.text("Sensor 2: "+ str(dist_2),10,24, 1)
    display.text("Sensor 3: "+ str(dist_3),10,36, 1)
    display.text("Temp:",42,48, 1)
    txt1 = f'{ds.read_temp(rom):.2f}'
    display.text(txt1, 83,48,1)
    display.show()
    
    # housekeeping for the temp sensor
    if ds_initiated == 1:
        ds_loopcount = ds_loopcount + 1
        if ds_loopcount > 10:
            ds_pending = 1
            ds_loopcount = 0
           

3 Likes

Hey Anthony,

Awesome to hear you got this working! If those problems pop back up let us know.

I think everyoneā€™s troubleshooting code ends up looking like that, more comments than code is sometimes a part of the process.

1 Like

Result! :partying_face:

Whoops! I missed closing the quote marks. Iā€™ve fixed this in the original reply for posterity.
(this was guaranteed to happen in hindsight, i was writing code straight into this forum post :grimacing: )

Iā€™ve had fluctuations when my sensors are pointed up at office lighting too - especially fluorescent tubes that spew a lot of IR

Iā€™m glad your project is back on track @Anthony7497 :smiley: Weā€™ll use this forum post as a reference for anybody else that wants to use multiple VL53L1X modules in future too :slight_smile:

1 Like