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

Pololu Forum

Vl6180x gpio1 interrupt / asynchronous use

#1

Hello. I am using the Pololu vl6180x TOF sensor and the associated Arduino library. I am looking for a way to use these sensors asynchronously (so my code can do other stuff while the sensor is reading) in continuous/interleaving mode. I read in the datasheet that GPIO1 can be used as an interrupt when a sensor has completed a reading but I hooked that pin up to a scope and it always seems to be high. So I’m asumming I need to do some writing to the register to utilize this function? Is there any easy way to do this through the Pololu library?

Thank you.

#2

Hello.

By default, our Arduino library for the VL6180X does not configure GPIO1 as an interrupt output. You can do so by calling:

writeReg(VL6180X::SYSTEM__MODE_GPIO1, 0x10);

-Jon

#3

Thanks for the reply. I tried using this command but the interrupt pin is now just constantly low so I’m assuming it is not indicating when a measurement is ready? Or do I need to modify other parts of the interleaving continuous example to see this pin changing on the scope?

I read that there is a specific mode for asynchronous use of the Vl6180x so does this mean that I cannot take advantage of this feature in continuous mode?

#4

Note that the interrupt output is active low when configured this way, so if you are not reading the sensor very quickly, it might be low to indicate that data is ready most of the time. Can you confirm that you are using scope to detect the output at GPIO1?

-Jon

#5

Hello,

Yes I am using a scope. It is constantly low in interleaving continuous mode. If I use the single shot example, it works as expected: about 37 times a second the interrupt pin dips from high to low. Even with that, though, it’s unclear how I could use the sensor asynchronously as the “sensor.readRangeSingleMillimeters()” command seems to stop and wait until it receives a reply. Also, I’m hoping to be able to use the interleaving continuous mode asynchronously so I can get a higher update rate.

#6

Hi, mureytasroc.

It looks like the way our library sets up the data ready signal, the GPIO1 interrupt output works if you are using interleaved mode (startContinuousInterleaved()) and retrieving both ambient and range results (readAmbientContinuous() and readRangeContinuous()), but it doesn’t work well if you are only retrieving one type of result. Which are you trying to read: ambient, range, or both?

The library in its current state also doesn’t provide functions for asynchronous reading, but it’s pretty straightforward to check the RESULT__INTERRUPT_STATUS_GPIO to see whether the results are ready.

I can give you some more specific code examples for both setting up the GPIO1 interrupt and doing asynchronous readings once I know what type(s) of measurements you are trying to get.

Kevin

#7

Hello,

Thanks for the reply. I only need range data.

#8

This sketch should set up the interrupt correctly (it seems like the best solution is to just clear any existing interrupts just before starting continuous mode) and has a few functions that let you read the sensor asynchronously:

#include <Wire.h>
#include <VL6180X.h>

VL6180X sensor;

bool rangeDataReady()
{
  return ((sensor.readReg(VL6180X::RESULT__INTERRUPT_STATUS_GPIO) & 0x04) != 0);
}

uint8_t readRangeNonBlocking()
{
  uint8_t range = sensor.readReg(VL6180X::RESULT__RANGE_VAL);
  sensor.writeReg(VL6180X::SYSTEM__INTERRUPT_CLEAR, 0x01);

  return range;
}

uint8_t readRangeNonBlockingMillimeters()
{
  return readRangeNonBlocking() * sensor.getScaling();
}

void setup()
{
  Serial.begin(9600);
  Wire.begin();

  sensor.init();
  sensor.configureDefault();

  // Reduce range max convergence time and ALS integration
  // time to 30 ms and 50 ms, respectively, to allow 10 Hz
  // operation (as suggested by Table 6 ("Interleaved mode
  // limits (10 Hz operation)") in the datasheet).
  sensor.writeReg(VL6180X::SYSRANGE__MAX_CONVERGENCE_TIME, 30);
  sensor.writeReg16Bit(VL6180X::SYSALS__INTEGRATION_PERIOD, 50);

  sensor.setTimeout(500);

   // stop continuous mode if already active
  sensor.stopContinuous();
  // in case stopContinuous() triggered a single-shot
  // measurement, wait for it to complete
  delay(300);

  // enable interrupt output on GPIO1
  sensor.writeReg(VL6180X::SYSTEM__MODE_GPIO1, 0x10);
  // clear any existing interrupts
  sensor.writeReg(VL6180X::SYSTEM__INTERRUPT_CLEAR, 0x03);
  
  // start interleaved continuous mode with period of 100 ms
  sensor.startRangeContinuous(100);
}

void loop()
{
  // only get a range reading if it is ready
  if (rangeDataReady())
  {
    Serial.print("Range: ");
    Serial.println(readRangeNonBlockingMillimeters());
  }
}

I would like to eventually get this into the library (our similar VL53L1X library already has support for asynchronous reading).

Kevin

#9

Thanks, this totally works. Interestingly enough, the output of gpio1 on the scope still seems to be constantly low (or about +200mV) but the code works asynchronously so I’m not complaining. Does this mean I don’t actually have to hook up another Arduino pin to the sensor’s gpio1 output?

#10

That’s strange; with the exact sketch I posted above, I see GPIO1 high (2.8 V) most of the time and going low briefly every 100 ms. If you still want to get the interrupt signal working, I can try to help you troubleshoot more. However, if you are fine with using the rangeDataReady() function to check when a reading is available, then you shouldn’t need the interrupt output.

Kevin

#11

Actually, I checked again and that is the behavior I am getting as well. I must have made a mistake when I was probing it the last time. So I guess I can use either that pin or the
rangeDataReady() function. Thanks for all your help.