Newby : need help to calibrate VL53L0X sensors

I have some VL53L0X sensors that I would like to use in a ranging application. I need to do a horizontal and a vertical measurement and store the data to an SD card. I'm using a Teensy 3.6 board with the built-in uSD card. I have a basic sketch working. It initialized the sensor, takes a reading, and stores the value to the uSD card.

The problem I'm having is with the actual reading values. I'm using a tape measure as a reference and taking measurements every 6" from 6" to 48". I'm averaging 5 measurements to get an averaged reading. I'm seeing a consistent offset value from the reading compared to the actual distance. i.e. I get an average reading of around 6.85" at 6", 13.07" at 12", 19.26" at 18", etc.

Is there a way to calibrate the sensor prior to taking the measurements?

Thanks for any help.

You could make answering easier if you provided a link to the data sheet for the device. But I found it anyway. A quick look shows you exactly the calibration procedure.

Thanks for answering. The datasheet is at:
https://www.st.com/resource/en/data_brief/vl53l0x.pdf

I based my sketch on the example v53l0x.ino included when the library was installed. When you say a calibration procedure is shown, where is that? Is there some example code showing how I could incorporate a calibration at power up? Maybe a modified version of the vl53l0x.ino?

Thanks.

I see section 2.3 is about calibration.

I have tried the calibration and using "high-accuracy" with the VL53L0x but (so far) have not been able to get consistent results. I use a metal 4 foot ruler as a reference and take measurements at 6", 12", 18", 24", 30", 36", and 42". My results from run to run vary sometimes by an inch or more. I have tried multiple sensors (4 total) and the results vary between sensors and between runs. I'm attaching my code:

/* ------------------------------------------------------------------------------------------
 Name:     VL53L0X_high_accuracy_cal_v1_0.ino
 Project:  4D0221
 Version:  1.0
 Author:   D. F. Spencer
 Date:     11 Mar 2024
 
 ---- revision history ----
 ver   date         description
 1.0   10 Mar 2024  initial version

 ---- system hardware components ----
 1. Teensy 3.6
 2. Teensy 3.6 Internal Real Time Clock Module, battery-backed
 3. STI VL53L0X TOF Rangeing Sensor on I2C I/F
------------------------------------------------------------------------------------------ */

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

#include <Wire.h>
#include <VL53L0X.h> // Pololu library https://github.com/pololu/vl53l0x-arduino
#include <SD.h>
#include <SD_t3.h>
#include <SPI.h>
#include <TimeLib.h>    // Date/Time functions: internal RTC of Teensy 3.6


// ---- function prototypes
int ReadAveSensorVL53L0X();

// ---- sensor section
VL53L0X sensor;

#define HIGH_ACCURACY
#define RANGEMIN 30
#define RANGEMAX 1000

// ---- variables
#define POS_STEP 6          // position step size (in inches)

boolean isRunning = false;  // true:acquisition loop is running

int numSamps = 5;   // number of samples for averaging
int loopCntr = 0;   // position index
int mmVal;          // reading, mm
float inVal;        // reading, inches
float offsetVal;    // difference between reading and actual values
float posVal;       // position value, inches

// ---- hardware setup and pins
int momSw0 = 23;    // board pin 45 / pin 23 / pin A9 : switch input


void setup()
{
  pinMode (LED_BUILTIN, OUTPUT);     //Assign LED as output pin
  pinMode(momSw0, INPUT);     // switch input

  delay(2000);                  // start-up delay to allow system to settle
  digitalWrite(LED_BUILTIN, HIGH);  // short blink to indicate ready to start
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);

  Wire.begin();

  Serial.begin(115200);

  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)

  Serial.println("Waiting for Start...");
  while(digitalRead(momSw0) == HIGH)
    ;           // wait for start button

  isRunning = true;
}

void loop()
{
  if(isRunning == true)
  {
    loopCntr++;   // calibration position (*6 for inch position) (starts with 1)
    posVal = loopCntr * POS_STEP;
    
    mmVal = ReadAveSensorVL53L0X();  // reads numSamps averaged value, in mm
    inVal = mmVal / 25.4;
    
    Serial.print("distance (mm): ");
    Serial.print(mmVal);
    Serial.print("  (in): ");
    Serial.print(inVal);
    Serial.print("  nom (in): ");
    Serial.print(posVal);
    Serial.print("  offset (in): ");
    Serial.println(inVal - posVal);
    
    delay(1000);

    isRunning = false;      

    Serial.println("Waiting for Start...");
  }
  else
  {
    if(digitalRead(momSw0) == HIGH) // if no switch, indicate waiting
    {
      digitalWrite(LED_BUILTIN, HIGH);
      delay(50);
      digitalWrite(LED_BUILTIN, LOW);
      delay(100);
    }
    else
    {
      Serial.println("Starting...");
      isRunning = true;   // change to running mode again
    }
  }
}

int ReadAveSensorVL53L0X()
{
  int reading = 0;
  
  for(int i = 0; i < numSamps; i++)
  {
    reading += sensor.readRangeContinuousMillimeters();

    delay(10);  // short delay between readings
  }

  reading /= numSamps;

  return reading;
}

Has anyone used this sensor successfully with accurate and repeatable results? If so, what am I doing wrong or have I overlooked?

Thanks for any help.

What are you measuring? Consider that this sensor has FOV 25deg, so it is not very good for measuring small objects. Also consider surface of the object.

Thanks for responding.

My target is a white cardboard box with dimensions of roughly 7" x 7". In addition, I elevated the sensor from the work bench by about 5". I also reduce any other light sources from influencing the readings. The readings are showing roughly correct values for the range but not consistent. I'm attaching some test results to explain.

Sensor Calibration Tests						
Sensor 1						
4D0221						
11 Mar 2024						
Nominal = Nominal measurement stage value (inches)						
Meas = Measured value (inches)						
Ameas = Average of three Meas values (inches)						
Adiff = Average difference Ameas – Nominal (inches)						
Meas -Adiff = Measured value – Adiff value (inches)						
Var% = ((Meas – Adiff)/Meas)*100						
Nominal	Test	Meas	Ameas	Adiff	Meas-Adiff	Var%
6.00	1	8.98	8.97	2.97	6.01	0.22
6.00	2	9.02			6.05	0.89
6.00	3	8.90			5.93	-1.11
12.00	1	15.39	15.33	3.33	12.06	0.53
12.00	2	15.35			12.02	0.19
12.00	3	15.24			11.91	-0.72
18.00	1	21.54	21.37	3.37	18.17	0.96
18.00	2	21.34			17.97	-0.15
18.00	3	21.22			17.85	-0.81
24.00	1	27.44	27.30	3.30	24.14	0.60
24.00	2	27.28			23.98	-0.07
24.00	3	27.17			23.87	-0.53
30.00	1	33.46	33.33	3.33	30.13	0.42
30.00	2	33.43			30.10	0.32
30.00	3	33.11			29.78	-0.74
36.00	1	39.61	39.45	3.45	36.16	0.44
36.00	2	39.53			36.08	0.22
36.00	3	39.21			35.76	-0.67
42.00	1	45.59	45.43	3.43	42.16	0.38
42.00	2	45.39			41.96	-0.10
42.00	3	45.31			41.88	-0.29

At first glance, it appears the readings are just long by about 3". If this were the case, it would be easy to adjust for. The problem is, the next time I run the tests, I get different readings where the values may be off by only 1 1/2".

Too much...
Try to measure distance to white wall indoors. Did you try to raise timingbudget? 300ms.

It seems this sensor may not be practical for my application. In looking at the described FOV of 25 degrees, at 48" distance the target would have to be about 21" wide. Is there a better sensor with a more narrow FOV that would range accurately at about 48" with a target about 7" or 8" wide? ...that is... without breaking the bank? I've looked at the handheld Ames 64001 (available from Harbor Freight) and it works very accurately with a narrow target, even at distances much greater than 48". Is there a modular version similar to this available that could be externally controlled and read by an Arduino or a PIC?

It doesn't mean you can't measure object smaller than full FOV, but everything within is "seen" by the sensor. If there are not other objects near to target, it should not be an issue.
I can't give recommendations for specific sensor, but you could have a look at Sharp IR sensors, narrow beam ultrasonics, lidar, laser rangefinder sensors... If measurement speed is not critical and max distance is 1m, you should have plenty of choices. All of them have pros and cons.
But even your actual sensor should fit there...

Try the wall test I proposed above, if your measurements are still inconsistent, your problem is not related to FOV.

Thanks for your help...

You're welcome. Update when you solve it.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.