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?
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.
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?
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?
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.
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.
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".
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.