This is the ST”s Single Package VL6180X Proximity and Ambient Light Sensor that measures a range to a target object distance up to 20-centimeter or 60-centimeter range by reducing the resolution. The VL61850X uses TIME-TO-FLIGHT measurements with the use of infrared pulses for ranging, which delivers an accurate result independent of the color and surface of the target. Moreover, the distance and ambient light level measurements can be captured through the i2c(TWI) digital interface, compare to other optical proximity sensors, some sensor uses the intensity of reflected light to detect an object, whereas the VL6180 uses ST’s patented FlightSense technology to precisely measure how long it takes for emitted pulses of infrared laser light to reach the object and reflected back a detector, similar to a short-range LIDAR (Light Detection and Ranging) sensor.
The TOF (Time-Of-Flight) allows one to accurately determine the distance to a target within 1 mm resolution without the barrier reflectance affecting the measurement. This sensor is rated to perform a range of up 10 centimeters, however, it can often give a reading of up to 20cm with its factory settings. Furthermore, the ST’s VL6180X can be set to measure ranges of up to 60 cm by reducing the resolution. however, thriving at this longer distance will depend on the target and ambient. The VL6180 also includes an ambient light sensor, that can measure the light intensity which is illuminated. Ranging and ambient light readings are available through the i2C bus interface which is also used to configure the settings of the sensor, and two GPIO pins to set independently programmed and configure as interrupt outputs. These ST’s VL6180X is a great small-size leadless land grid array package it quite difficult to use. however, there are some videos available that you can mount the LGA package to a pre-holed prototyping PCB board but using 1/4 resistors and SMD capacitors.
The ST’s VL6180X operates at a voltage of 3v, making interfacing difficult for microcontrollers to operate at 3.3v or 5v. our schematics handle these issues and make it easier to get started using the sensor while maintaining the most comprehensive sizes possible.
As you can see from the schematics we used a Low-dropout Linear Voltage Regulator that provides a 2.8v as the requirement for the VL6180X, which allows us to drive the sensor to be powered from a 2.7 volts to 5.5 volts supply or getting the supply voltage from the microcontroller. For important technical details including the RANGE SCALING FACTOR Please see the datasheet bellow.
Requirements
- Arduino IDE | PlatformIO
- Test Boards :
- Note: The Diagram below is using Raspberry Pi PICO (please refer to your MCU’s respective pin-outs & bus configuration)
- Resistors (See below diagram for required value)
- Regulator (See below diagram for required value)
- Capacitor(See below diagram for required value)
- Resistors (See below diagram for required value)
- LED (SMD)
Wiring Diagram & Schematics
Sketch Source Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#include <Wire.h> #include <VL6180X.h> VL6180X sensor; void setup() { Serial.begin(9600); Wire.begin(); sensor.init(); sensor.configureDefault(); sensor.writeReg(VL6180X::SYSRANGE__MAX_CONVERGENCE_TIME, 30); sensor.writeReg16Bit(VL6180X::SYSALS__INTEGRATION_PERIOD, 50); sensor.setTimeout(500); // stop continuous mode if already active sensor.stopContinuous(); // in case stopContinuous() triggered a single-shot // measurement, wait for it to complete delay(300); // start interleaved continuous mode with period of 100 ms sensor.startInterleavedContinuous(100); } void loop() { Serial.print("Ambient: "); Serial.print(sensor.readAmbientContinuous()); if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); } Serial.print("\tRange: "); Serial.print(sensor.readRangeContinuousMillimeters()); if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); } Serial.println(); } |
CircuitPython
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
import time import board import busio import adafruit_vl6180x # Create I2C bus. i2c = busio.I2C(board.SCL, board.SDA) # Create sensor instance. sensor = adafruit_vl6180x.VL6180X(i2c) # You can add an offset to distance measurements here (e.g. calibration) # Swapping for the following would add a +10 millimeter offset to measurements: # sensor = adafruit_vl6180x.VL6180X(i2c, offset=10) # Main loop prints the range and lux every second: while True: # Read the range in millimeters and print it. range_mm = sensor.range print("Range: {0}mm".format(range_mm)) # Read the light, note this requires specifying a gain value: # - adafruit_vl6180x.ALS_GAIN_1 = 1x # - adafruit_vl6180x.ALS_GAIN_1_25 = 1.25x # - adafruit_vl6180x.ALS_GAIN_1_67 = 1.67x # - adafruit_vl6180x.ALS_GAIN_2_5 = 2.5x # - adafruit_vl6180x.ALS_GAIN_5 = 5x # - adafruit_vl6180x.ALS_GAIN_10 = 10x # - adafruit_vl6180x.ALS_GAIN_20 = 20x # - adafruit_vl6180x.ALS_GAIN_40 = 40x light_lux = sensor.read_lux(adafruit_vl6180x.ALS_GAIN_1) print("Light (1x gain): {0}lux".format(light_lux)) # Delay for a second. time.sleep(1.0) |
MicroPython
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
import ustruct import struct import time from machine import I2C # i2c = I2C(0, I2C.MASTER, baudrate=100000, pins=('P8', 'P9')) class Sensor: def __init__(self, i2c, address=0x29): self.i2c = i2c self._address = address self.default_settings() self.init() 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), 'big' ) 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), self.myRead16(0x0004)), '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 time.sleep(0.01) return self.myRead16(0x0062) # Result range valueimport ustruct |
PCB Board Milling / Gerber File
Downloads
- Download the ST’s VL6180X Datasheet | PDF
- Download VL6180X Sample Codes | Zip
- Download VL6180X Arduino Code Library | Zip
- Download VL6180X CircuitPython | Zip