cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to read ID Register directly

mttdarko
Associate II

Hello, 

 

As suggested in my last post here, I am trying to read the ID Value of a VL53L1X sensor. I get a read failure when I attempt to read the register. Strangely, I have slightly modified code that I am using to read the ID register of a VL53l0X which I am able to run successfully. Further, I know I do not have a hardware or wiring problem because I am able to use the sensor for ranging just fine. I have copied my basic ESP32 Arduino sketch below, any ideas what I'm doing wrong? Thanks in advance

 

 

 

#include <Wire.h> // Include Wire library for I2C communication

// I2C address of the VL53L1X sensor (0x29)
#define VL53L1X_ADDRESS 0x29
// Register addresses
#define VL53L1X_IDENTIFICATION_MODEL_ID  0x010F // Model ID register (lower byte)
#define VL53L1X_IDENTIFICATION_REVISION  0x0110 // Model revision register (upper byte)


void setup() {
  Serial.begin(115200);
  Serial.println("Starting VL53L1X sensor test (I2C access)");

  // Read ID registers directly using I2C communication
  uint8_t model_id = readRegister(VL53L1X_ADDRESS, VL53L1X_IDENTIFICATION_MODEL_ID);
  Serial.print("Model ID: ");
  Serial.println(model_id, HEX);
  uint8_t revision_id = readRegister(VL53L1X_ADDRESS, VL53L1X_IDENTIFICATION_REVISION);
  Serial.print("Revision ID: ");
  Serial.println(revision_id, HEX);

  // Combine model and revision for complete ID (optional)
  uint16_t sensor_id = (revision_id << 8 | model_id;

  Serial.print("Sensor ID: 0x");
  Serial.println(sensor_id, HEX);
}

uint8_t readRegister(uint8_t address, uint8_t reg) {
  Wire.beginTransmission(address);
  Wire.write(reg);
  Wire.endTransmission();

  Wire.requestFrom(address, 1);
  if (Wire.available() == 1) {
    return Wire.read();
  } else {
    Serial.println("Failed to read register!");
    return 0;
  }
}

void loop() {
}

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions

Hi John, 

This problem has been solved! You are correct in that the main issue was in writing the address. I got out the logic analyzer and with that simplified code, it was actually only writing 0x0F, which I thought was interesting for a few reasons. In the documentation for the Wire library, it claims to have a 32 bit buffer, seemingly implying that you did not need to explicitly do anything special based on but length of the address, but this was not the case. I'm also a little bit curious as to why the last byte was what was written, and not the first. 

 

Another issue was in my handling of the returned data. I needed to save each byte separately and then bit shift and combine them. 

 

My working simplified code (tested on an ESP32 in Arduino) is pasted below in the hopes that this can help someone else in the future: 

 

#include <Wire.h>

void setup() {
  uint8_t buffer[2] = {0,0};
  buffer[0]=(uint8_t) (0x010F >> 8);
  buffer[1]=(uint8_t) (0x010F & 0xFF);
  uint8_t pBuffer[2] = {0,0};
  Serial.begin(115200);
  Wire.begin();
  Wire.beginTransmission(0x29);
  Wire.write(buffer, 2);
  Wire.endTransmission(false);
  Wire.requestFrom(0x29, 2);
  int i = 0;
  while (Wire.available()) {
    pBuffer[i] = Wire.read();
    i++;
 }
  int ID = (pBuffer[0] << 8 + pBuffer[1];
  Serial.print("ID: 0x");
  Serial.println(ID, HEX);
}

void loop() {
}

 

View solution in original post

5 REPLIES 5
John E KVAM
ST Employee

The issue is 2-byte addresses. There are a lot of registers on the vl53L0 so there are page registers to switch pages. On the L1 (and all the other VL53 sensors ) we send 2-byte register addresses. This avoids using a lot of pages, but forces you to change your i2c functions so that each register address is 2-bytes. 
good luck

-john


Our community relies on fruitful exchanges and good quality content. You can thank and reward helpful and positive contributions by marking them as 'Accept as Solution'. When marking a solution, make sure it answers your original question or issue that you raised.

ST Employees that act as moderators have the right to accept the solution, judging by their expertise. This helps other community members identify useful discussions and refrain from raising the same question. If you notice any false behavior or abuse of the action, do not hesitate to 'Report Inappropriate Content'
mttdarko
Associate II

Hi John, thanks for this. I have made the changes you suggested and simplified my code entirely. Unfortunately, I am still having a similar issue. While it no longer hangs with data unavailable, the data is not what is expected, I either read a 0x0 or 0xFF. I looked into the documentation for the Wire.h library and it uses a 32byte buffer, so there should be no issues sending the two byte address. Anything else I can try?

#include <Wire.h>

#define VL53L1X_ADDRESS 0x29
#define VL53L1X_IDENTIFICATION 0x010F

// I2C read function with 2-byte register address
uint8_t readRegister(uint16_t reg) {
  Wire.beginTransmission(VL53L1X_ADDRESS);
  Wire.write(reg);
  Wire.endTransmission(false);
  Wire.requestFrom(VL53L1X_ADDRESS, 1);
  if (Wire.available() == 1) {
    return Wire.read();
  } else {
    Serial.println("Failed to read register!");
    return 0;
  }
}

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

  uint16_t id = readRegister(VL53L1X_IDENTIFICATION);
  Serial.print("ID: 0x");
  Serial.println(id, HEX);
}

void loop() {
}
John E KVAM
ST Employee

I'm not completely convinced your call to 

Wire.write(reg);

'knows', reg is a 16-byte integer. But I'll believe you. 

It could also be an issue with 'byte swap". How did you determine which of the address bytes should be first? Instead of getting the data at 0x0001, you could easily be getting the data at 0x0100. This issue is way more common than one might guess. And it requires a careful reading of the I2C section of the data sheet. 

I have 2 suggestions:

For $100 or so, one can buy a mini logic analyzer that connects to the USB connector of your PC. It's a handy bit of kit and will analyze your I2C for you. There are other I2C bus analyzers, but they don't have any other use. 

The other idea is to search GitHub for some already working code. People are really generous, and post working projects. Look for one that uses the VL53L1, L3 or L4, L5, L7 or L8 and your MCU or preferred language. You might find that someone has already fought this battle for you. 

And you might consider posting when you get this bug solved as well. 


Our community relies on fruitful exchanges and good quality content. You can thank and reward helpful and positive contributions by marking them as 'Accept as Solution'. When marking a solution, make sure it answers your original question or issue that you raised.

ST Employees that act as moderators have the right to accept the solution, judging by their expertise. This helps other community members identify useful discussions and refrain from raising the same question. If you notice any false behavior or abuse of the action, do not hesitate to 'Report Inappropriate Content'

Hi John, 

This problem has been solved! You are correct in that the main issue was in writing the address. I got out the logic analyzer and with that simplified code, it was actually only writing 0x0F, which I thought was interesting for a few reasons. In the documentation for the Wire library, it claims to have a 32 bit buffer, seemingly implying that you did not need to explicitly do anything special based on but length of the address, but this was not the case. I'm also a little bit curious as to why the last byte was what was written, and not the first. 

 

Another issue was in my handling of the returned data. I needed to save each byte separately and then bit shift and combine them. 

 

My working simplified code (tested on an ESP32 in Arduino) is pasted below in the hopes that this can help someone else in the future: 

 

#include <Wire.h>

void setup() {
  uint8_t buffer[2] = {0,0};
  buffer[0]=(uint8_t) (0x010F >> 8);
  buffer[1]=(uint8_t) (0x010F & 0xFF);
  uint8_t pBuffer[2] = {0,0};
  Serial.begin(115200);
  Wire.begin();
  Wire.beginTransmission(0x29);
  Wire.write(buffer, 2);
  Wire.endTransmission(false);
  Wire.requestFrom(0x29, 2);
  int i = 0;
  while (Wire.available()) {
    pBuffer[i] = Wire.read();
    i++;
 }
  int ID = (pBuffer[0] << 8 + pBuffer[1];
  Serial.print("ID: 0x");
  Serial.println(ID, HEX);
}

void loop() {
}

 

John E KVAM
ST Employee

If you want to be a real hero, create a program that does a bit more with the sensor an publish it on GitHub. 

That's where a lot of people go when looking for VL53 code running on a ESP32 in Arduino. 

They don't generally go to ST because we kind of push the STM32 line of microprocessors. 

As a sensor guy, I support anything with an I2C interface, but as an ST employee I favor the STM32s.

Cheers, and well done.

- john


Our community relies on fruitful exchanges and good quality content. You can thank and reward helpful and positive contributions by marking them as 'Accept as Solution'. When marking a solution, make sure it answers your original question or issue that you raised.

ST Employees that act as moderators have the right to accept the solution, judging by their expertise. This helps other community members identify useful discussions and refrain from raising the same question. If you notice any false behavior or abuse of the action, do not hesitate to 'Report Inappropriate Content'