Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-blocking read, GPIO0 signalling support, alternative I2C interface #42

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,11 @@ This library is intended to provide a quicker and easier way to get started usin
* `uint8_t getAddress(void)`<br>
Returns the current I&sup2;C address.

* `bool init(bool io_2v8 = true)`<br>
Iniitializes and configures the sensor. If the optional argument `io_2v8` is true (the default if not specified), the sensor is configured for 2V8 mode (2.8 V I/O); if false, the sensor is left in 1V8 mode. The return value is a boolean indicating whether the initialization completed successfully.
* `bool init(int16_t GPIO0_pin, TwoWire &theWire, bool io_2v8)`<br>
Iniitializes and configures the sensor.
If the optional argument `GPIO0_pin` is set, the sensor will use that pin to check if the measurment is finished. This pin should be connected to the sensors GPOI0 pin. This can save a bit of time compared to reading the register. Default is -1.
The optional argument `theWire` lets you specify a diferent I2C port for communication with the sensor. Default is Wire.
If the optional argument `io_2v8` is true (the default if not specified), the sensor is configured for 2V8 mode (2.8 V I/O); if false, the sensor is left in 1V8 mode. The return value is a boolean indicating whether the initialization completed successfully.

* `void writeReg(uint8_t reg, uint8_t value)`<br>
Writes an 8-bit sensor register with the given value.
Expand Down Expand Up @@ -143,10 +146,17 @@ This library is intended to provide a quicker and easier way to get started usin
Stops continuous mode.

* `uint16_t readRangeContinuousMillimeters(void)`<br>
Returns a range reading in millimeters when continuous mode is active.
Returns a range reading in millimeters when continuous mode is active. Blocks execution until the measurment is received.

* `uint16_t readRangeSingleMillimeters(void)`<br>
Performs a single-shot ranging measurement and returns the reading in millimeters.
Performs a single-shot ranging measurement and returns the reading in millimeters. Blocks execution until the measurment is received.

* `uint16_t available(void)`<br>
Returns true if the measurment has finished and data is ready to be read. Used when reading the sensor in a non-blocking manner.

* `uint16_t readRangeMillimeters(void)`<br>
Returns a range reading in millimeters when continuous mode is active. Should be used in combination with `available(void)` to read the sensor in a non-blocking manner.


* `void setTimeout(uint16_t timeout)`<br>
Sets a timeout period in milliseconds after which read operations will abort if the sensor is not ready. A value of 0 disables the timeout.
Expand Down
129 changes: 82 additions & 47 deletions VL53L0X.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,14 @@ void VL53L0X::setAddress(uint8_t new_addr)
// enough unless a cover glass is added.
// If io_2v8 (optional) is true or not given, the sensor is configured for 2V8
// mode.
bool VL53L0X::init(bool io_2v8)
bool VL53L0X::init(int16_t GPIO0_pin, TwoWire &theWire, bool io_2v8)
{
gpio_pin=GPIO0_pin;
if(gpio_pin >- 1)
{
pinMode(gpio_pin,INPUT);
}
wire = &theWire;
// check model ID register (value specified in datasheet)
if (readReg(IDENTIFICATION_MODEL_ID) != 0xEE) { return false; }

Expand Down Expand Up @@ -236,7 +242,7 @@ bool VL53L0X::init(bool io_2v8)
// -- VL53L0X_SetGpioConfig() begin

writeReg(SYSTEM_INTERRUPT_CONFIG_GPIO, 0x04);
writeReg(GPIO_HV_MUX_ACTIVE_HIGH, readReg(GPIO_HV_MUX_ACTIVE_HIGH) & ~0x10); // active low
writeReg(GPIO_HV_MUX_ACTIVE_HIGH, 0x01); // active low
writeReg(SYSTEM_INTERRUPT_CLEAR, 0x01);

// -- VL53L0X_SetGpioConfig() end
Expand Down Expand Up @@ -284,45 +290,45 @@ bool VL53L0X::init(bool io_2v8)
// Write an 8-bit register
void VL53L0X::writeReg(uint8_t reg, uint8_t value)
{
Wire.beginTransmission(address);
Wire.write(reg);
Wire.write(value);
last_status = Wire.endTransmission();
wire->beginTransmission(address);
wire->write(reg);
wire->write(value);
last_status = wire->endTransmission();
}

// Write a 16-bit register
void VL53L0X::writeReg16Bit(uint8_t reg, uint16_t value)
{
Wire.beginTransmission(address);
Wire.write(reg);
Wire.write((value >> 8) & 0xFF); // value high byte
Wire.write( value & 0xFF); // value low byte
last_status = Wire.endTransmission();
wire->beginTransmission(address);
wire->write(reg);
wire->write((value >> 8) & 0xFF); // value high byte
wire->write( value & 0xFF); // value low byte
last_status = wire->endTransmission();
}

// Write a 32-bit register
void VL53L0X::writeReg32Bit(uint8_t reg, uint32_t value)
{
Wire.beginTransmission(address);
Wire.write(reg);
Wire.write((value >> 24) & 0xFF); // value highest byte
Wire.write((value >> 16) & 0xFF);
Wire.write((value >> 8) & 0xFF);
Wire.write( value & 0xFF); // value lowest byte
last_status = Wire.endTransmission();
wire->beginTransmission(address);
wire->write(reg);
wire->write((value >> 24) & 0xFF); // value highest byte
wire->write((value >> 16) & 0xFF);
wire->write((value >> 8) & 0xFF);
wire->write( value & 0xFF); // value lowest byte
last_status = wire->endTransmission();
}

// Read an 8-bit register
uint8_t VL53L0X::readReg(uint8_t reg)
{
uint8_t value;

Wire.beginTransmission(address);
Wire.write(reg);
last_status = Wire.endTransmission();
wire->beginTransmission(address);
wire->write(reg);
last_status = wire->endTransmission();

Wire.requestFrom(address, (uint8_t)1);
value = Wire.read();
wire->requestFrom(address, (uint8_t)1);
value = wire->read();

return value;
}
Expand All @@ -332,13 +338,13 @@ uint16_t VL53L0X::readReg16Bit(uint8_t reg)
{
uint16_t value;

Wire.beginTransmission(address);
Wire.write(reg);
last_status = Wire.endTransmission();
wire->beginTransmission(address);
wire->write(reg);
last_status = wire->endTransmission();

Wire.requestFrom(address, (uint8_t)2);
value = (uint16_t)Wire.read() << 8; // value high byte
value |= Wire.read(); // value low byte
wire->requestFrom(address, (uint8_t)2);
value = (uint16_t)wire->read() << 8; // value high byte
value |= wire->read(); // value low byte

return value;
}
Expand All @@ -348,15 +354,15 @@ uint32_t VL53L0X::readReg32Bit(uint8_t reg)
{
uint32_t value;

Wire.beginTransmission(address);
Wire.write(reg);
last_status = Wire.endTransmission();
wire->beginTransmission(address);
wire->write(reg);
last_status = wire->endTransmission();

Wire.requestFrom(address, (uint8_t)4);
value = (uint32_t)Wire.read() << 24; // value highest byte
value |= (uint32_t)Wire.read() << 16;
value |= (uint16_t)Wire.read() << 8;
value |= Wire.read(); // value lowest byte
wire->requestFrom(address, (uint8_t)4);
value = (uint32_t)wire->read() << 24; // value highest byte
value |= (uint32_t)wire->read() << 16;
value |= (uint16_t)wire->read() << 8;
value |= wire->read(); // value lowest byte

return value;
}
Expand All @@ -365,30 +371,30 @@ uint32_t VL53L0X::readReg32Bit(uint8_t reg)
// starting at the given register
void VL53L0X::writeMulti(uint8_t reg, uint8_t const * src, uint8_t count)
{
Wire.beginTransmission(address);
Wire.write(reg);
wire->beginTransmission(address);
wire->write(reg);

while (count-- > 0)
{
Wire.write(*(src++));
wire->write(*(src++));
}

last_status = Wire.endTransmission();
last_status = wire->endTransmission();
}

// Read an arbitrary number of bytes from the sensor, starting at the given
// register, into the given array
void VL53L0X::readMulti(uint8_t reg, uint8_t * dst, uint8_t count)
{
Wire.beginTransmission(address);
Wire.write(reg);
last_status = Wire.endTransmission();
wire->beginTransmission(address);
wire->write(reg);
last_status = wire->endTransmission();

Wire.requestFrom(address, count);
wire->requestFrom(address, count);

while (count-- > 0)
{
*(dst++) = Wire.read();
*(dst++) = wire->read();
}
}

Expand Down Expand Up @@ -755,6 +761,10 @@ uint8_t VL53L0X::getVcselPulsePeriod(vcselPeriodType type)
else { return 255; }
}





// Start continuous ranging measurements. If period_ms (optional) is 0 or not
// given, continuous back-to-back mode is used (the sensor takes measurements as
// often as possible); otherwise, continuous timed mode is used, with the given
Expand Down Expand Up @@ -816,7 +826,7 @@ void VL53L0X::stopContinuous(void)
uint16_t VL53L0X::readRangeContinuousMillimeters(void)
{
startTimeout();
while ((readReg(RESULT_INTERRUPT_STATUS) & 0x07) == 0)
while ((gpio_pin > -1) ? digitalRead(gpio_pin) == HIGH : (readReg(RESULT_INTERRUPT_STATUS) & 0x07) == 0)
{
if (checkTimeoutExpired())
{
Expand Down Expand Up @@ -863,6 +873,31 @@ uint16_t VL53L0X::readRangeSingleMillimeters(void)
return readRangeContinuousMillimeters();
}

//check to see if the sensor finished measuring
//used when reading the sensor continuosly in a non-blocking manner
bool VL53L0X::available(void)
{
if(gpio_pin > -1)
{
if(digitalRead(gpio_pin) == LOW)
return true;
else
return false;
}
if((readReg(RESULT_INTERRUPT_STATUS) & 0x07) == 0)
return false;
else return true;
}

//read the sensor mesurment in millimeters after checking if the measurment is finished
//used when reading the sensor continuosly in a non-blocking manner
uint16_t VL53L0X::readRangeMillimeters(void)
{
uint16_t range = readReg16Bit(RESULT_RANGE_STATUS + 10);
writeReg(SYSTEM_INTERRUPT_CLEAR, 0x01);
return range;
}

// Did a timeout occur in one of the read functions since the last call to
// timeoutOccurred()?
bool VL53L0X::timeoutOccurred()
Expand Down
7 changes: 6 additions & 1 deletion VL53L0X.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define VL53L0X_h

#include <Arduino.h>
#include <Wire.h>

class VL53L0X
{
Expand Down Expand Up @@ -101,7 +102,7 @@ class VL53L0X
void setAddress(uint8_t new_addr);
inline uint8_t getAddress(void) { return address; }

bool init(bool io_2v8 = true);
bool init(int16_t GPIO0_pin = -1, TwoWire &theWire = Wire, bool io_2v8 = true);

void writeReg(uint8_t reg, uint8_t value);
void writeReg16Bit(uint8_t reg, uint16_t value);
Expand All @@ -126,6 +127,8 @@ class VL53L0X
void stopContinuous(void);
uint16_t readRangeContinuousMillimeters(void);
uint16_t readRangeSingleMillimeters(void);
bool available(void);
uint16_t readRangeMillimeters(void);

inline void setTimeout(uint16_t timeout) { io_timeout = timeout; }
inline uint16_t getTimeout(void) { return io_timeout; }
Expand Down Expand Up @@ -153,6 +156,8 @@ class VL53L0X
uint16_t io_timeout;
bool did_timeout;
uint16_t timeout_start_ms;
uint16_t gpio_pin;
TwoWire *wire;

uint8_t stop_variable; // read by init and used when starting measurement; is StopVariable field of VL53L0X_DevData_t structure in API
uint32_t measurement_timing_budget_us;
Expand Down
Binary file added examples/.DS_Store
Binary file not shown.
44 changes: 44 additions & 0 deletions examples/Continuous_Non_Blocking/Continuous_Non_Blocking.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* This example shows how to use continuous mode to take
range measurements with the VL53L0X. It is based on
vl53l0x_ContinuousRanging_Example.c from the VL53L0X API.

The range readings are in units of mm. */

#include <Wire.h>
#include <VL53L0X.h>

VL53L0X sensor;

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

sensor.setTimeout(500);

//to check for measurments in a more efficient manner you can
//connect the sensors GPIO0 pin to Arduino, and initialise
//it with "sensor.init(myPinNumber)"
if (!sensor.init())
{
Serial.println("Failed to detect and initialize sensor!");
while (1) {}
}

// Start continuous back-to-back mode (take readings as
// fast as possible). To use continuous timed mode
// instead, provide a desired inter-measurement period in
// ms (e.g. sensor.startContinuous(100)).
sensor.startContinuous();
}

void loop()
{
if(sensor.available())
{
Serial.print(sensor.readRangeMillimeters());
if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }
}

Serial.println();
}
2 changes: 2 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ startContinuous KEYWORD2
stopContinuous KEYWORD2
readRangeContinuousMillimeters KEYWORD2
readRangeSingleMillimeters KEYWORD2
available KEYWORD2
readRangeMillimeters KEYWORD2
setTimeout KEYWORD2
getTimeout KEYWORD2
timeoutOccurred KEYWORD2
Expand Down