Skip to main content
Peter111
Associate
August 11, 2021
Question

VL53L5CX driver vl53l5cx_init() fails

  • August 11, 2021
  • 19 replies
  • 18433 views

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?

19 replies

J.Duchesne
Associate
August 18, 2021

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
Visitor II
August 18, 2021

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
August 18, 2021

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.​

Peter111
Peter111Author
Associate
August 18, 2021
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]
RRace
Explorer
August 18, 2021

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
Explorer
August 18, 2021

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;
}

J.Duchesne
Associate
August 18, 2021

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

J.Duchesne
Associate
August 18, 2021

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.

J.Duchesne
Associate
August 18, 2021

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

J.Duchesne
Associate
August 18, 2021

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.

RRace
Explorer
August 18, 2021

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

KWine
Senior
August 20, 2021

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

PChat.1
Associate
August 28, 2021

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
November 9, 2021

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
Associate II
January 7, 2022

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)

jspiller
Associate II
May 12, 2022

Hey Sebastiaan,

Are you using Zephyr? I'm running into the initial issue in this thread with the _vl53l5cx_poll_for_answer() timing out. Did you get this driver working on your end with Zephyr by chance? I am thinking the firmware did not upload correctly.

Thanks,

Jacob

Sebastiaan
Associate II
May 13, 2022

Hi Jacob,

Yes I got this working. I indeed did some changes on the poll_for_answer function but not sure anymore why exactly. In general I also removed all the "p_dev" stuff from all calls. See the "//changed" comment in below, that's definitely something I changed, but I don't remember why exactly (maybe this was not necessary at all and I only used it during debugging?)

Are you using 100 kHz or 400 kHz I2C speed?

	uint8_t status = VL53L5CX_STATUS_OK;
	uint8_t timeout = 0;
 
	do
	{
		status |= RdMulti(address, p_dev->temp_buffer, size);
		status |= WaitMs(10);
 
		if (timeout >= (uint8_t)200) /* 2s timeout */
		{
			status |= p_dev->temp_buffer[2];
		}
		else
		{
			if ((size >= (uint8_t)4) && (p_dev->temp_buffer[2] >= (uint8_t)0x7f))
			{
 timeout++; //changed...
				status |= VL53L5CX_MCU_ERROR;
			}
			else
			{
				timeout++;
			}
		}
	} while ((p_dev->temp_buffer[pos] & mask) != expected_value);
 
	return status;