VL53L0X time-of-flight distance sensor for speed measurement

Hi! I am trying to develop a speed measurement system based on the distance sensor VL53L0X. The idea is to set the sensor in one side of the object whose speed I want to measure. The object would move along a corridor with a number of protrusions, separated by equal distances of 20,0 cm (this distance is modifiable, but it should not be much greater than this, because the corridor would be too long!).
The sensor gives me back the distance measure, which -using an ‘‘if’’ function- I use as 0-1 to calculate the time consumed between consecutive protrusions. The distance and velocity measures appear on a screen.

I have been able to measure velocity, but at a very slow pace (no more than 0,2 m/s) that is not enough for my application.The distance measurement is accurate, but I guess the sensor is not good at calculating sudden changes at high speed (from 200 mm to 500 mm aprox. in less than a second). I suppose the problem has something to do with this, but I am not sure if it could also be related to the library I use and the variable that saves the distance value.

Has anyone tried to make a similar project with this sensor? Have you found these problems?

I would be very grateful if someone could help me with this.

I attach here a copy of my code.

#include <Wire.h>
#include <VL53L0X.h>
#include <MedianFilter.h>
#include <LiquidCrystal_I2C_AvrI2C.h>


VL53L0X sensor;

MedianFilter test(10, 0);
LiquidCrystal_I2C_AvrI2C lcd(0x27, 20, 4);
unsigned long timeBefore = 0;  //Time reference to compare
unsigned long timeConsumed = 0;  
int faraway=HIGH; 
float speedmm=0; //Speed in mm/s
float distance=0.2; //distance between protrusions
float speedm=0; //speed in m/s

// Uncomment this line to use long range mode. This
// increases the sensitivity of the sensor and extends its
// potential range, but increases the likelihood of getting
// an inaccurate reading because of reflections from objects
// other than the intended target. It works best in dark
// conditions.
//
#define LONG_RANGE

// Uncomment ONE of these two lines to get
// - higher speed at the cost of lower accuracy OR
// - higher accuracy at the cost of lower speed

#define HIGH_SPEED
//
//#define HIGH_ACCURACY



void setup()
{
  Serial.begin(9600);
  Wire.begin();
  sensor.init();
  sensor.setTimeout(500);
  lcd.begin();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("WELCOME");

#if defined LONG_RANGE
//  // lower the return signal rate limit (default is 0.25 MCPS)
//  sensor.setSignalRateLimit(0.1);
//  // increase laser pulse periods (defaults are 14 and 10 PCLKs)
//  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
//  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
#endif
//
#if defined HIGH_SPEED
//  // reduce timing budget to 20 ms (default is about 33 ms)
//  sensor.setMeasurementTimingBudget(20000);
#elif defined HIGH_ACCURACY
//  // increase timing budget to 200 ms
//  sensor.setMeasurementTimingBudget(200000);
#endif

  // Clear the buffer.
  
  
}

void loop()
{
  int o,r = sensor.readRangeSingleMillimeters();
  test.in( r );
  o = test.out();
  if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }
  lcd.setCursor(0, 0);
  lcd.print("DISTANCE           ");
  lcd.setCursor(0, 1);
  lcd.print(o);
  if(o>500){  //No-protrusion
    lcd.setCursor(0, 2);
    lcd.print("FARAWAY...    ");
    faraway=1;
    }
  if(o<500 and faraway==1){ //Protrusion
    timeConsumed = (millis()-timeBefore); //It calculates the time between protrusions
    lcd.setCursor(0, 2);
    lcd.print("NEAR...      ");
    faraway=0;
    speedmm=distance*1000000/timeConsumed;
    speedm=speedmm/1000;
    lcd.setCursor(0, 3);
    lcd.print(speedmm);
    Serial.print(speedmm);
    Serial.println();
    timeBefore=millis(); //Time actualization
    }
}

The code you have offers the option to sample distance in 20 millisecond intervals, for about 50 samples/second. It is "commented out" at the moment, and although the data sheet is not clear, you probably can't sample much faster.

#if defined HIGH_SPEED
//  // reduce timing budget to 20 ms (default is about 33 ms)
//  sensor.setMeasurementTimingBudget(20000);

It takes at least two sample intervals to detect a distance change.

So, 20 cm/40 ms is about 5 m/s, which is the maximum speed that can be measured. At present you are using the default 30 samples/second, so the maximum speed you can detect is 3 m/s.

However, the loop() function is spending most of its time printing on the LCD and the serial monitor. Get rid of the LCD printing, and change the serial.begin() Baud rate from 9600 to as fast as it can go (try 115200). Or, don't print at all unless you need to.

Thank you jremington! I had already changed the code to the HIGH_SPEED mode. I've changed the Baud rate to 2000000 and everything is going much faster!

However, I still have problems. I have found that probably the errors have to do with the sensor's detection. The sensor has problems to detect distance changes at a very high pace, above all if the surfaces are not completely white. I am doing some test with different surfaces but, even when I use white panels, it is difficult to get the right conditions. The highest speed I have reached was 1 m/s. This should be enhough for my application, the problem is that it doesn't always work.

I don't really know what to do in this point :confused: . Has anyone done some test with this sensor and could help me to get better conditions for measurement? Do you have more ideas of what could be going wrong?

Are you still printing to the slow LCD display?

GabiRub: I don't really know what to do in this point :confused: . Has anyone done some test with this sensor and could help me to get better conditions for measurement? Do you have more ideas of what could be going wrong?

These sensors work best in low low light conditions. Sunlight coming through windows or high intensity lighting will greatly reduce the sensitivity. For increased sensitivity try using retroreflective tape (the type with the tiny prisms under plastic) or the reflector from a bicycle.

Does the data sheet say anything at all about moving targets? If not then you may be trying to use it in a way for it was never designed.

When I researched these a year ago suggested applications included detecting when a mobile phone was held against a person's head and detecting when a persons hands were placed under a fan dryer. In both cases the targets were effectively stationary or very slow moving. I didn't see anything about using these to detection motion, for example, to trigger the opening of an automatic door as someone walks towards it.

jremington: Are you still printing to the slow LCD display?

I've tried with and without the LCD display and it doesn't make a great difference! The main issue seems to be the sensor's detection, rather than the code's time of ejecution. Thank you for your help jremington!

Thank you for sharing your experience mikb55. Effectively, the data sheet says nothing about moving targets, so you are probably right- the sensor was perhaps not designed for this application. In any case, I will do some tests with retroreflective tape, it looks like a great idea!