Lopy 4 with vl6180x TOF sensor

  • I have a LoPy 4 connected with a vl6180x and im trying to figure out how to get it properly set up.
    The value(distance) varies from 1-60 and after 60 it goes straight to 255. I don't know why this is happening and how it can be solved.

    import ustruct
    import struct
    import time
    from machine import I2C
    i2c = I2C(0, I2C.MASTER, baudrate=100000, pins=('P9', 'P10'))
    class Sensor:
        def __init__(self, i2c, address=0x29):
            self.i2c = i2c
            self._address = address
        def myWrite16(self, register, regValue):
            """ write a byte to specified 16 bit register """
            return self.i2c.writeto_mem(self._address, register, bytearray([regValue]), addrsize=16), 'big'
        def myRead16(self, register):
            """read 1 bit from 16 byte register"""
            # i2c.readfrom_mem(0x29, 0x0016, 1, addrsize=16)
            value = int.from_bytes(
                self.i2c.readfrom_mem(self._address, register, 1, addrsize=16),
            return value & 0xFFFF
        def init(self):
            if self.myRead16(0x0016) != 1:
                raise RuntimeError("Failure reset")
            # Recommended setup from the datasheet
            self.myWrite16(0x0207, 0x01)
            self.myWrite16(0x0208, 0x01)
            self.myWrite16(0x0096, 0x00)
            self.myWrite16(0x0097, 0xfd)
            self.myWrite16(0x00e3, 0x00)
            self.myWrite16(0x00e4, 0x04)
            self.myWrite16(0x00e5, 0x02)
            self.myWrite16(0x00e6, 0x01)
            self.myWrite16(0x00e7, 0x03)
            self.myWrite16(0x00f5, 0x02)
            self.myWrite16(0x00d9, 0x05)
            self.myWrite16(0x00db, 0xce)
            self.myWrite16(0x00dc, 0x03)
            self.myWrite16(0x00dd, 0xf8)
            self.myWrite16(0x009f, 0x00)
            self.myWrite16(0x00a3, 0x3c)
            self.myWrite16(0x00b7, 0x00)
            self.myWrite16(0x00bb, 0x3c)
            self.myWrite16(0x00b2, 0x09)
            self.myWrite16(0x00ca, 0x09)
            self.myWrite16(0x0198, 0x01)
            self.myWrite16(0x01b0, 0x17)
            self.myWrite16(0x01ad, 0x00)
            self.myWrite16(0x00ff, 0x05)
            self.myWrite16(0x0100, 0x05)
            self.myWrite16(0x0199, 0x05)
            self.myWrite16(0x01a6, 0x1b)
            self.myWrite16(0x01ac, 0x3e)
            self.myWrite16(0x01a7, 0x1f)
            self.myWrite16(0x0030, 0x00)
    #  writeReg System__Fresh_OUT_OF_Reset
            # self.myWrite16(0x0016, 0x00),
        def default_settings(self):
            # Enables polling for ‘New Sample ready’ when measurement completes
            self.myWrite16(0x0011, 0x10)
            self.myWrite16(0x010A, 0x30)  # Set Avg sample period
            self.myWrite16(0x003f, 0x46)  # Set the ALS gain
            self.myWrite16(0x0031, 0xFF)  # Set auto calibration period
            # (Max = 255)/(OFF = 0)
            self.myWrite16(0x0040, 0x63)  # Set ALS integration time to 100ms
            # perform a single temperature calibration
            self.myWrite16(0x002E, 0x01)
            # Optional settings from datasheet
            self.myWrite16(0x001B, 0x09)  # Set default ranging inter-measurement
            # period to 100ms
            self.myWrite16(0x003E, 0x0A)  # Set default ALS inter-measurement
            # period to 100ms
            self.myWrite16(0x0014, 0x24)  # Configures interrupt on ‘New Sample
            # Ready threshold event’
            # Additional settings defaults from community
            self.myWrite16(0x001C, 0x32)  # Max convergence time
            self.myWrite16(0x002D, 0x10 | 0x01)  # Range check enables
            self.myWrite16(0x0022, 0x7B)  # Eraly coinvergence estimate
            self.myWrite16(0x0120, 0x01)  # Firmware result scaler
        def identify(self):
            """Retrieve identification information of the sensor."""
            return {
                'model': self.myRead16(0x0000),
                'revision': (self.myRead16(0x0001), self.myRead16(0x0002)),
                'module_revision': (self.myRead16(0x0003),
                'date': self.myRead16(0x006),
                'time': self.myRead16(0x008),
        def address(self, address=None):
            """Change the I2C address of the sensor."""
            if address is None:
                return self._address
            if not 8 <= address <= 127:
                raise ValueError("Wrong address")
            self._set_reg8(0x0212, address)
            self._address = address
        def range(self):
            """Measure the distance in millimeters. Takes 0.01s."""
            self.myWrite16(0x0018, 0x01)  # Sysrange start
            return self.myRead16(0x0062)  # Result range valueimport ustruct


    import vl6180xb
    from machine import I2C
    i2c = I2C(0, I2C.MASTER, baudrate=100000, pins=('P9', 'P10'))
    vl61b = vl6180xb.Sensor(vl6180xb.i2c)
    while True:
    	# print("Getting sensor range...")

  • How do I change the register code to extend the time for each measurement and also use the lux calibration before each measurement? I guess I could specify the gain manually but also get it for each specific measurement but I still don't know how.

  • @jcaron aaah ofcourse. Did not even think about the time, it makes so much sense. I only need it to measure at most 10cm.
    Will try with time adjustment.
    I will only use the sensor to measure if the distance is greater than x. So the accuracy is not really that important.
    Thanks for the help

  • @Rasmus-Persson-0 did you check the datasheet? It makes it clear (section 2.7.1) that it takes a variable amount of time to measure range, depending on distance and reflectance.

    You have a fixed 10 ms delay between ranging start and reading the result, which may not always be enough (it can reach nearly 20 ms in some cases, possibly more if the reader manages to measure beyond 10 cm).

    Also, max range depends on reflectance and ambient light. In some cases it can be as low as 4 cm.

    You should check the error/status before reading the result. At least check the contents of registers 4D and 4F, though it’s unclear to me what is really the indicator of when ranging has completed and data is ready. I think bits 2:0 of 4F should be 4 before you can read the result.

    Finally, remember that this is a proximity sensor, designed to measure short distances (a few cm), not for longer distances.

  • I also need help setting up vl6080. Do you know if there will be a major difference in the code between mine and the x version?

Log in to reply

Pycom on Twitter