VL53L0X not very accurate at all

Hej,

testing the VL53L0X in a stable jig, I obtain very different distances measured, depending on the type of object/material…

77 mm measured manually

55 mm shiny aluminium (extrusion)
67 mm coated/lacquered paper (Beginning C for Arduino book cover)
68 mm satin stainless steel (Mitutoyo slide rule)
71 mm anodised aluminium (iPad back)
77 mm near black matt rubber (iPad cover)
79 mm rough plank o’ maple
86 mm human skin

These measurements are repeatable after resetting the Metro Mini or while interchanging the objects.

Is this to be expected? Are there some settings in the Pololu library or other tricks how one can get something far more predictable?

In STMicroelectronics PDF from 2017 on page 4 it says that reflectance of object is not an issue : (

Any assistance much appreciated!

/******* VL53L0X distance meter (with OLED display and piezoelectronic buzzer) *******/

/******* LIBRARIES *******/

#include <Wire.h>
#include <VL53L0X.h> // Pololu library https://github.com/pololu/vl53l0x-arduino
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

/******* FUNCTION PROTOTYPES *******/

int ReadSensorVL53L0X();
float WeightedAverageFilter(float incomingValue, float lastValue);
void WriteToDisplaySSD1306 (int distance);

/******* SENSOR *******/

VL53L0X sensor;

#define HIGH_ACCURACY
#define RANGEMIN 30
#define RANGEMAX 1200
#define VL53L0X_CORR 0 // Correction factor of 15 mm from table surface
#define WAF_WEIGHT 0.2 // Factor for the weighted average filter; higher = less smoothing

float lastDistance = 0;
float currentRange = RANGEMAX - RANGEMIN;

/******* DISPLAY *******/

#define OLED_RESET 4

Adafruit_SSD1306 display(OLED_RESET);

/******* FUNCTIONS *******/

void setup() {
  Wire.begin();

  Serial.begin(9600);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3D); // Default I2C address (for 0x3C connect SA0 pin to GND)
  display.setRotation(2); // Rotates display 180°
  display.clearDisplay();

  sensor.init();
  sensor.setTimeout(0); // Set sensor timeout in milliseconds (0 = no timeout)
  sensor.startContinuous(100); // Sensing interval four times per second
  sensor.setMeasurementTimingBudget(100000); // For HIGH_ACCURACY mode (default = 33)
}

void loop() {
  int distance = ReadSensorVL53L0X();
  float currentDistance = WeightedAverageFilter(distance, lastDistance);
  lastDistance = currentDistance;
  if (currentDistance > RANGEMIN && currentDistance < RANGEMAX) {
    WriteToDisplaySSD1306 (currentDistance);
  }
  else {
    Serial.println("Out of range!");
    display.display(); // Tell display to display nothing
    display.clearDisplay();
  }
}

int ReadSensorVL53L0X() {
  int reading = sensor.readRangeContinuousMillimeters();
  reading = reading + VL53L0X_CORR;
  return reading;
}

float WeightedAverageFilter(float incomingValue, float lastValue) { // See https://www.tigoe.com/pcomp/code/arduinowiring/37/
  float result = WAF_WEIGHT * incomingValue + (1.0 - WAF_WEIGHT) * lastValue;
  return result;
}

void WriteToDisplaySSD1306 (int distance) {
  display.setCursor(8, 20); // x,y co-ordinates
  display.setTextSize(3);
  display.setTextColor(WHITE); // Monochrome, BLACK would erase
  display.println(distance); // Reading from sensor
  display.setCursor(86, 20);
  display.setTextSize(3);
  display.println("mm");
  display.display(); // Tell display to display everything
  display.clearDisplay(); // Clears the display
}

Hello.

Can you post pictures of your testing jig and the objects you are testing?

-Nathan

Hej Nathan,

thanks for replying. I took it apart. It was one, two and three layers of tomato pulp cans to each side, away from the cone of the sensor, with each object, all objects being flat, placed across ; ) The objects are listed in my original post; I think my photography skills will fall short of online images of the things. This is what I obtained with a large fairly white matt postcard…

I probably do some more “rigorous” testing, again, but since the lighting was controlled, the objects were placed at the same height and not moving, the results are quite telling. I also tested all at a different height and got this:

203 (77) mm measured manually, same ambient light conditions as before, room temperature also

176 174 (55) mm shiny aluminium (extrusion)
197 192 (67) mm coated/lacquered paper (Beginning C for Arduino book cover)
193 189 (68) mm satin stainless steel (Mitutoyo slide rule)
205 203 (71) mm anodised aluminium (iPad back)
214 211 (77) mm near black matt rubber (iPad cover)
215 213 (79) mm rough plank o’ maple
220 219 (86) mm human skin

So, the iPad won : D

First row numbers are with weighted averaging disabled, numbers fluctuate much and are averaged by eye ; )

The shiny aluminium, shiny book cover and human skin are the worst. Maybe it’s just the limit of this ultra low-price sensor, compared to those from Bosch, Balluff or Garmin, costing from €50 upwards.

I set up a test here with a piece of white board moved by a stepper motor and then covered the board in aluminum foil. The foil covered board produced different distance measurements than the white board itself. We would still consider this sensor to be more accurate than our Sharp IR distance sensors and sonar range finders, but it appears that the material can have a slight effect on the measurement.

Here is a graph that shows how the average of 250 measurements (with the standard deviation those measurements) differs from the actual distance for tests with whiteboard material and aluminum foil. So for close measurements, the average was closer to the actual for the whiteboard, but further away (past about 200mm) the foil surface produced more accurate measurements. I used a timing budget of 50000us for those measurements.

Whiteboard%20compaired%20to%20aluminum

-Nathan

Alright, thanks, that’s a good one, using a stepper motor for repeatable measurements. It shows that this sensor ain’t no digital ruler. I suppose my beginner’s expectation was too high. If you could be so kind, could you post the code/settings according to the Pololu library you used for continuous measurement? I’d like to compare that to what I used above.

Meanwhile, I saw the new VL53L1X, which is a follow-up that, to a degree (which degree, though), addresses some problems the old VL53L0X has in broad daylight. It has tiny lenses that concentrate the incoming reflected light, also shielding the receptacle hole to a certain degree from stray light ingress. Do you sell that one, too? Is there a library for it already? Worth comparing.

I also learned from automotive electronics discussions that the Asian and European car industry almost exclusively uses low-cost Murata ultrasonic sensors in the cars’ bumpers for parking aids, so I’ll try to get one of those also.

The code (shown below) is pretty straight forward. I used a spreadsheet to calculate the average and standard deviation of the 250 measurements taken at each distance.

We do have a carrier board with the new VL53L1X on it and an Arduino library for simple measurement functionality for it.

I would not expect parking assistance in a full sized automobile to be an application that requires more accuracy than a few centimeters, but we would be interested to see how sensors like those compare.

-Nathan

#include <SPI.h>
#include <AMIS30543.h>
#include <Wire.h>
#include <VL53L0X.h>

const uint8_t amisDirPin = 1;
const uint8_t amisStepPin = 0;
const uint8_t amisSlaveSelect = 4;

AMIS30543 stepper;
VL53L0X sensor;

void setup()
{
  Serial.begin(115200);
  delay(100);
  Wire.begin();
  SPI.begin();
    
  stepper_init();

  sensor.init();
  sensor.setTimeout(500);

  sensor.setSignalRateLimit(0.1);
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange,14);
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange,10);
  sensor.setMeasurementTimingBudget(50000);

  //stepper.disableDriver();
  delay(10000);
  Serial.println("Ready to start");

  for (int i = 0; i<10; i++){
    //Take 250 measurements
    for (unsigned int x = 0; x < 250; x++){
      Serial.print(i);
      Serial.print(" ");
      Serial.println(sensor.readRangeSingleMillimeters());
    } 
    //move 30mm
    for (unsigned int x = 0; x < 2387; x++){
      step();
    } 
  }
  stepper.disableDriver();
}

void loop(){

}

Ok, thanks!

Holidays came in between, but I should receive the pololu VL53L1X breakout board this week, and then I hope to compare as good as I can.

@systembolaget did you achieve more accurate results with the VL53L1X sensor?

Yes, I did. This sensor is better. But don’t expect it to do wonders.

The biggest issue with these kind of sensors seems to be colour and reflectivity of what is being measured; see my list in an above post and what nathan did with a more controlled set-up.

You cannot use these sensor as a 0-2 metres digital ruler, but rather as some kind distance indicator, which is fine for applications where the accurate distance is not critical.

No surprise that professional laser-based distance meters start from €200 and go to well over €1000.