Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

VL53L1X non blocking communication

Hey,

I am using the vl53l1x on a raspberry pi with python (pimoroni library). However, to my knowledge and experience, by default the waiting method for measurement data is BLOCKING. So in Python the get_distance() function takes about as much time as the set timing budget or intermeasurement period, which is simply too time consuming for me.

What would I need to change in the api/core files to realize the non-blocking method or the physical interrupt driven method for the Raspberry Pi described in the docs from ST? I tried to change the “wait_method” in the api (vl53l1_api_core.c) for measurements to NON_BLOCKING and recompiled/reinstalled the module. But in python I still need about the same long duration for finishing the “get_distance()” line (from the Python module), I just want to get the distance measured by the sensor in a given frequency without having to wait for the data in a program blocking way.

Any help would be appreciated

Kind regards,

Malik

EDIT:

So I tried some stuff on my own, which unfortunately failed. Here is what i tried:

In the “vl53l1x_python.c” file I changed some lines in order to get a non-blocking reading

1.: Introduce new variable/pointer for the GetMeasurementDataReady function

static uint8_t MeasurementDataReady;

static uint8_t *pMeasurementDataReady = &MeasurementDataReady;

2.: change the getDistance() function

int32_t getDistance(VL53L1_Dev_t *dev)

{

VL53L1_Error Status = VL53L1_ERROR_NONE;

int32_t current_distance = -1;

uint8_t dataready= 0; //new

//Status = VL53L1_WaitMeasurementDataReady(dev); //dont want to wait

Status = VL53L1_GetMeasurementDataReady(dev, pMeasurementDataReady);

dataready = pMeasurementDataReady;//->pready; //is measurement finished //(which parameter is correct here, i dont quite know?)

if (dataready == 1){

Status = VL53L1_GetRangingMeasurementData(dev,

pRangingMeasurementData);

current_distance = pRangingMeasurementData->RangeMilliMeter;

VL53L1_ClearInterruptAndStartMeasurement(dev);

}

return current_distance;

}

So in my theory, this should return -1 for most of the time and the actual distance for when the measurement is done. But this doesn`t work like said before. The “if dataready ==1” conditition is probably also never met (do I have the wrong pointer?).

I also played with the original form of the function to determine, which function actually consumes the most time. Turns out that for a setting of 33 ms timing budget and 34 ms intermeasurement time the

VL53L1_WaitMeasurementDataReady() takes 4 ms

while the

VL53L1_GetRangingMeasurementData() function takes most of the time (~ 30 ms). This is quite confusing as I didnt see any waiting commands in the api/core files in this function or in functions used by this function.

I hope that this info can help you understand my situation.

Hi, Malik.

I think the problem in your code is related to this line:

dataready = pMeasurementDataReady;//->pready; //is measurement finished //(which parameter is correct here, i dont quite know?)

pMeasurementDataReady is a uint8_t * (pointer), but you are assigning it to dataready, which is a uint8_t, and then checking if it’s equal to 1. It would work if you dereference the pointer first, but in general, I think the function could be simplified a bit (you don’t really need the MeasurementDataReady or pMeasurementDataReady variables). Does this work?

int32_t getDistance(VL53L1_Dev_t *dev)
{
  VL53L1_Error Status = VL53L1_ERROR_NONE;
  int32_t current_distance = -1;
  uint8_t dataready = 0;
  Status = VL53L1_GetMeasurementDataReady(dev, &dataready); // VL53L1_GetMeasurementDataReady takes a pointer, so we pass the address of dataready
  if (dataready == 1)
  {
    Status = VL53L1_GetRangingMeasurementData(dev, pRangingMeasurementData);
    current_distance = pRangingMeasurementData->RangeMilliMeter;
    VL53L1_ClearInterruptAndStartMeasurement(dev);
  }
  return current_distance;
}

For reference, you can compare the non-blocking part of this Arduino sketch, which does something similar. (I should be merging that into the master branch of the repository soon.)

By the way, I edited your post to make the code a little more readable. You can do that yourself by surrounding the code with three backticks above and below, along with an optional language for syntax highlighting, like this:

```c
(code here)
```

Kevin

1 Like

Thank you very much! I will look into it and inform you about the results.

Kind regards

@kevin

Hey Kevin,

I tried it with your suggested code and got the following result using the code down below

tof.set_timing(30000, 40)
print("budget", tof.get_timing())
time.sleep(0.5)

while running:
    elapsed = 0
    current_time = time.time()
    
    time_before = time.time()
    distance_in_mm = tof.get_distance() # Grab the range in mm
    print("time spend", time.time()-time_before) # print the time spent for grabbing the range

    if distance_in_mm>0:    
        print("Distance: {}mm".format(distance_in_mm))

    while elapsed < 0.05: #wait to complete the 50 ms cycle
        elapsed = time.time()-current_time
    print("50 ms loop done"+"\n")

it seems that whenever data is ready, the program/sensor (or whatever causes the issue) takes about 30 ms to transfer it. When data is not ready, it only needs like 1 ms. I tried out different measurement times and timing budgets, but had the same result of 30 ms delay. I think there might be an issue with the API, probably the following line, as I pointed out before.

VL53L1_GetRangingMeasurementData(dev, pRangingMeasurementData);

Do you have any ideas?

Kind regards,

Malik

Hi, Malik.

I just tested this on an Arduino and found that to call both VL53L1_GetRangingMeasurementData and VL53L1_ClearInterruptAndStartMeasurement, it takes about 22 ms with a 100 kHz I2C frequency and about 8 ms with a 400 kHz I2C frequency. What frequency are you using on your Raspberry Pi? I think the default is 100 kHz, so if you haven’t changed it, that might explain why it’s taking about 30 ms to get the data.

Kevin

1 Like

Hello Kevin!

Yes you are absolutely right! The frequency was the culprit! Didn’t think it would make such a difference. For me it’s also about 7 ms now. Not as fast as I’d wish, but it’s okay.
Thank you very much!

Kind regards,

Malik