Velocity Measurement with Adafruit VL53L0X TOF (Time of Flight) Sensor

Hi, so I've run into an issue trying to calculate velocity from the distance data from the Adafruit VL53L0X TOF (Time of Flight) sensor. Basically, I can't get the program to pause between measurements, so that I can calculate speed between two points.

Here's my sensor setup (incase its important):

#include "Adafruit_VL53L0X.h"
Adafruit_VL53L0X lox = Adafruit_VL53L0X();

void setup() {
  Serial.begin(115200);

  // wait until serial port opens for native USB devices
  while (! Serial) {
    delay(1);
  }
  
  Serial.println("Adafruit VL53L0X test");
  if (!lox.begin()) {
    Serial.println(F("Failed to boot VL53L0X"));
    while(1);
  }
  // power 
  Serial.println(F("VL53L0X API Simple Ranging example\n\n")); 
}

And here's my speed detection function.

double speedDetection(){
  VL53L0X_RangingMeasurementData_t measure;

  if (measure.RangeMilliMeter < 2000){
    distanceA = measure.RangeMilliMeter;
    timeA = millis();
  }
  
  delay (30);
  
  if (measure.RangeMilliMeter < 2000){
    distanceB = measure.RangeMilliMeter;
    timeB = millis();
  }
  
  speed = (((distanceA-distanceB)/(timeB-timeA)));
  return speed;
  
}```

My output is always either zero or nan.

Help would be greatly appreciated.

Can you make a drawing of the geometry of your project? Is your test subject directly in line with the sensor laser beam? Are you getting a proper measurement of distance when the object is not being moved?

Paul

Welcome to the forum!

Your code does not guarantee that TimeA, DistanceA, etc. are all meaningfully defined, before speed is calculated, so most of the time the function will return nonsense.

Think about what happens if both if conditions are false.

Please, ALWAYS post all of your code. We often need to see how things are defined in order to find mistakes.

Your code doesn't guarantee that timeA, timeB, distanceA or distanceB are even set!!

I'd suggest restructuring like this:

  if (measure.RangeMilliMeter < 2000){
    distanceA = measure.RangeMilliMeter;
    timeA = millis();
  
    delay (30);
  
    if (measure.RangeMilliMeter < 2000){
      distanceB = measure.RangeMilliMeter;
      timeB = millis();

      speed = (((distanceA-distanceB)/(timeB-timeA)));  // only perform this if all 4 variables actually defined
      return speed;
    }
  }
  return INVALID_READING ;

Thank for those notes. I have taken @MarkT 's suggestion and re-structured my code such that it guarantees all four variables are set before calculating speed. I will list that new code (the full program this time) below, as well as the serial monitor output when moving an object in front of the sensor.

@Paul_KD7HB I can make a drawing if necessary, but my setup is just an object in line with the sensor beam, being moved closer or further. I get proper measurements of distance both when the object is being moved and when it is stationary.

#include "Adafruit_VL53L0X.h"

Adafruit_VL53L0X lox = Adafruit_VL53L0X();

int distance;
double distanceA;
double distanceB;
double timeA;
double timeB;
double speed;

void setup() {
  Serial.begin(115200);
  pinMode(6,OUTPUT);
  pinMode(2,OUTPUT);
  
  digitalWrite(6,LOW);
  digitalWrite(2,LOW);

  // wait until serial port opens for native USB devices
  while (! Serial) {
    delay(1);
  }
  
  Serial.println("Adafruit VL53L0X test");
  if (!lox.begin()) {
    Serial.println(F("Failed to boot VL53L0X"));
    while(1);
  }
  // power 
  Serial.println(F("VL53L0X API Simple Ranging example\n\n")); 
}

double speedDetection(){
VL53L0X_RangingMeasurementData_t measure;
  
//SPEED DETECTION CODE AS SUGGESTED BY MARK T
  if (measure.RangeMilliMeter < 2000){
    distanceA = measure.RangeMilliMeter;
    timeA = millis();
  
    delay (30);
  
    if (measure.RangeMilliMeter < 2000){
      distanceB = measure.RangeMilliMeter;
      timeB = millis();

      speed = (((distanceA-distanceB)/(timeB-timeA)));  // only perform this if all 4 variables actually defined
      return speed;
    }
  }

//// MY OLD SPEED DETECTION CODE
//  if (measure.RangeMilliMeter < 2000){
//    distanceA = measure.RangeMilliMeter;
//    timeA = millis();
//    delay(30);
//  }
//
//  
//  if (measure.RangeMilliMeter < 2000){
//    distanceB = measure.RangeMilliMeter;
//    timeB = millis();
//  }
//  
//  speed = (((distanceA-distanceB)/(timeB-timeA)));
//  Serial.print("Speed");
//  return speed;
}

double distanceDetection(){
  VL53L0X_RangingMeasurementData_t measure;
  lox.rangingTest(&measure, false); 
  if (measure.RangeMilliMeter!= 4){
    distance = measure.RangeMilliMeter;
    return(distance);
  }
}

void loop() {
  Serial.print("SPEED: "); Serial.println(speedDetection());      
  Serial.print("DISTANCE: "); Serial.println(distanceDetection());      
}

Selection of Serial Monitor Outputs:
DISTANCE: 163.00
SPEED: 0.00
DISTANCE: 176.00
SPEED: 0.00
DISTANCE: 151.00
SPEED: 0.00
DISTANCE: 160.00
SPEED: 0.00
DISTANCE: 153.00
SPEED: 0.00
DISTANCE: 164.00
SPEED: 0.00
DISTANCE: 189.00
SPEED: 0.00
DISTANCE: 194.00
SPEED: 0.00
DISTANCE: 203.00

Thank you for the suggestions. I have tried those changes (code and output posted in the link below) and unfortunately have the same results.

Try printing the values of the variables used in the speed calculation.

Thank you so much, I did that, and was able to pinpoint the problem. I noticed that my distance values were outputting as zero. Which made me realize I missed an essential line of code when implementing @MarkT 's suggestion

  lox.rangingTest(&measure, false); 

Adding this made the code work. Thank you both so much! I have posted the working code below, so if anyone runs into similar problems to me in the future they have something to reference.

#include "Adafruit_VL53L0X.h"

Adafruit_VL53L0X lox = Adafruit_VL53L0X();

int distance;
double distanceA;
double distanceB;
double timeA;
double timeB;
double speed;

void setup() {
  Serial.begin(115200);

  // wait until serial port opens for native USB devices
  while (! Serial) {
    delay(1);
  }
  
  Serial.println("Adafruit VL53L0X test");
  if (!lox.begin()) {
    Serial.println(F("Failed to boot VL53L0X"));
    while(1);
  }
  // power 
  Serial.println(F("VL53L0X API Simple Ranging example\n\n")); 
}

double speedDetection(){
VL53L0X_RangingMeasurementData_t measure;
  
//SPEED DETECTION CODE AS SUGGESTED BY MARK T
  if (measure.RangeMilliMeter < 2000){
    lox.rangingTest(&measure, false); 
    distanceA = measure.RangeMilliMeter;
//    Serial.print("Distance A: "); Serial.println(distanceA);      
    timeA = millis();
//    Serial.print("Time A: "); Serial.println(timeA);      
    delay (30);
  
   if (measure.RangeMilliMeter < 2000){
     lox.rangingTest(&measure, false); 
     distanceB = measure.RangeMilliMeter;
//     Serial.print("Distance B: "); Serial.println(distanceB);      
     timeB = millis();
//     Serial.print("Time B: "); Serial.println(timeB);      

     speed = (((distanceA-distanceB)/(timeB-timeA)));  // only perform this if all 4 variables actually defined
     return speed;
   }
  }

double distanceDetection(){
  VL53L0X_RangingMeasurementData_t measure;
  lox.rangingTest(&measure, false); 
  if (measure.RangeMilliMeter!= 4){
    distance = measure.RangeMilliMeter;
    return(distance);
  }
}

void loop() {
  Serial.print("SPEED: "); Serial.println(speedDetection());      
  Serial.print("DISTANCE: "); Serial.println(distanceDetection());     
}