For many of my applications I need to measure a distance. I have used ultrasonic sensors, but there view angle (beam) is not able to detect smaller objects, it very much depends on the object surface and angle, it is slow and not very precise. I have used infrared sensors, but here again it depends on the infrared reflection of the object in range, it depends the amount of reflected light is not really telling much about the distance, and yet IR reflection is subject of material and object targeted.
But there is yet another sensor type to consider: ToF! ToF (or Time-of-Flight) sensors have a built-in LIDAR: The sensor is sending out light pulses and measures how much time it takes for the light to come back. Similar to ultrasonic sensors (see “Tutorial: Ultrasonic Ranging with the Freedom Board“), but instead of ultrasonic it uses an infrared laser light. Or think about a radar system using an infrared laser light.
STMicroelectronics calls its technology ‘FlightSense’. It uses a SPAD (Single Photon Avalanche Diode) array and a VCSEL (Vertical Cavity Surface-Emitting Laser), combined with an ALS (Ambient Light Sensor) on the VL6180x. The ToF technology starts to be used in more and more applications: from gesture recognition, human presence detection in public transportation up to detect and measure object distances (e.g. how far a mobile phone is from the ear to adopt the audio volume).
The STMicroelectronics VL6180X sensor is a very small one. Its LGA package makes it a bit difficult to solder it, at least with my SMD soldering skills (my students are by far better!). That’s why breakout modules from Pololu , Sparkfun or Adafruit are a good starting point. Additionally the VL6180X device is operating at 2.8V: the breakout modules include the necessary voltage generator and level shifter to use the module in 3.3V or 5V systems. The sensor uses IR light at 850 nm and the VL6180X comes with an extra ALS (Ambient Light Sensor):
The sensor is specified for ranging up to 10 cm with a resolution of 1 mm, but I have found it works fine with the default settings and good conditions up to about 20 cm. There range scaling factor which can be used:
The range scaling is not mentioned in the data sheet, but mentioned in UM1876.
Below a picture of the Pololu breakout module:
Remove the I2C pull-ups if using multiple sensor boards on the same bus, or if the I2C bus already has pull-ups attached.
The board has the following pins (left-to-right in the picture below):
Using a single sensor, only SCL, SDA, GND and VIN are needed. Below is how I have wired it up with a tinyK20 microcontroller board:
To read and write the device registers over I²C, I’m using the following routines with the GenericI2C (GI2C1) driver:
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 |
|
The sensors need a special initialization sequence, explained in AN4545 and DT0037:
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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
|
The sensor offers multiple modes (continuous and single shot). The easiest one is the single shot ranging. The function below stores the measured value the pointer passed to the function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Because it takes some time until the result is ready, the function below waits until the result is ready:
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 |
|
The same principle is used to read the ambient light level:
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 |
|
On the MINT Robot (see “MINTomat: World’s Most Complicated Bubble Gum Automata?“) we are using multiple sensors:
Because the sensors by default use the same I²C address, the sensors have to enabled one after each other while assigning different I²C device addresses. For this, the CE pin is used to enable one sensor after each other. A GPIO pin (input/output, default after reset as input pin) for each module is used:
The code below demonstrates how to do this inside a FreeRTOS task:
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 |
|
An example project is available on GitHub. It is a simple bare-metal application which initializes the sensor and then reports the reading on the console/UART:
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 |
|
The output looks like this:
With the STMicroelectronics VL6180X I’m able to measure very accurately distances for robotics and gesture recognition. The VL6180X works up to 60 cm, for longer distances the VL53L0X (up to 2 m) should be considered.
An example project is available on GitHub.
Happy Flying