cancel
Showing results for 
Search instead for 
Did you mean: 

VL53L5CX driver vl53l5cx_init() fails

Peter111
Associate II

The Ultra Light Driver (STSW-IMG023) init function vl53l5cx_init() fails in this section :

/* Get offset NVM data and store them into the offset buffer */
 
	status |= WrMulti(&(p_dev->platform), 0x2fd8,
 
		(uint8_t*)VL53L5CX_GET_NVM_CMD, sizeof(VL53L5CX_GET_NVM_CMD));
 
	status |= _vl53l5cx_poll_for_answer(p_dev, 4, 0,
 
		VL53L5CX_UI_CMD_STATUS, 0xff, 2);

The sensor does not answer with '2' as expected by _vl53l5cx_poll_for_answer. (The senosr answers '0')

This results in a failed initialization.

How can this be fixed?

50 REPLIES 50
J.Duchesne
Associate II

I am having the exact same problem trying to run the example after platform.c implementation.

It's particularly frustrating given that the read/write functionality appears to be working great until this point.

Here's a log (I suspect this looks pretty much identical to what Peter is seeing):

01:14:54.251 -> Basic Test
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0x7FFF
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Reading 1 bytes from register 0x0
01:14:54.570 ->  0xF0
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Reading 1 bytes from register 0x1
01:14:54.570 ->  0x2
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0x7FFF
01:14:54.570 -> VL53L5CX foound!
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0x7FFF
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0x9
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0xF
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0xA
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Reading 1 bytes from register 0x7FFF
01:14:54.570 ->  0x0
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0xC
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0x101
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0x102
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0x10A
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0x4002
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0x4002
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0x10A
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0x103
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0xC
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0xF
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0xF
01:14:54.570 -> Beginning transmission to 29
01:14:54.570 -> Writing 1 bytes to register 0xA
01:14:54.669 -> Beginning transmission to 29
01:14:54.669 -> Writing 1 bytes to register 0x7FFF
01:14:54.669 -> Beginning transmission to 29
01:14:54.669 -> Reading 1 bytes from register 0x6
01:14:54.669 ->  0x1
01:14:54.669 -> Beginning transmission to 29
01:14:54.669 -> Writing 1 bytes to register 0xE
01:14:54.669 -> Beginning transmission to 29
01:14:54.669 -> Writing 1 bytes to register 0x7FFF
01:14:54.669 -> Beginning transmission to 29
01:14:54.669 -> Writing 1 bytes to register 0x3
01:14:54.669 -> Beginning transmission to 29
01:14:54.669 -> Writing 1 bytes to register 0x7FFF
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Reading 1 bytes from register 0x21
01:14:54.702 ->  0x10
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x7FFF
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0xC
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x7FFF
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x101
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x102
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x10A
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x4002
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x4002
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x10A
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x103
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x400F
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x21A
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x21A
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x21A
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x21A
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x219
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x21B
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x7FFF
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0xC
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x7FFF
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x20
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x20
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 1 bytes to register 0x7FFF
01:14:54.702 -> Beginning transmission to 29
01:14:54.702 -> Writing 32768 bytes to register 0x0
01:14:54.770 -> Beginning transmission to 29
01:14:54.770 -> Writing 1 bytes to register 0x7FFF
01:14:54.770 -> Beginning transmission to 29
01:14:54.770 -> Writing 32768 bytes to register 0x0
01:14:54.837 -> Beginning transmission to 29
01:14:54.837 -> Writing 1 bytes to register 0x7FFF
01:14:54.837 -> Beginning transmission to 29
01:14:54.837 -> Writing 20480 bytes to register 0x0
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0x7FFF
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0x7FFF
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0x3
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0x7FFF
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Reading 1 bytes from register 0x21
01:14:54.871 ->  0x10
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0x7FFF
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0xC
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0x7FFF
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0x114
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0x115
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0x116
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0x117
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0xB
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0xC
01:14:54.871 -> Beginning transmission to 29
01:14:54.871 -> Writing 1 bytes to register 0xB
01:14:54.905 -> Beginning transmission to 29
01:14:54.905 -> Reading 1 bytes from register 0x6
01:14:54.905 ->  0x0
01:14:54.905 -> Beginning transmission to 29
01:14:54.905 -> Writing 1 bytes to register 0x7FFF
01:14:54.905 -> Beginning transmission to 29
01:14:54.905 -> Writing 40 bytes to register 0x2FD8
01:14:54.905 -> Beginning transmission to 29
01:14:54.905 -> Reading 4 bytes from register 0x2C00
01:14:54.905 ->  0x0 0x0 0x0 0x0
01:14:54.905 -> Beginning transmission to 29
01:14:54.905 -> Reading 4 bytes from register 0x2C00
01:14:54.905 ->  0x0 0x0 0x0 0x0
01:14:54.938 -> Beginning transmission to 29

That last section repeats forever (trying to read from VL53L5CX_UI_CMD_STATUS, looking for 2, finding 0.

SBonn.2
Associate II

I am also having the same issue. In my case I am trying to connect from a SAMD21 board using the Arduino framework, if that is relevant. I hooked up a logic analyzer and found the same conclusion, it fails during the _vl53l5cx_poll_for_answer call right after the comment "/* Get offset NVM data and store them into the offset buffer */". According to the logic analyzer I was getting the following 4 bytes: 0x98, 0x56, 0x37, and 0xD1. Not all 0's which is a bit different. In my case the code did continue (after the insane 200 retry timeout) and every single _vl53l5cx_poll_for_answer call after that did the same thing.

J.Duchesne
Associate II

Interesting. I'm also using a samd21 based Arduino board (seeduino Xiao).

I'm wondering if the samd21 Wire implementation (the Arduino i2c library) is doing something that the device isn't expecting. I've also got a logic analyzer and I'd like to check that the firmware download is being sent correctly (comparing to the sprc sheet's i2c diagrams. Overall the ultralige driver is not doing any error checking, and just barreling through whatever responses come without heed until it gets stuck.

I'm not sure how your poll for answer call is timing out though, I can't find any exit condition from the loop (the ​timeout just sets error bits in the return code) (1.0.4 ultralite driver.

The init section is also a wall of magic numbers without any documentation so my ability to troubleshoot is quite limited.​

I now found the reason for the problem. The send-2 bytes-function was implemented wrong by me, so the ToF-FW was not written to the device correctly. When i fixed it, the problem was solved. Am 18.08.2021 17:15 schrieb ST Community : Interesting. I'm also using a samd21 based Arduino board (seeduino Xiao). I'm wondering if the samd21 Wire implementation (the Arduino i2c library) is doing something that the device isn't expecting. I've also got a logic analyzer and I'd like to check that the firmware download is being sent correctly (comparing to the sprc sheet's i2c diagrams. Overall the ultralige driver is not doing any error checking, and just barreling through whatever responses come without heed until it gets stuck. ​ I'm not sure how your poll for answer call is timing out though, I can't find any exit condition from the loop (the ​timeout just sets error bits in the return code) (1.0.4 ultralite driver. ​ The init section is also a wall of magic numbers without any documentation so my ability to troubleshoot is quite limited.​ [https://community.st.com/img/userprofile/default_profile_45_v2.png?fromEmail=1]<> JDuch.1<> (Community Member) Interesting. I'm also using a samd21 based Arduino board (seeduino Xiao). I'm wondering if the samd21 Wire implementation (the Arduino i2c library) is doing something that the device isn't expecting. I've also got a logic analyzer and I'd like to check that the firmware download is being sent correctly (comparing to the sprc sheet's i2c diagrams. Overall the ultralige driver is not doing any error checking, and just barreling through whatever responses come without heed until it gets stuck. ​ I'm not sure how your poll for answer call is timing out though, I can't find any exit condition from the loop (the ​timeout just sets error bits in the return code) (1.0.4 ultralite driver. ​ The init section is also a wall of magic numbers without any documentation so my ability to troubleshoot is quite limited.​ View/Answer<> or reply to this email Replying to [https://community.st.com/img/userprofile/default_profile_45_v2.png?fromEmail=1]<> Peter111<> (Community Member) asked a question. Wednesday, August 11, 2021 2:47 AM<> VL53L5CX driver vl53l5cx_init() fails The Ultra Light Driver (STSW-IMG023) init function vl53l5cx_init() fails in this section : /* Get offset NVM data and store them into the offset buffer */ status |= WrMulti(&(p_dev->platform), 0x2fd8, (uint8_t*)VL53L5CX_GET_NVM_CMD, sizeof(VL53L5CX_GET_NVM_CMD)); status |= _vl53l5cx_poll_for_answer(p_dev, 4, 0, VL53L5CX_UI_CMD_STATUS, 0xff, 2); The sensor does not answer with '2' as expected by _vl53l5cx_poll_for_answer. (The senosr answers '0') This results in a failed initialization. How can this be fixed? [https://community.st.com/img/userprofile/default_profile_45_v2.png?fromEmail=1]<> JDuch.1<> (Community Member) Interesting. I'm also using a samd21 based Arduino board (seeduino Xiao). I'm wondering if the samd21 Wire implementation (the Arduino i2c library) is doing something that the device isn't expecting. I've also got a logic analyzer and I'd like to check that the firmware download is being sent correctly (comparing to the sprc sheet's i2c diagrams. Overall the ultralige driver is not doing any error checking, and just barreling through whatever responses come without heed until it gets stuck. ​ I'm not sure how your poll for answer call is timing out though, I can't find any exit condition from the loop (the ​timeout just sets error bits in the return code) (1.0.4 ultralite driver. ​ The init section is also a wall of magic numbers without any documentation so my ability to troubleshoot is quite limited.​ Wednesday, August 18, 2021 8:15 AM<> You're receiving emails when someone "Comments on my posts." To change or turn off ST Community email, log in<> as felix.hundhausen@kit.edu.st. Are notifications about this post getting annoying? Reply to this email with the word " mute ". STMicroelectronics N.V. [ST Community]

What "send-2 bytes-function" ? The API only uses WrByte or WrMulti and that is all I set up in the platform files. I do not see where the API calls any other. Are you using the ULP provided by ST? Can you share any of the code?

RRace
Associate II

I am also having the exact same issue. I am getting random responses on two SATEL breakouts. After each hard reset, I get all zeros or random number in the four bytes that are read. It is peculiar that the poll for answer works as expected on the the preceding calls but just not this one specific call. Just keeps going around around and around. Funny that is just looking for a 2 out of a byte but never gets it!…. AHHHHH

I am using a SAMD21 with Arduino Wire. No problems on the VL53L0X or VL53L0X with this setup.

VL53L5CX_ULD_driver_1.0.4

platform code below. Any idea or suggestions?

 
#include "platform.h"
#include <Arduino.h>
#include <Wire.h>
 
 
 
uint8_t RdByte(
		VL53L5CX_Platform *p_platform,
		uint16_t RegisterAdress,
		uint8_t *p_value)
{
	uint8_t status = 255;
 
	Wire.beginTransmission(p_platform->address);
	Wire.write((RegisterAdress >> 8) & 0xFF);
	Wire.write(RegisterAdress & 0xFF); 
  	status = Wire.endTransmission();
 
	Wire.requestFrom(p_platform->address, 1);
	*p_value = Wire.read();	
 
	return status;
}
 
uint8_t WrByte(
		VL53L5CX_Platform *p_platform,
		uint16_t RegisterAdress,
		uint8_t value)
{
	uint8_t status = 255;
 
	Wire.beginTransmission(p_platform->address);
	Wire.write((RegisterAdress >> 8) & 0xFF);
	Wire.write(RegisterAdress & 0xFF); 
  	Wire.write(value);
  	status = Wire.endTransmission();
 
	return status;
}
 
uint8_t WrMulti(
		VL53L5CX_Platform *p_platform,
		uint16_t RegisterAdress,
		uint8_t *p_values,
		uint32_t size)
{
	uint8_t status = 255;
	
	Wire.beginTransmission(p_platform->address);
	Wire.write((RegisterAdress >> 8) & 0xFF);
	Wire.write(RegisterAdress & 0xFF); 
 
	while(size--){
		Wire.write(*p_values);
		p_values++;
	}
	
	status = Wire.endTransmission();
 
	return status;
}
 
uint8_t RdMulti(
		VL53L5CX_Platform *p_platform,
		uint16_t RegisterAdress,
		uint8_t *p_values,
		uint32_t size)
{
	uint8_t status = 255;
 
	Wire.beginTransmission(p_platform->address);
	Wire.write((RegisterAdress >> 8) & 0xFF);
	Wire.write(RegisterAdress & 0xFF); 
  	status = Wire.endTransmission();
 
	Wire.requestFrom(p_platform->address, size);
 
	while(size--){
		*p_values = Wire.read();
		p_values++;
	}
	
	return status;
}
 
uint8_t Reset_Sensor(
		VL53L5CX_Platform *p_platform)
{
	uint8_t status = 0;
	
	/* (Optional) Need to be implemented by customer. This function returns 0 if OK */
	
	/* Set pin LPN to LOW */
	/* Set pin AVDD to LOW */
	/* Set pin VDDIO  to LOW */
	WaitMs(p_platform, 100);
 
	/* Set pin LPN of to HIGH */
	/* Set pin AVDD of to HIGH */
	/* Set pin VDDIO of  to HIGH */
	WaitMs(p_platform, 100);
 
	return status;
}
 
void SwapBuffer(
		uint8_t 		*buffer,
		uint16_t 	 	 size)
{
	uint32_t i, tmp;
	
	// Example of possible implementation using <string.h> 
	for(i = 0; i < size; i = i + 4) 
	{
		tmp = (
		  buffer[i]<<24)
		|(buffer[i+1]<<16)
		|(buffer[i+2]<<8)
		|(buffer[i+3]);
		
		memcpy(&(buffer[i]), &tmp, 4);
	}
}	
 
uint8_t WaitMs(
		VL53L5CX_Platform *p_platform,
		uint32_t TimeMs)
{
	uint8_t status = 0;
 
	/* Need to be implemented by customer. This function returns 0 if OK */
	delay(TimeMs);
	
	return status;
}

I am also confused by that, clarification would be very helpful.

J.Duchesne
Associate II

My code looks pretty much the same, with a few caveats:

Wire seems to want the address bit shifted by 1 right:

((p_platform->address) >> 1) & 0x7F

The samd21 rx and tx buffers are too small for a few of the operations (256b each):

The RX buffer is too small for one of the read operations ~450 bytes), so I went into the samd21's Wire.h and bumped it from 256 to 512. As far as I can tell this is larger than any of the i2c reads that the uld needs.

The TX buffer on the other hand is way too small and I ran into memory errors when I tried setting it to the largest size used (0x8000 bytes).

Instead, I added a check for the write buffer size (hard coded for now) and use the SERCOM device directly the "manually" send each byte for larger data.

This is super slow since it's not draining the buffer on i2c interrupts, and instead polling one byte at a time, but it does seem to allow the firmware load to work:

uint8_t WrMultiLarge(VL53L5CX_Platform *p_platform,
   uint16_t RegisterAdress,
    uint8_t *p_values,
    uint32_t size) {
   // Solution based on https://forum.arduino.cc/t/stream-large-array-to-i2c-slave/659405/4
  
   // uses raw I2C writes, rather than use the txbuffer
   PERIPH_WIRE.startTransmissionWIRE(((p_platform->address) >> 1) & 0x7F, WIRE_WRITE_FLAG);
 
   // Send address of register
   PERIPH_WIRE.sendDataMasterWIRE((byte)(RegisterAdress >> 8));
   PERIPH_WIRE.sendDataMasterWIRE((byte)(RegisterAdress & 0xFF));
 
   // send one byte at a time from the array to the I2C device
   for (unsigned int i = 0; i < size; i++) {
     if (!PERIPH_WIRE.sendDataMasterWIRE((byte) p_values[i])){ 
      Serial.println("Write error at index "); Serial.println(i); 
    }
   }
  
   // stop sending the data
   PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
 
  return 0;  // No error checking :(
}
 
uint8_t WrMulti(
		VL53L5CX_Platform *p_platform,
		uint16_t RegisterAdress,
		uint8_t *p_values,
		uint32_t size)
{
  // The arduino Wire TX buffer size found in your arduino core's Wire.h
  // For samd21 this is 256, but for other cores it varies widely
  if (size>=256) {  
    return WrMultiLarge(p_platform, RegisterAdress, p_values, size);
  }
 
  Wire.beginTransmission(((uint8_t)(((p_platform->address) >> 1) & 0x7F)));
 
  const uint8_t buffer[2] {RegisterAdress >> 8, RegisterAdress & 0xFF };
  Wire.write(buffer, 2);
  for (uint32_t i = 0 ; i < size ; i++) {
  
    if(Wire.write(p_values[i])==0){ Serial.print("Write error at offset "); Serial.println(i); }
  }
 
  uint8_t code = Wire.endTransmission(true);
  return code;
}

This allows the device to initialize without error and go into ranging mode without error, but it's now getting stuck at

status = vl53l5cx_check_data_ready(&Dev, &isReady);

The status register always returns

0xFF 0x5 0xC5 0x81

And the function is looking for:

[0] != 255     // fails, stays 255 always. Should contain stream count when ready.
[1] == 0x05    // pass
[2]            // & 0x5 == 0x5, pass, value is 0xC5
[3]            // & 0x10 == 0x10, fail. Stays 0x81

I'm not really sure where to go from here other than capture the full i2c transmission on a logic probe and start going through every single rx and tx looking for errors. I may try that later.

Hmmm, I was misremembering the poll function, thought that the timeout <= 200 part was to break out of the loop. I see what you are saying now. For some reason mine does break out of the loop eventually, despite never getting the value it is looking for. Odd. Regardless, the Wire library in theory has a buffer of only 32 bytes, at least according to Arduino’s documentation. But I definitely saw much more than 32 bytes being sent correctly.

I did not verify the entire firmware transmission unfortunately, but that might be a good next step. My analyzer’s capture was short of the entire init function by about a second or so I’d say, missed the last 2-3 I2C transactions, but it did capture the full firmware image write. So I should be able to compare that to what it should have been.

I also agree, there should definitely be some more error checking along the way. If the very first poll to answer function fails, the entire rest of the init function runs before it checks that? Very weird.