Skip to content

Commit

Permalink
optimized some larger data transfers to use I2C block reads/writes
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin-pololu committed Aug 21, 2024
1 parent 8a2371d commit bc86590
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 11 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Most of the functionality of this library is based on the [VL53L4CD Ultra Lite D
Range reading from the last measurement, in millimeters. (This reading can also be obtained as the return value of `read()`.)
* `uint8_t range_status`<br>
Status of the last measurement; see the API user manual UM2931 for descriptions of the possible statuses. A status of 0 means there were no problems with the measurement.
* `uint16_t number_of_spad`<br>
* `uint8_t number_of_spad`<br>
The number of SPADs (single photon avalanche diodes) enabled for the last measurement. More SPADs will be activated for sensing distant and less reflective targets.
* `uint16_t signal_rate_kcps`<br>
Quantity of photons measured during the last measurement, in units of kilo counts per second.
Expand All @@ -81,6 +81,8 @@ Most of the functionality of this library is based on the [VL53L4CD Ultra Lite D
Signal rate divided by number of SPADs.
* `uint16_t ambient_per_spad_kcps`<br>
Ambient rate divided by number of SPADs.
* `uint16_t sigma_mm`<br>
An estimate of the noise (standard deviation) in the last range measurement.

* `uint8_t last_status`<br>
The status of the last I&sup2;C write transmission. See the [`Wire.endTransmission()` documentation](http://arduino.cc/en/Reference/WireEndTransmission) for return values.
Expand All @@ -95,7 +97,7 @@ Most of the functionality of this library is based on the [VL53L4CD Ultra Lite D
Returns a pointer to the I&sup2;C bus this object is using.

* `void setAddress(uint8_t new_addr)`<br>
Changes the I&sup2;C slave device address of the VL53L4CD to the given value (7-bit).
Changes the I&sup2;C target device address of the VL53L4CD to the given value (7-bit).

* `uint8_t getAddress()`<br>
Returns the current I&sup2;C address.
Expand Down Expand Up @@ -168,4 +170,4 @@ Most of the functionality of this library is based on the [VL53L4CD Ultra Lite D

## Version history

* 1.0.0 (2024-08-19): Original release.
* 1.0.0 (2024-08-20): Original release.
46 changes: 39 additions & 7 deletions src/VL53L4CD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,22 @@ bool VL53L4CD::init(bool io_2v8, bool fast_mode_plus)
put 0x40 in location 0x87 */
};

for (uint8_t reg = 0x30; reg <= 0x87; reg++)
// Load the rest of the default config (0x30-0x87) with a few block writes.
// The Wire library for AVR uses a 32-byte tx buffer, and 2 bytes are needed
// for the starting register address of each write, so we can write 30
// registers at a time.
const uint8_t block_size = 30;
for (uint8_t start_reg = 0x30; start_reg <= 0x87; start_reg += block_size)
{
writeReg(reg, pgm_read_byte(VL53L4CD_DEFAULT_CONFIGURATION + reg - 0x30));
bus->beginTransmission(address);
bus->write(0); // reg high byte
bus->write(start_reg); // reg low byte
for (uint8_t reg = start_reg; (reg < start_reg + block_size) && (reg <= 0x87); reg++)
{
bus->write(pgm_read_byte(VL53L4CD_DEFAULT_CONFIGURATION + reg - 0x30));
}
last_status = bus->endTransmission();
if (last_status) { return false; }
}

// "Start VHV"
Expand Down Expand Up @@ -472,14 +485,33 @@ void VL53L4CD::readResults()
0, 255, 255, 9, 13, 255, 255, 255, 255, 10, 6,
255, 255, 11, 12 };

uint8_t status = readReg(RESULT__RANGE_STATUS) & 0x1F;
// Block read 15 bytes from 0x89 (RESULT__RANGE_STATUS) to 0x97 (lower byte of
// RESULT_DISTANCE). This is faster than reading each register individually.

bus->beginTransmission(address);
bus->write((uint8_t)(RESULT__RANGE_STATUS >> 8)); // reg high byte
bus->write((uint8_t)(RESULT__RANGE_STATUS)); // reg low byte
last_status = bus->endTransmission();

bus->requestFrom(address, (uint8_t)15);

uint8_t buffer[15];
for (uint8_t i = 0; i < 15; i++)
{
buffer[i] = bus->read();
}

uint8_t status = buffer[0] & 0x1F; // 0x89
if (status < 24) { status = status_rtn[status]; }
ranging_data.range_status = status;

ranging_data.number_of_spad = readReg16Bit(RESULT__SPAD_NB) / 256;
ranging_data.signal_rate_kcps = readReg16Bit(RESULT__SIGNAL_RATE) * 8;
ranging_data.ambient_rate_kcps = readReg16Bit(RESULT__AMBIENT_RATE) * 8;
ranging_data.range_mm = readReg16Bit(RESULT__DISTANCE);
// The ULD reads RESULT__SPAD_NB as a 16-bit reg but then divides the value by
// 256, so we can just ignore the lower byte entirely.
ranging_data.number_of_spad = buffer[3]; // 0x8C
ranging_data.signal_rate_kcps = ((uint16_t)buffer[5] << 8 | buffer[6]) * 8; // 0x8E, 0x8F
ranging_data.ambient_rate_kcps = ((uint16_t)buffer[7] << 8 | buffer[8]) * 8; // 0x90, 0x91
ranging_data.sigma_mm = ((uint16_t)buffer[9] << 8 | buffer[10]) / 4; // 0x92, 0x93
ranging_data.range_mm = (uint16_t)buffer[13] << 8 | buffer[14]; // 0x96, 0x97

ranging_data.signal_per_spad_kcps = ranging_data.signal_rate_kcps / ranging_data.number_of_spad;
ranging_data.ambient_per_spad_kcps = ranging_data.ambient_rate_kcps / ranging_data.number_of_spad;
Expand Down
3 changes: 2 additions & 1 deletion src/VL53L4CD.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ class VL53L4CD
{
uint16_t range_mm;
uint8_t range_status;
uint16_t number_of_spad;
uint8_t number_of_spad;
uint16_t signal_rate_kcps;
uint16_t ambient_rate_kcps;
uint16_t signal_per_spad_kcps;
uint16_t ambient_per_spad_kcps;
uint16_t sigma_mm;
};

RangingData ranging_data;
Expand Down

0 comments on commit bc86590

Please sign in to comment.