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

Update:

I have fixed the bug (RdMulti was casting length to a byte, truncating one of the reads).

This now works fine running demos 1 and 2 in the Arduino IDE (after renaming the ULD c and platform files cpp).

Here's my platform.cpp:

/*******************************************************************************
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*
* This file is part of the VL53L5CX Ultra Lite Driver and is dual licensed,
* either 'STMicroelectronics Proprietary license'
* or 'BSD 3-clause "New" or "Revised" License' , at your option.
*
********************************************************************************
*
* 'STMicroelectronics Proprietary license'
*
********************************************************************************
*
* License terms: STMicroelectronics Proprietary in accordance with licensing
* terms at www.st.com/sla0081
*
* STMicroelectronics confidential
* Reproduction and Communication of this document is strictly prohibited unless
* specifically authorized in writing by STMicroelectronics.
*
*
********************************************************************************
*
* Alternatively, the VL53L5CX Ultra Lite Driver may be distributed under the
* terms of 'BSD 3-clause "New" or "Revised" License', in which case the
* following provisions apply instead of the ones mentioned above :
*
********************************************************************************
*
* License terms: BSD 3-clause "New" or "Revised" License.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
*******************************************************************************/
 
 
#include "platform.h"
 
//#define DEBUG_MODE 1
 
uint8_t RdByte(
		VL53L5CX_Platform *p_platform,
		uint16_t RegisterAdress,
		uint8_t *p_value)
{
	
	return RdMulti(p_platform, RegisterAdress, p_value, 1);;
}
 
uint8_t WrByte(
		VL53L5CX_Platform *p_platform,
		uint16_t RegisterAdress,
		uint8_t value)
{
  
  return WrMulti(p_platform, RegisterAdress, &value, 1);
}
 
uint8_t WrMulti(
		VL53L5CX_Platform *p_platform,
		uint16_t RegisterAdress,
		uint8_t *p_values,
		uint32_t size)
{
 
#ifdef DEBUG_MODE
  Serial.print("Beginning transmission to ");
  Serial.print(((p_platform->address) >> 1) & 0x7F, HEX);
  Serial.print("; Writing "); Serial.print(size); Serial.print(" bytes to register 0x");
  Serial.println(RegisterAdress, HEX);
#endif
  Wire.beginTransmission(((uint8_t)(((p_platform->address) >> 1) & 0x7F)));
  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) {  // buffer is full so this byte didn't write, flush buffer and restart sending at new offset
      Wire.endTransmission(false);  // writes out the current tx buffer, but hold the connection open since we're about to use it again
      Wire.beginTransmission(((uint8_t)(((p_platform->address) >> 1) & 0x7F)));  // restart sending data
 
      buffer[0] = (RegisterAdress+i) >> 8;
      buffer[1] = (RegisterAdress+i) & 0xFF;
      Wire.write(buffer, 2);
      if (Wire.write(p_values[i])==0) {
#ifdef DEBUG_MODE
        Serial.println("Re-sending value after buffer flushed failed again");
#endif
      }
    }
    
  }
 
  uint8_t code = Wire.endTransmission(true);
#ifdef DEBUG_MODE
if (code) {
  Serial.print("Write Status:  ");
  Serial.println(code);
}
#endif
  return code;
}
 
uint8_t RdMulti(
		VL53L5CX_Platform *p_platform,
		uint16_t RegisterAdress,
		uint8_t *p_values,
		uint32_t size)
{
  // based on https://github.com/stm32duino/VL53L1 i2c write function
  int status = 0;
  //Loop until the port is transmitted correctly
  do {
    Wire.beginTransmission(((uint8_t)(((p_platform->address) >> 1) & 0x7F)));
#ifdef DEBUG_MODE
    Serial.print("Beginning transmission to ");
    Serial.print(((p_platform->address) >> 1) & 0x7F, HEX);
    Serial.print("; Reading "); Serial.print(size); Serial.print(" bytes from register 0x");
    Serial.println(RegisterAdress, HEX);
#endif
    const uint8_t buffer[2] {RegisterAdress >> 8, RegisterAdress & 0xFF };
    Wire.write(buffer, 2);
    status = Wire.endTransmission(false);
    //Fix for some STM32 boards
    //Reinitialize th i2c bus with the default parameters
#ifdef ARDUINO_ARCH_STM32
    if (status) {
      Wire.end();
      Wire.begin();
    }
#endif
    //End of fix
  } while (status != 0);
 
  Wire.requestFrom(((uint8_t)(((p_platform->address) >> 1) & 0x7F)), size);
 
  int i = 0;
  while (Wire.available()) {
    p_values[i] = Wire.read();
    i++;
  }
 
#ifdef DEBUG_MODE
  Serial.print("Read "); Serial.print(i);  Serial.print("/"); Serial.println(size);
  for (i=0; i<size;i++) { Serial.print(" 0x"); Serial.print(p_values[i], HEX); }
  Serial.println("");
#endif
	return i!=size;
}
 
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 */
	digitalWrite(8, LOW);
	WaitMs(p_platform, 100);
 
	/* Set pin LPN of to HIGH */
	/* Set pin AVDD of to HIGH */
	/* Set pin VDDIO of  to HIGH */
	digitalWrite(8, 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)
{
 
	delay(TimeMs);
	
	return 0;
}

0693W00000DpjsRQAR.gif

So I looked at the three firmware writes to see if they are corrupted and they appear to be shifted to the right by two bytes. The first two bytes for each of the the three writes are zeros and then it matches the firmware - for a while - too big to look at all. I do not know a way to output my analyzer to a readable file to compare against the buffer file. Using Pulseview and an ten dollar analyzer but I am seeing what the code is sending and it is correct aside from the firmware leading zeros. I will keep at this and if I make any progress then I will post it.

J.Duchesne
Associate II

After a lot of scrolling through logic probe data comparing it to what I was seeing I found and fixed the problem in my platform.cpp. It now appears to work fully. I've updated my comment above to contain the fixed version. The current version still requires that the Wire.h read buffer is increased from 256 to 512 though, since it doesn't handle read buffer overflows.

I'm not sure how notifications work here but I've posted a fully working platform.cpp for samd21 elsewhere in this thread.

Thanks for the Wire buffer lesson! This solved it for me.

For next time pulseview ​does let you dump hex or binary i2c data: https://www.sigrok.org/blog/even-more-pulseview-features-you-might-have-missed

That's what I used to debug the same issue. It doesn't separate the data into packets or anything so I had to reformat the data as a single line and search for the starting bytes I wanted in the i2c read or write hex dumps.​

KWine
Senior

Thanks to SBonn2 this now works in the Arduino IDE, see here.

PChat.1
Associate II

Hello,

I am facing the same problem with the Init() Function. Yet a bit earlier because the register 0x06 always gives me a 9 and not 1 as planned... Changing the VL53L5 does not make any difference. The documentation is not very helpful on this one... Have you faced the same issue in the past?

I am using the platform.c of the VL53L1 (for Zephyr).

Thanks for the help

parata.carlo
ST Employee

Hi all,

if you are still interested, I found the reason why the Arduino VL53L5 library did not work with STM32duino Core. Basically, the WrMulti of 0x8000 bytes done to load the firmware in the sensor is too huge for that core and so the firmware is not loaded correctly. In order to fix it, I implemented a new version of the WrMulti, splitting the big written into small chunks. You can find here my Pull Request to fix this issue.

I hope it will be useful for everyone.

Best Regards,

Carlo

Sebastiaan
Senior

I was also struggling with some issues, a specific one that is not yet mentioned in this thread: it seemed important to use 400kHz I2C speed i.o. 100 kHz! (using NRF9160 microcontroller)