2025-02-10 5:34 AM
Hi
I am using VL53L4CD for detecting presence of an object at a distance below 300mm. I have considered Examnple4 Ultra Low Power as the base. I am able to get the interrupts when an object comes below 300mm distance as expected.
But in this scenario if the object stays at a distance below 300mm I keep on getting the interrupts after a regular interval.
What I want to implement is that I should get interrupt once an object comes below 300mm and once when it goes away.
Is it possible to get this functionality?
Solved! Go to Solution.
2025-03-10 9:04 AM
In our API, is the function.
VL53L4CD_Error VL53L4CD_SetDetectionThresholds(
Dev_t dev,
uint16_t distance_low_mm,
uint16_t distance_high_mm,
uint8_t window)
{
VL53L4CD_Error status = VL53L4CD_ERROR_NONE;
status |= VL53L4CD_WrByte(dev, VL53L4CD_SYSTEM__INTERRUPT, window);
status |= VL53L4CD_WrWord(dev, VL53L4CD_THRESH_HIGH, distance_high_mm);
status |= VL53L4CD_WrWord(dev, VL53L4CD_THRESH_LOW, distance_low_mm);
return status;
}
Just call that.
Trouble is that window is not very well defined. What you want is an interrupt when something goes away.
So set your thresholds to some value a good distance above and below where you expect your target to be. Then set the window to 2. Out of window. When your target goes away, you should get the interrupt.
In my experiments it works.
However, note that you will get one interrupt at start.
(it appears i got the register definition in my first reply from the wrong sensor. I'll remove that.)
- john
- john
2025-02-10 6:55 AM - edited 2025-03-10 9:07 AM
With the VL53L sensors each range is independent of any other range. So, indeed, you will get an interrupt every time you range if you have your thresholds set, and you have an object lower than your threshold.
If you want to trigger exactly once when the object comes near and get another interrupt when the object goes away, you should get the interrupt, reconfigure your interrupts for above your threshold. Once the object has gone away, you can go back to your 'below' threshold configuration.
In order to make this work right you might have to do a bit of experimenting with the function below :
VL53L4CD_Error VL53L4CD_SetDetectionThresholds(
Dev_t dev,
uint16_t distance_low_mm,
uint16_t distance_high_mm,
uint8_t window)
We simplified that code a bit as 99% of our customers don't need this functionality:
Try playing with 'out of Window'. Make sure you get an interrupt when you object leaves the area.
(Threshold =2 appears to be 'out of window'. That's what you want.
But I honestly think you are going to do better, by detecting the interrupt, and assuming your object went away when you stop getting them.
Good luck.
john
2025-02-10 11:03 PM
Hi John
Actually in my application, the object will stay below the threshold for more than 12 hours in a day... So getting interrupts for such long duration is not desirable as it will be a battery operated device...
I tried looking for the register definitions in the data sheet but I could not find any descritions there.. Can you point me to the document where I can get these definitions...
I am not sure where in the code I need to make the changes suggested by you..
Regards
Parag
2025-03-07 12:05 AM
Hi John
Just to be clear the register you meant is
2025-03-10 9:04 AM
In our API, is the function.
VL53L4CD_Error VL53L4CD_SetDetectionThresholds(
Dev_t dev,
uint16_t distance_low_mm,
uint16_t distance_high_mm,
uint8_t window)
{
VL53L4CD_Error status = VL53L4CD_ERROR_NONE;
status |= VL53L4CD_WrByte(dev, VL53L4CD_SYSTEM__INTERRUPT, window);
status |= VL53L4CD_WrWord(dev, VL53L4CD_THRESH_HIGH, distance_high_mm);
status |= VL53L4CD_WrWord(dev, VL53L4CD_THRESH_LOW, distance_low_mm);
return status;
}
Just call that.
Trouble is that window is not very well defined. What you want is an interrupt when something goes away.
So set your thresholds to some value a good distance above and below where you expect your target to be. Then set the window to 2. Out of window. When your target goes away, you should get the interrupt.
In my experiments it works.
However, note that you will get one interrupt at start.
(it appears i got the register definition in my first reply from the wrong sensor. I'll remove that.)
- john
- john
2025-03-11 5:54 AM
Hi
I am using the below code:
int8_t init_TOF_sensor(const struct i2c_dt_spec *dev_i2c1)
{
int8_t status = 0;
uint8_t tmp = 0;
uint16_t sensor_id;
int rc = 0;
char report[64];
VL53L4CD_Result_t results;
rc = gpio_pin_configure_dt(&irq_acc_pin, GPIO_INPUT);
if (rc < 0) {
return -1;
}
rc = gpio_pin_interrupt_configure_dt(&irq_acc_pin, GPIO_INT_EDGE_FALLING);
gpio_init_callback(&irq_acc_pin_cb_data, IRQ_ACC_handler, BIT(irq_acc_pin.pin));
gpio_add_callback(irq_acc_pin.port, &irq_acc_pin_cb_data);
status = VL53L4CD_ULP_GetSensorId(dev_i2c1, &sensor_id);
if(status || (sensor_id != 0xEBAA))
{
printk("VL53L4CD not detected at requested address\n");
return status;
}
status = VL53L4CD_ULP_SensorInit(dev_i2c1);
if(status)
{
printk("VL53L4CD ultra low power Loading failed\n");
return status;
}
printk("VL53L4CD ultra low power ready !\n");
status = VL53L4CD_SetDetectionThresholds(dev_i2c1,5,500,2);
if(status)
{
printk("VL53L4CD_ULP_SetInterruptConfiguration failed with status %u\n", status);
return status;
}
// Ranging loop
status = VL53L4CD_ULP_StartRanging(dev_i2c1);
if(status)
{
printk("VL53L4CD_ULP_StartRanging failed with status %u\n", status);
return status;
}
VL53L4CD_ULP_ClearInterrupt(dev_i2c1);
VL53L4CD_GetResult(dev_i2c1, &results);
snprintf(report, sizeof(report), "Status = %3u, Distance = %5u mm, \r\n",
results.range_status,
results.distance_mm);
printk(report);
status = VL53L4CD_ULP_SetInterMeasurementInMs(dev_i2c1, 1000);
if(status)
{
printk("VL53L4CD_ULP_SetInterMeasurementInMs failed with status %u\n", status);
return status;
}
// Reduce the macro timing to minimum. This is equivalent as reducing the integration time
status = VL53L4CD_ULP_SetMacroTiming(dev_i2c1, 1);
if(status)
{
printk("VL53L4CD_ULP_SetMacroTiming failed with status %u\n", status);
return status;
}
// Reduce at maximum the SPADS
status = VL53L4CD_ULP_SetROI(dev_i2c1, 4);
if(status)
{
printk("VL53L4CD_ULP_SetROI failed with status %u\n", status);
return status;
}
return status;
}
In this I have configured the sensoto interrupt when the object is below 5mm and above 500mm. I am able to get the interrupt when an object is below 5mm but no interrupt is generated if the object is beyond 500mm. I have placed the object at aroung 580mm.
Regards
2025-03-11 9:08 AM
First, let us do a test. change the upper to something like 300 and use your hand to insure you are getting the interrupt. it could be your target is too small to be detected. if that works then the issue is not the interrupt but the ability to see the target.
And if you set 'out of window' you will only get one.
We did this so we could solve the problem of someone leaving a urinal. He leaves, we flush, then go back to looking for the next guy to approach.
But i see you are using the ULP driver. And that might be the issue.
ToF sensors get their distance and accuracy by doing statistics on lots of photon arrival times. But as you cut down the integration time, it might be that you cannot 'see' to 500mm. increase the integration time using:
uint8_t VL53L4CD_ULP_SetMacroTiming(
uint16_t dev,
uint16_t macro_timing);
Increase that timing to something that works for you. Uses more power though, so don't go any higher than you have to.