Hi,
On uint8_t Adafruit_VL6180X::readRange(void) there are two while statments. How can I change this for something that is non blocking the loop?
This is a bit advanced for me.
Hi,
On uint8_t Adafruit_VL6180X::readRange(void) there are two while statments. How can I change this for something that is non blocking the loop?
This is a bit advanced for me.
You're asking us to hack an Adafruit library for you?
You need to learn how to untangle blocking code using state machines.
Here in this case the code is pretty self explanatory :
there is an initial active wait for the device to be ready
// wait for device to be ready for range measurement
while (! (read8(VL6180X_REG_RESULT_RANGE_STATUS) & 0x01));
so a new function would need to test that flag and return false or something until this is ready
Once ready the code initiates a range measurement
// Start a range measurement
write8(VL6180X_REG_SYSRANGE_START, 0x01);
this can be kept as is.
But then the code waits for the measure to be ready
// Poll until bit 2 is set
while (! (read8(VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO) & 0x04));
so that would need again to return instantly until the data is ready.
When the data is ready, then it's a simple read and clean up, you can acquire the value
// read range in mm
uint8_t range = read8(VL6180X_REG_RESULT_RANGE_VAL);
// clear interrupt
write8(VL6180X_REG_SYSTEM_INTERRUPT_CLEAR, 0x07);
So the idea is to build a small state machine, embedded into a non blocking function, that would return false until the data is available and true where the data has been read.
I would do something like this (to add inside the library code and declared in the public methods)
boolean Adafruit_VL6180X::readRangeNoWait(uint8_t &range)
{
static uint8_t _range_state = 0; // 0 = Idle. 1 = read requested, waiting for device to be ready. 2 = trigger read. 3 = waiting for range to be avail. 4=data is there
static boolean dataReady;
switch (_range_state) {
case 0: // initiate a read
dataReady = false;
_range_state = 1;
break;
case 1: // wait for device to be ready for range measurement
if ((read8(VL6180X_REG_RESULT_RANGE_STATUS) & 0x01)) _range_state = 2;
break;
case 2:// Start a range measurement
write8(VL6180X_REG_SYSRANGE_START, 0x01);
_range_state = 3;
break;
case 3:// wait for data to be available, Poll until bit 2 is set
if ((read8(VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO) & 0x04)) _range_state = 4;
break;
case 4:// read & cleanup, flag data is there
range = read8(VL6180X_REG_RESULT_RANGE_VAL); // read range in mm
write8(VL6180X_REG_SYSTEM_INTERRUPT_CLEAR, 0x07); // clear interrupt
_range_state = 0; // go back to Idle state
dataReady = true;
break;
default: // should not happen!
break;
}
return dataReady;
}
and you would use it like this in your loop()
uint8_t aRange;
...
// somewhere in the loop()
if (VL6180X.readRangeNoWait(aRange)) {
// data ready, aRange is set with the right value
} else {
// go do something else as the data was not ready
}
Typed here - totally untested! let us know if that works... really curious
To J-M-L
Thanks, works like a charm