cancel
Showing results for 
Search instead for 
Did you mean: 

How to get the VL53L4CD to interrupt when nothing is detected

Jason Mount
Associate III

I am trying to use the VL53L4CD as a low power tamper sensor so that it interrupts when someone removes a lid.  I am using the ULP driver and I pulled in SetDetectionThresholds from the other driver.  I have been able to configure it to interrupt whenever the lid is outside of a threshold range (in case the lid is smashed in or removed), which seems to do exactly what I want.  However, if I quickly remove the lid completely so that the sensor detects nothing, it does not generate interrupts. 

Is there a configuration that tells it to interrupt when it sees nothing?

1 ACCEPTED SOLUTION

Accepted Solutions
John E KVAM
ST Employee

I think you've named it. The 'nothing' case. And it's a tricky one. 

It's actually in the VL53L4CD ULD threshold, but unfortunately it was left out of the UltraLowPower (ULP) driver. 

But anything used in the ULD can be used in the ULP. They are, after all, the same part. 

In the ULP is the comment:

0x20, /* 0x46 : interrupt configuration 
  0->level low detection, 
  1-> level high, 
  2-> Out of window, 
  3->In window, 0x20-> New sample ready , TBC */
In the ULP we only give you a choice between 0 (below a threshold) and 20 - (new sample ready).
I think you want Out of Window. 
Set a high, set a low and select Interrupt 2.  
The code from the ULD driver is below. You could actually stick that code in your ULP driver. 
VL53L1X_ERROR VL53L1X_SetDistanceThreshold(VL53L1_Dev_t dev, uint16_t ThreshLow,
			      uint16_t ThreshHigh, uint8_t Window,
			      uint8_t IntOnNoTarget)
{
	VL53L1X_ERROR status = 0;
	uint8_t Temp = 0;

	status = VL53L1_RdByte(&dev, SYSTEM__INTERRUPT_CONFIG_GPIO, &Temp);
	Temp = Temp & 0x47;
	if (IntOnNoTarget == 0) {
		status = VL53L1_WrByte(&dev, SYSTEM__INTERRUPT_CONFIG_GPIO,
			       (Temp | (Window & 0x07)));
	} else {
		status = VL53L1_WrByte(&dev, SYSTEM__INTERRUPT_CONFIG_GPIO,
			       ((Temp | (Window & 0x07)) | 0x40));
	}
	status = VL53L1_WrWord(&dev, SYSTEM__THRESH_HIGH, ThreshHigh);
	status = VL53L1_WrWord(&dev, SYSTEM__THRESH_LOW, ThreshLow);
	return status;
}

If this or any post solves your issue, please mark them as 'Accept as Solution' It really helps. And if you notice anything wrong do not hesitate to 'Report Inappropriate Content'. Someone will review it.

View solution in original post

3 REPLIES 3
John E KVAM
ST Employee

I think you've named it. The 'nothing' case. And it's a tricky one. 

It's actually in the VL53L4CD ULD threshold, but unfortunately it was left out of the UltraLowPower (ULP) driver. 

But anything used in the ULD can be used in the ULP. They are, after all, the same part. 

In the ULP is the comment:

0x20, /* 0x46 : interrupt configuration 
  0->level low detection, 
  1-> level high, 
  2-> Out of window, 
  3->In window, 0x20-> New sample ready , TBC */
In the ULP we only give you a choice between 0 (below a threshold) and 20 - (new sample ready).
I think you want Out of Window. 
Set a high, set a low and select Interrupt 2.  
The code from the ULD driver is below. You could actually stick that code in your ULP driver. 
VL53L1X_ERROR VL53L1X_SetDistanceThreshold(VL53L1_Dev_t dev, uint16_t ThreshLow,
			      uint16_t ThreshHigh, uint8_t Window,
			      uint8_t IntOnNoTarget)
{
	VL53L1X_ERROR status = 0;
	uint8_t Temp = 0;

	status = VL53L1_RdByte(&dev, SYSTEM__INTERRUPT_CONFIG_GPIO, &Temp);
	Temp = Temp & 0x47;
	if (IntOnNoTarget == 0) {
		status = VL53L1_WrByte(&dev, SYSTEM__INTERRUPT_CONFIG_GPIO,
			       (Temp | (Window & 0x07)));
	} else {
		status = VL53L1_WrByte(&dev, SYSTEM__INTERRUPT_CONFIG_GPIO,
			       ((Temp | (Window & 0x07)) | 0x40));
	}
	status = VL53L1_WrWord(&dev, SYSTEM__THRESH_HIGH, ThreshHigh);
	status = VL53L1_WrWord(&dev, SYSTEM__THRESH_LOW, ThreshLow);
	return status;
}

If this or any post solves your issue, please mark them as 'Accept as Solution' It really helps. And if you notice anything wrong do not hesitate to 'Report Inappropriate Content'. Someone will review it.
Jason Mount
Associate III

I am currently using VL53L4CD_SetDetectionThresholds() that I copied from the ULD driver in STSW-IMG026 and I'm using 0x02 for the window value.  I have the test thresholds set at 50mm and 150mm with a 100mm tall grey test surface 85mm x 85mm.

It interrupts as expected if I move the test surface below 50mm or above 150mm but if I move the test surface beyond about a meter above the sensor, it stops interrupting (to measure the full distance, I held an 8.5x11 sheet of white paper to make sure there was a nice big target because manual alignment becomes difficult above 600mm).  For reference, as I raise the target, the values just before it stops interrupting are similar to this: 

Dist = 1004, Signal - 1200, Sigma = 12, Ambient = 128

Is that VL53LX1 code compatible with the VL53L4CD? I didn't see anything matching in the ULD code.  I modified it to match the ULP API so I could call the same way it and it didn't seem to behave any differently:

uint8_t VL53L1X_SetDistanceThreshold(
                uint16_t dev,
                uint16_t ThreshLow,
                uint16_t ThreshHigh,
                uint8_t Window,
                uint8_t IntOnNoTarget)
{
	uint8_t status = 0;
	uint8_t Temp = 0;

	status = VL53L4CD_ULP_RdByte(dev, VL53L4CD_ULP_SYSTEM__INTERRUPT, &Temp);
	Temp = Temp & 0x47;
	if (IntOnNoTarget == 0) {
		status = VL53L4CD_ULP_WrByte(dev, VL53L4CD_ULP_SYSTEM__INTERRUPT,
			       (Temp | (Window & 0x07)));
	} else {
		status = VL53L4CD_ULP_WrByte(dev, VL53L4CD_ULP_SYSTEM__INTERRUPT,
			       ((Temp | (Window & 0x07)) | 0x40));
	}
	status = VL53L4CD_ULP_WrWord(dev, VL53L4CD_ULP_THRESH_HIGH, ThreshHigh);
	status = VL53L4CD_ULP_WrWord(dev, VL53L4CD_ULP_THRESH_LOW, ThreshLow);
	return status;
}

Also, upon further examination, I probably don't need the lower threshold, just an upper will do fine as long as it interrupts when there is no target.

Am I missing or misunderstanding something? 

Jason Mount
Associate III

Thanks @John E KVAM, I was initially thrown off by the VL53LX1, but this worked.

The example I was using had multiple calls to re-configure the interrupt register I hadn't noticed; once the other calls were fixed it started generating interrupts even when nothing was detected.

For anyone else who might have this issue, the key was setting bit 0x40 in the VL53L4CD_ULP_SYSTEM__INTERRUPT register along with the desired window value.