cancel
Showing results for 
Search instead for 
Did you mean: 

Vl53l1X GPIO1 Interrupt

JPere.3
Associate II

Hi there,

My application is battery operated, so I’m trying to wake up atmega328p from deep sleep from an interrupt though the GPIO pin from the sensor.

I'm using Thresholds, "inside window". If any object ditected inside the range, to fire a trigger to wake up the host.

Is such thing possible?

If yes, could you give me some pointers or code samples please?

My host platform is Arduino Pro Mini @ 8Mhz 3.3v.

Thanks!

1 ACCEPTED SOLUTION

Accepted Solutions
John E KVAM
ST Employee

The camera test shows that the sensor is working. If it's flashing, it's ranging.

The interrupt is active low, so going low indicates it's got a range that meets your ranging conditions.

You are using the Pololu code which I'm not really good at, but I can guess.

Place the .startRangeing() call OUTSIDE your loop.

And don't stop it until you want to shut the system off. So take the stopRanging() out of your loop.

Once the sensor is running, it will stay running until you stop it.

Continually starting the senor will goof everything up.

It may well be that you get one interrupt that is outside your window.

So for every interrupt read the range to double check, then just go back to sleep.


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

7 REPLIES 7
John E KVAM
ST Employee

Thresholds and interrupts are available to do exactly what you want.

With the VL53L1X you have two choices.

The full driver which exposes all the functionality of the sensor, or the UltraLite Driver, which is limited but is very small.

STSW-IMG007 is the full driver, STSW-IMG009 is the UltraLite Driver.

Both can be found on the by searching the web site for VL53L1X.

Using the ULD,

VL53LX_SetDistanceThreshold (). The available detection condition usecases

include:

• Object under a certain distance

• Objet beyond a certain distance

• Object within a window limited by a near and far threshold

• Object out of a window limited by a near and far threshold

Using the Full driver, the ability is the same, but the call is different.

  • john


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.
JPere.3
Associate II

Thanks John,

Question;

Looking at the "Ranging flow" diagram (in UM2510),

if I'm using "VL53LX_SetDistanceThreshold" with detection condition to be "Object within a window",

Do the interrupt triggers when an object comes within the window?

Or does the interrupt triggers Autonomously ?

0693W000000WbN6QAK.png

John E KVAM
ST Employee

I'd do it this way.

Write your code without the thresholds.

Prove it ranges and you can get the data.

if you have a non-iPhone or can use your laptop camera, you can see the flash of light. (Iphones have really good IR filters, so they will not see the light).

The sensor will continue to range even if you don't read the answer.

Then re-write your code and insert the set_thresholds, and your window.

You will see that you only get an interrupt when an object comes within your window.

So to answer your questions:

Do the interrupt triggers when an object comes within the window?

You will get the interrupt after the range occurs with an object within the threshold window

Or does the interrupt triggers Autonomously?

The sensor will run completely autonomously giving an interrupt only when your thresholds are met.


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.

:backhand_index_pointing_right: Please I'm a novice and kindly excuse my coding and questions if they seems as lame.:backhand_index_pointing_left:

I'm not sure why you asked me to do try this.

I did the camera test with my laptop camera and I see the light emitting from the sensor on both set of code.

light was always visible.

with regards to the interrupt;

Below is the pseudocode of my program.

It print the GPIO pin state so that I can see if an interrupt had occurred.

But all I see only 0 (digital low) being printed.

I checked and I realized the Sensor pulls the GPIO to low.

But what puzzles me is that it is always pulled to low within or outside the range.

And I'm clueless how i could implement a wake-up on interrupt for my project.

Btw: My test module is from Pololu https://www.pololu.com/product/3415/specs

setup() 
{
  Sensor.init()
  Sensor.setDistanceModeLong();
  Sensor.setDistanceThreshold(50, 100, 3);  //Min:50mm, Max:100mm, Window: Within a distance range (min/max), "inside window"
}
 
loop()
{
  Sensor.startRanging();
 
  while (!Sensor.checkForDataReady()){
    println(digitalRead(2));  //Read the GPIO pin
  }
 
  int x = Sensor.getDistance(); 
  Sensor.clearInterrupt();
  Sensor.stopRanging();
}

John E KVAM
ST Employee

The camera test shows that the sensor is working. If it's flashing, it's ranging.

The interrupt is active low, so going low indicates it's got a range that meets your ranging conditions.

You are using the Pololu code which I'm not really good at, but I can guess.

Place the .startRangeing() call OUTSIDE your loop.

And don't stop it until you want to shut the system off. So take the stopRanging() out of your loop.

Once the sensor is running, it will stay running until you stop it.

Continually starting the senor will goof everything up.

It may well be that you get one interrupt that is outside your window.

So for every interrupt read the range to double check, then just go back to sleep.


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.

I'm using the Sparkfun library since Pololu library does not have setDistanceThreshold implemented.

Let me try the changes you've mentioned.

Thanks!

JPere.3
Associate II

Okay I managed to get this to work with Sparkfun library for Arduino.

Only thing I should point here is that if anyone using the Sparkfun library for Arduino, make sure to set

setInterruptPolarityLow();

if your interrupt is on a LOW signal as below line of coding,

attachInterrupt(0, wakeUp, LOW);

My test example code here if anyone is interested;

#include <avr/sleep.h>
#include <Wire.h>
#include "SparkFun_VL53L1X.h"
 
#define SHUTDOWN_PIN 10
#define INTERRUPT_PIN 2
 
long heartBeatTime = 0, count = 0, pollingInterval = 0;;
int heartBeatLedState = LOW; 
int status;
 
SFEVL53L1X distanceSensor(Wire, SHUTDOWN_PIN, INTERRUPT_PIN);
 
void setup() 
{
  pinMode(INTERRUPT_PIN, INPUT_PULLUP);
  pinMode(SHUTDOWN_PIN, OUTPUT);
  digitalWrite(SHUTDOWN_PIN, HIGH);
 
  ADCSRA &= ~(1 << 7);
 
  Wire.begin();
 
  Serial.begin(9600);
  Serial.println(F("VL53L1X Qwiic Test"));
 
  if (distanceSensor.begin() == 0) //Begin returns 0 on a good init
  {
    Serial.println(F("Sensor online!"));
  }
 
  distanceSensor.setInterruptPolarityLow();
  distanceSensor.setDistanceModeLong();
  distanceSensor.setDistanceThreshold(50, 1000, 3);
  distanceSensor.startRanging(); 
}
 
void loop(void)
{
  if ((millis() - heartBeatTime) >= 1000) 
  {
    heartBeatTime = millis();
 
    if (heartBeatLedState == LOW) {
      heartBeatLedState = HIGH;
    } else {
      heartBeatLedState = LOW;
    }
  
    digitalWrite(LED_BUILTIN, heartBeatLedState);
  }
 
  if ((millis() - pollingInterval) >= 10) 
  {
    pollingInterval = millis();
    
    static uint16_t startMs = millis();
  
    // non-blocking check for data ready
    status = distanceSensor.checkForDataReady();
    if(status)
    {
      int distance = distanceSensor.getDistance();
 
      Serial.print(F("count: "));
      Serial.print(count);
      Serial.print(F(" distance: "));
      Serial.println(distance);
 
      distanceSensor.clearInterrupt();
      startMs = millis();
    }
    else if((uint16_t)(millis() - startMs) > 10000) //Goes to sleep if no object in range for 10 seconds
    {
      Serial.println(F("Entering CPU low power sleep."));
 
      distanceSensor.clearInterrupt();
      startMs = millis();
 
      Going_To_Sleep();
 
      Serial.println(count);
    }
  }
}
 
void Going_To_Sleep(){
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  MCUCR = bit (BODS) | bit (BODSE);
  MCUCR = bit (BODS);
  noInterrupts();
  attachInterrupt(0, wakeUp, LOW);
  digitalWrite(LED_BUILTIN, LOW);
  Serial.println(F("I'm going to bed!"));
  Serial.flush();
  interrupts();
  sleep_cpu();
 
  Serial.println(F("I just now woke up!"));
  digitalWrite(LED_BUILTIN, HIGH);
}
 
void wakeUp(){
  count++;
 
  sleep_disable();
  detachInterrupt(0);
}