VL53L0X Lidar Sensor Range Detection

Hi Arduino family,

I have reached the end of my knowledge. I am trying to use the VL53L0X sensor to simply turn on/off LED’s by swiping my hand or fingers across the sensor at a specific distance.

I tried to annotate my code to the best of my abilities. :o

I am trying to understand how to get the measurement, see if it falls between 20 and 200 mm, and add to the count (for the switch statement) if it’s in the range.

The sensor is attached via 3.3V-Vin, SCL-SCL, SDA-SDA, GND-GND (and works using example library code from Adafruit)

#include "Adafruit_VL53L0X.h" //Including an Adafruit Library for the sensor
Adafruit_VL53L0X lox = Adafruit_VL53L0X(); 

int wLED = 3;  // Orange and White LED's are the outputs
int oLED = 4;  // See above
int buttonPushCounter = 0; // Used in the switch statement below

long time = 0; // Time since last action occured 
long debounce = 200; // Debounce time to increase if the output is flickering

void setup() {
  Serial.begin(9600); // 9600 baud
  
  while (! Serial) { // wait until serial port opens for native USB devices
    delay(1);
  }
  pinMode(wLED, OUTPUT); //Both LED's are outputs 
  pinMode(oLED, OUTPUT);
  
  Serial.println("Adafruit VL53L0X test"); //The following lines of the setup print to verify proper boot
  if (!lox.begin()) {
    Serial.println(F("Failed to boot VL53L0X"));
    while(1);
  }
  // power 
  Serial.println(F("VL53L0X API Simple Ranging example\n\n")); 
}


void loop() {
  VL53L0X_RangingMeasurementData_t measure; //Bringing in measurement data

if (measure.RangeMilliMeter >20 && measure.RangeMilliMeter <200 && millis() - time > debounce){ // The purpose of this line is to detect if the range is between 20 and 200 mm and if there has been enough time since last occurance (SUPER STUCK HERE!)
  buttonPushCounter++; // Switch statement 
  delay(300);
  Serial.println("Motion range detected"); // Print for verification
}

switch(buttonPushCounter){
    case 1:                   // 1st swipe turns on only the white LED
      digitalWrite(wLED, HIGH);
      digitalWrite(oLED, LOW);
      break;
    case 2:                   // 2nd swipe turns on only the orange LED
      digitalWrite(wLED, LOW);
      digitalWrite(oLED, HIGH);
      break;
    case 3:                   // 3rd Swipe turns off both LEDs and resets count
      digitalWrite(wLED, LOW);
      digitalWrite(oLED, LOW);
      buttonPushCounter = 0;
      break;
      }
 

}

Any constructive criticism and recommendations are welcomed!!! Thank you already, and happy Thanksgiving!

if (measure.RangeMilliMeter >20 && measure.RangeMilliMeter <200 && millis() - time > debounce){ // The purpose of this line is to detect if the range is between 20 and 200 mm and if there has been enough time since last occurance (SUPER STUCK HERE!)

Indeed… maybe consider when does variable “time” stop being equal to the “0” it was set at.

I added " time = millis();"

if (measure.RangeMilliMeter >20 && measure.RangeMilliMeter <200 && millis() - time > debounce){ // The purpose of this line is to detect if the range is between 20 and 200 mm and if there has been enough time since last occurance 
  buttonPushCounter++; // Switch statement 
  delay(300);
  Serial.println("Motion range detected"); // Print for verification
  time = millis(); 
}

into that portion of the code, thanks. It’s just not actually performing the code! The example code is below, and it works just fine…

#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")); 
}


void loop() {
  VL53L0X_RangingMeasurementData_t measure;
    
  Serial.print("Reading a measurement... ");
  lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!

  if (measure.RangeStatus != 4) {  // phase failures have incorrect data
    Serial.print("Distance (mm): "); Serial.println(measure.RangeMilliMeter);
  } else {
    Serial.println(" out of range ");
  }
    
  delay(1000);
}

I can’t explain my fix with science, but here’s what I have managed to get working:

I need to use the following code and nest an if statement inside of another if statement.

So this is within my loop:

 if (measure.RangeStatus != 4) {  // phase failures have incorrect data
    Serial.print("Distance (mm): "); Serial.println(measure.RangeMilliMeter);
    if (measure.RangeMilliMeter > 20 && measure.RangeMilliMeter < 200 && millis() - time > debounce){ // The purpose of this line is to detect if the range is between 20 and 200 mm and if there has been enough time since last occurance 
  buttonPushCounter++; // Switch statement 
  delay(300);
  time = millis(); 
}

I imagine it’s to make sure the status is functioning before it reads. Hope this helps another stranger like this forum has helped me!

Thanks folks.

Just bouncing your loop code lines around.

Not sure how much “time” the sensor needs between reads to function right. The example code used delay(1000).

So if this works at all, maybe play with debounce values to see where you get stable values.

I did not add state machine code, so the code should increment if you maintain your hand inside range.

#include "Adafruit_VL53L0X.h" //Including an Adafruit Library for the sensor
Adafruit_VL53L0X lox = Adafruit_VL53L0X(); 

int wLED = 3;  // Orange and White LED's are the outputs
int oLED = 4;  // See above
int buttonPushCounter = 0; // Used in the switch statement below

long time = 0; // Time since last action occured 
long debounce = 200; // Debounce time to increase if the output is flickering

void setup() {
  Serial.begin(9600); // 9600 baud
  
  while (! Serial) { // wait until serial port opens for native USB devices
    delay(1);
  }
  pinMode(wLED, OUTPUT); //Both LED's are outputs 
  pinMode(oLED, OUTPUT);
  
  Serial.println("Adafruit VL53L0X test"); //The following lines of the setup print to verify proper boot
  if (!lox.begin()) {
    Serial.println(F("Failed to boot VL53L0X"));
    while(1); has 
  }
  // power 
  Serial.println(F("VL53L0X API Simple Ranging example\n\n")); 
}


void loop() {
 
If ( millis() - time >= debounce ) {
 VL53L0X_RangingMeasurementData_t measure;
 time = millis();
}
    
if (measure.RangeMilliMeter >= 20 && measure.RangeMilliMeter <= 200) {
  buttonPushCounter++;
  Serial.println("Motion range detected");
 measure.RangeMilliMeter = 0;
}

switch(buttonPushCounter){
    case 1:                   // 1st swipe turns on only the white LED
      digitalWrite(wLED, HIGH);
      digitalWrite(oLED, LOW);
      break;
    case 2:                   // 2nd swipe turns on only the orange LED
      digitalWrite(wLED, LOW);
      digitalWrite(oLED, HIGH);
      break;
    case 3:                   // 3rd Swipe turns off both LEDs and resets count
      digitalWrite(wLED, LOW);
      digitalWrite(oLED, LOW);
      buttonPushCounter = 0;
      break;
      }
 

}

I gave it a try. It's a bit fidgety and doesn't like my commands outside of the first "if" statement. I wonder why there aren't more publications on this as it seems to be a standard device in the drone community.

Thanks for the help!

The code originally posted does not make any actual measurements.

This line (from the OP) just creates and defines a variable (structure) named "measure", and it certainly does not need to be within the loop function.

 VL53L0X_RangingMeasurementData_t measure;

Go back to the example code and make sure you understand what each line is doing before making modifications.

This is the line from the example code that actually makes the measurement.

  lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!

jremington:
Go back to the example code and make sure you understand what each line is doing before making modifications.

I have to admit I am very unaware of such matters. I've been finding the example codes a little abstract.

My understanding of the "measure" line is a sort of instance the code needs to run through each time we run the loop function.

I tried placing it in the setup and the code couldn't run because the "measure" variable wasn't initialized.

My question is this: where can I go to best understand the library? The github sources and API datasheets don't seem to simplify the matters. Are these the best places to go to learn about code libraries for hardware?

EDIT: Spelling

I tried placing it in the setup and the code couldn't run because the "measure" variable wasn't initialized.

Correct. When defined within a function, such as setup() or loop(), the "measure" variable is local, and visible only within that function.

Most people put such definitions in front (above) the setup() function, which makes it global and visible within functions. Like this:

#include "Adafruit_VL53L0X.h" //Including an Adafruit Library for the sensor
Adafruit_VL53L0X lox = Adafruit_VL53L0X();

int wLED = 3;  // Orange and White LED's are the outputs
int oLED = 4;  // See above
int buttonPushCounter = 0; // Used in the switch statement below

long time = 0; // Time since last action occured
long debounce = 200; // Debounce time to increase if the output is flickering

VL53L0X_RangingMeasurementData_t measure; //measurement data structure

void setup() {
...

This are among the many basic things you need to learn about C/C++ programming, and can be learned from the many tutorials on line.

CeaseNResist:
I gave it a try. It's a bit fidgety and doesn't like my commands outside of the first "if" statement. I wonder why there aren't more publications on this as it seems to be a standard device in the drone community.

Thanks for the help!

Check out using the Pololu Arduino library for VL53L0X