VL53L5CX Does not range beyond 3000mm

I’ve been using VL53L5CX for a couple of weeks now in my office but once I moved to install on site I discovered that beyond about 2500mm the VL53L5CX does not provide consistent or reliable measurements. Around 3000mm the ranges that are returned vary wildly by about 300-500mm. Ranges less than 2500mm are consistent to within 10mm.

I have about a 10’ ceiling where the sensor is installed, pointing directly down at a concrete floor. In my code if I ignore results beyond 2500mm I can pretty reliably track a person as they walk through the 8x8 grid.

However, because the range is limited it cannot track a person as the enter the edge of the grid.

The sensor advertises a 4000mm range, but I’ve yet to see a measurement higher than about 3300mm.

I have also noticed (which another forum post mentions) the VL53L5CX will return 0 or the last known read when out of range. I am able to easily filter this out by ignoring any value that is the same on consecutive reads.

For context, my code (below) checks for changes in each quadrant and treats it like a coordinate grid. As a person walks closer to 0x0 (where the moon is located) the moon will increase in brightness (moon code not included).

I have read the documentation for the sensor. I don’t see anything in the docs about increasing the range to 4000mm.

#include <Wire.h>

#include <SparkFun_VL53L5CX_Library.h> //http://librarymanager/All#SparkFun_VL53L5CX

SparkFun_VL53L5CX myImager;
VL53L5CX_ResultsData measurementData; // Result data class structure, 1356 byes of RAM

int imageResolution = 0; // Used to pretty print output
int imageWidth = 0;      // Used to pretty print output

long measurements = 0;         // Used to calculate actual output rate
long measurementStartTime = 0; // Used to calculate actual output rate
int lastMeasureArray[64];
int ignoreStatic[64];
float distanceToMoon = 30;

void setup()
{
  Serial.begin(115200);
  delay(1000);
  Serial.println("SparkFun VL53L5CX Imager Example");

  Wire.begin(); // This resets I2C bus to 100kHz
  Wire.setClock(200000); //Sensor has max I2C freq of 1MHz

  //myImager.setWireMaxPacketSize(32); // Increase default from 32 bytes to 128 - not supported on all platforms

  Serial.println("Initializing sensor board. This can take up to 10s. Please wait.");
  if (myImager.begin() == false)
  {
    Serial.println(F("Sensor not found - check your wiring. Freezing"));
    while (1)
      ;
  }

  myImager.setResolution(8 * 8); // Enable all 64 pads
  // I have not tested these configurations yet:
  //myImager.setRangingMode(SF_VL53L5CX_RANGING_MODE.CONTINUOUS);
  //myImager.setSharpenerPercent(20);
  //myImager.setTargetOrder(SF_VL53L5CX_TARGET_ORDER.CLOSEST);

  imageResolution = myImager.getResolution(); // Query sensor for current resolution - either 4x4 or 8x8
  imageWidth = sqrt(imageResolution);         // Calculate printing width

  // Using 4x4, min frequency is 1Hz and max is 60Hz
  // Using 8x8, min frequency is 1Hz and max is 15Hz
  myImager.setRangingFrequency(1);

  myImager.startRanging();

  measurementStartTime = millis();
}

void loop()
{
  // Poll sensor for new data
  if (myImager.isDataReady() == true)
  {
    if (myImager.getRangingData(&measurementData)) // Read distance data into array
    {
      float newDistanceToMoon = 30;
      // The ST library returns the data transposed from zone mapping shown in datasheet
      // Pretty-print data with increasing y, decreasing x to reflect reality
      for (int y = 0; y < imageWidth; y++)
      {
        for (int x = 0; x < imageWidth; x++)
        {
          int arrayIndex = x + (y * imageWidth);
          float distanceMm = measurementData.distance_mm[arrayIndex];
          float change = abs(lastMeasureArray[arrayIndex] - distanceMm);
          float changePercent = change / distanceMm * 100; // unused
          //Serial.println(change);
          if(change > 10) { // this seems to effectively filter out errant reads
              if( ignoreStatic[arrayIndex] > 0) {
                if(distanceMm < 4000 && distanceMm > 600) {
                   Serial.print(distanceMm);
                  int xscale = x * 3; // arbitrary increase in scale makes variation easier to sus out
                  int yscale = y * 3;
                  float dist = sqrt((sq(xscale) + sq(yscale))); // moon is at 00
                  newDistanceToMoon = min(newDistanceToMoon,dist);
                } else {
                   Serial.print("[ ]");
                }
              } else {
                ignoreStatic[arrayIndex] = ignoreStatic[arrayIndex] + 1;
                 Serial.print("[ ]");
              }
          } else {
              if(ignoreStatic[arrayIndex] > 0) {
                ignoreStatic[arrayIndex] = ignoreStatic[arrayIndex] - 1;
              }
               Serial.print("[ ]");
          }
           Serial.print("\t");
          lastMeasureArray[arrayIndex] = distanceMm;
  
        }
         Serial.println();
      }
      //Serial.println();
      if(newDistanceToMoon > distanceToMoon) { // moving away
        distanceToMoon += (newDistanceToMoon - distanceToMoon) * .1;
      } else { // moving close
        distanceToMoon += (newDistanceToMoon - distanceToMoon) * .4;        
      }

      distanceToMoon = constrain(distanceToMoon,0,30);

      for(int b = 0; b <= distanceToMoon; b++) {
        //Serial.print("█ ");
      }

      //Serial.print(distanceToMoon);

      // Serial.println();
      Serial.println();

      //Uncomment to display actual measurement rate
      // measurements++;
      // float measurementTime = (millis() - measurementStartTime) / 1000.0;
      // Serial.print("rate: ");
      // Serial.print(measurements / measurementTime, 3);
      // Serial.println("Hz");
    }
  }

  delay(5); // Small delay between polling
}

Depending on lighting conditions a +/- 10% might be expected https://cdn.sparkfun.com/assets/6/e/3/0 … asheet.pdf

Try the default library in the dark https://learn.sparkfun.com/tutorials/qw … tancearray - what kind of accuracy are you seeing?

I used the library and have the same issue, but I should reconsider that maybe what’s throwing me is all the 0’s that the lidar is returning in the array. I assume that the 0s mean that the lidar was unable to see a reflection of the laser so it couldn’t range beyond 3 meters, but maybe there is some other reason it’s returning 0, like it’s reflecting off a perpendicular wall near the floor. The walls and floors are painted darkly.

I changed my approach with my code. I currently get a baseline for each sensor in the array, then I ignore all the 0s, then I watch for change of greater than 30cm from the baseline and I also ignore static by smoothing subsequent reads.

I also found that the target order, ranging mode and sharpening make a difference in the accuracy/consistency of the read. It’s been a lot of hours to get this figured out, and it wasn’t quite as seamless as I had originally hoped.