cancel
Showing results for 
Search instead for 
Did you mean: 

VL53L4CD give back a wrong ID

CPoisson
Associate III

Hi ! I'm using the VL53L4CD sensor's example with the Nucleo-L432KC.

A first problem I solved was that the VL53L4CD didn't have the adress 0x52 as in the documentation, but 0x29 (this problem has already mentioned in a topic).

My current problem is that the following code return a good status but a wrong id :
'''

/* (Optional) Check if there is a VL53L4CD sensor connected */
status = VL53L4CD_GetSensorId(dev, &sensor_id);
if(status || (sensor_id != 0xEBAA))
{
printf("VL53L4CD not detected at requested address\n");
printf("Sensor ID : %d\r\n", sensor_id);
return status;
}

'''

It gives back the address 0.

It should be the basic code, but it doesn't work.
Have you got a solution ?

Thank you !

 

Clément Poisson.

1 ACCEPTED SOLUTION

Accepted Solutions
John E KVAM
ST Employee

I'm stuck setting up for CES, and I cannot verify it, but I think I see something. 

The VL53 sensors (unlike other I2C devices) use a 16 bit address to decide which location to read.

uint8_t VL53L4CD_WrDWord(Dev_t dev, uint16_t RegisterAdress, uint32_t value)

 

That uint16_t is not kidding. They really want that.

But later you have the line:

	status = HAL_I2C_Mem_Write(I2C, dev, (uint8_t)RegisterAdress,1, (uint8_t*)towrite, 4, I2CTIMEOUT);

This sends only half the register address. I think changing the 1 to a 2 should do it. 

Fix it in all locations.

- john 


If this or any post solves your issue, please mark them as 'Accept as Solution' It really helps. And if you notice anything wrong do not hesitate to 'Report Inappropriate Content'. Someone will review it.

View solution in original post

5 REPLIES 5
John E KVAM
ST Employee

The first thing to know about the I2C bus is that it has a funny addressing scheme. 

There is a base address, and to make the write address, one shifts the base to the left one bit. 

The LSB is now the Write/Read bit.

So 0x29 turns into 0x52 as a write address and 0x53 as a read address. 

So when it comes to I2C 0x29 is 0x52. 

(And i know, it's a mess. )

I'm going to guess that you don't get a good ID because your chip is not on, and your I2C read command is timing out. 

Unfortunately that "if ( status || ( sensor_id != 0xEBAA ))" does not distinguish between an I2C timeout and no data.

i've included a bit of verification code.

But do check that the Xshut line is high and that you have power. 

- john


If this or any post solves your issue, please mark them as 'Accept as Solution' It really helps. And if you notice anything wrong do not hesitate to 'Report Inappropriate Content'. Someone will review it.
CPoisson
Associate III

Thank you so much for your answer, I now understand about the 7bits I2C adress and finally find the 0x52 et 0x53.
I used your I2C verification function, but it still doesn't give a good result :
expected = ebaa10ff,
read_bytes = 0, 29, 0, 0
read words = 0, 56a2
read dword = 0
Even regarding the bit to bit, I don't see any correspondances or logic between theses results.

Here is my platform file for the read/write functions :

/*
 Copyright (c) 2021, STMicroelectronics - All Rights Reserved

 This file : part of VL53L4CD Ultra Lite Driver and : 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 : strictly prohibited unless
 specifically authorized in writing by STMicroelectronics.


*******************************************************************************

 Alternatively, VL53L4CD 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:

 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"

uint8_t VL53L4CD_RdDWord(Dev_t dev, uint16_t RegisterAdress, uint32_t *value)
{
	uint8_t status = 255;
	
	uint8_t temp[4];
	status = HAL_I2C_Mem_Read(I2C, dev, (uint8_t)RegisterAdress,1, temp, 4, I2CTIMEOUT);
	*value = (((uint32_t)temp[0])<<24) | (((uint32_t)temp[1])<<16) | (((uint32_t)temp[2])<<8) | (temp[3]);
	checkI2CError(status);
	
	return status;
}

uint8_t VL53L4CD_RdWord(Dev_t dev, uint16_t RegisterAdress, uint16_t *value)
{
	uint8_t status = 255;
	
	uint8_t temp[4];
	status = HAL_I2C_Mem_Read(I2C, dev, (uint8_t)RegisterAdress,1, temp, 2, I2CTIMEOUT);
    *value = (((uint16_t)temp[0])<<8) | (temp[1]);
	checkI2CError(status);

	return status;
}

uint8_t VL53L4CD_RdByte(Dev_t dev, uint16_t RegisterAdress, uint8_t *value)
{
	uint8_t status = 255;
	
	status = HAL_I2C_Mem_Read(I2C, dev, (uint8_t)RegisterAdress,1, value, 1, I2CTIMEOUT);
	checkI2CError(status);
	
	return status;
}

uint8_t VL53L4CD_WrByte(Dev_t dev, uint16_t RegisterAdress, uint8_t value)
{
	uint8_t status = 255;

	status = HAL_I2C_Mem_Write(I2C, dev, (uint8_t)RegisterAdress,1, &value, 1, I2CTIMEOUT);
	checkI2CError(status);

	return status;
}

uint8_t VL53L4CD_WrWord(Dev_t dev, uint16_t RegisterAdress, uint16_t value)
{
	uint8_t status = 255;
	
	uint8_t towrite[2];
	towrite[0]=(uint8_t)(value>>8 & 0xFF); //MSB
	towrite[1]=(uint8_t)(value & 0xFF); //LSB
    status = HAL_I2C_Mem_Write(I2C, dev, (uint8_t)RegisterAdress,1, (uint8_t*)towrite, 2, I2CTIMEOUT);
	checkI2CError(status);
	
	return status;
}

uint8_t VL53L4CD_WrDWord(Dev_t dev, uint16_t RegisterAdress, uint32_t value)
{
	uint8_t status = 255;

	uint8_t towrite[4];
	towrite[0]=(uint8_t)(value>>24 & 0xFF); //MSB
	towrite[1]=(uint8_t)(value>>16 & 0xFF);
	towrite[2]=(uint8_t)(value>>8 & 0xFF);
	towrite[3]=(uint8_t)(value & 0xFF); //LSB
	status = HAL_I2C_Mem_Write(I2C, dev, (uint8_t)RegisterAdress,1, (uint8_t*)towrite, 4, I2CTIMEOUT);
	checkI2CError(status);

	return status;
}

uint8_t WaitMs(Dev_t dev, uint32_t TimeMs)
{
	uint8_t status = 255;

	HAL_Delay(TimeMs);
	
	return status;
}

void checkI2CError(uint8_t status)
{
	if (status != HAL_OK) {
		printf("I2C error: ");
		I2C_HandleTypeDef *hi2c; // Assume hi2c is initialized and points to your I2C handle

		if (hi2c->ErrorCode & HAL_I2C_ERROR_BERR) {
			printf("Bus error\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_ARLO) {
			printf("Arbitration lost error\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_AF) {
			printf("Acknowledge failure\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_OVR) {
			printf("Overrun error\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_DMA) {
			printf("DMA transfer error\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_TIMEOUT) {
			printf("Timeout error\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_SIZE) {
			printf("Size mismatch\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_NONE) {
			printf("No error\n");
		}
	}
}

 

Do you have a solution ? Or do you see an error in the platform ?

Thank you again for your time !

Clement Poisson.

CPoisson
Associate III

I just precise that the message "I2C test failed" isn't printed*

John E KVAM
ST Employee

I'm stuck setting up for CES, and I cannot verify it, but I think I see something. 

The VL53 sensors (unlike other I2C devices) use a 16 bit address to decide which location to read.

uint8_t VL53L4CD_WrDWord(Dev_t dev, uint16_t RegisterAdress, uint32_t value)

 

That uint16_t is not kidding. They really want that.

But later you have the line:

	status = HAL_I2C_Mem_Write(I2C, dev, (uint8_t)RegisterAdress,1, (uint8_t*)towrite, 4, I2CTIMEOUT);

This sends only half the register address. I think changing the 1 to a 2 should do it. 

Fix it in all locations.

- john 


If this or any post solves your issue, please mark them as 'Accept as Solution' It really helps. And if you notice anything wrong do not hesitate to 'Report Inappropriate Content'. Someone will review it.
CPoisson
Associate III

Oh yes of curse ! Thank you so much for your help !
I am just giving my corrected platform to help who would want it.

/*
 Copyright (c) 2021, STMicroelectronics - All Rights Reserved

 This file : part of VL53L4CD Ultra Lite Driver and : 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 : strictly prohibited unless
 specifically authorized in writing by STMicroelectronics.


*******************************************************************************

 Alternatively, VL53L4CD 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:

 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"

uint8_t VL53L4CD_RdDWord(Dev_t dev, uint16_t RegisterAdress, uint32_t *value)
{
	uint8_t status = 255;
	
	uint8_t temp[4];
	status = HAL_I2C_Mem_Read(I2C, dev, RegisterAdress,2, temp, 4, I2CTIMEOUT);
	*value = (((uint32_t)temp[0])<<24) | (((uint32_t)temp[1])<<16) | (((uint32_t)temp[2])<<8) | (temp[3]);
	checkI2CError(status);
	
	return status;
}

uint8_t VL53L4CD_RdWord(Dev_t dev, uint16_t RegisterAdress, uint16_t *value)
{
	uint8_t status = 255;
	
	uint8_t temp[2];
	status = HAL_I2C_Mem_Read(I2C, dev, RegisterAdress,2, &temp, 2, I2CTIMEOUT);
    *value = (((uint16_t)temp[0])<<8) | (temp[1]);
	checkI2CError(status);

	return status;
}

uint8_t VL53L4CD_RdByte(Dev_t dev, uint16_t RegisterAdress, uint8_t *value)
{
	uint8_t status = 255;
	
	status = HAL_I2C_Mem_Read(I2C, dev, RegisterAdress,2, value, 1, I2CTIMEOUT);
	checkI2CError(status);
	
	return status;
}

uint8_t VL53L4CD_WrByte(Dev_t dev, uint16_t RegisterAdress, uint8_t value)
{
	uint8_t status = 255;

	status = HAL_I2C_Mem_Write(I2C, dev, RegisterAdress,2, &value, 1, I2CTIMEOUT);
	checkI2CError(status);

	return status;
}

uint8_t VL53L4CD_WrWord(Dev_t dev, uint16_t RegisterAdress, uint16_t value)
{
	uint8_t status = 255;
	
	uint8_t towrite[2];
	towrite[0]=(uint8_t)(value>>8 & 0xFF);
	towrite[1]=(uint8_t)(value & 0xFF);
    status = HAL_I2C_Mem_Write(I2C, dev, RegisterAdress,2, (uint8_t*)towrite, 2, I2CTIMEOUT);
	checkI2CError(status);
	
	return status;
}

uint8_t VL53L4CD_WrDWord(Dev_t dev, uint16_t RegisterAdress, uint32_t value)
{
	uint8_t status = 255;

	uint8_t towrite[4];
	towrite[0]=(uint8_t)(value>>24 & 0xFF);
	towrite[1]=(uint8_t)(value>>16 & 0xFF);
	towrite[2]=(uint8_t)(value>>8 & 0xFF);
	towrite[3]=(uint8_t)(value & 0xFF); 
	status = HAL_I2C_Mem_Write(I2C, dev, RegisterAdress,2, (uint8_t*)towrite, 4, I2CTIMEOUT);
	checkI2CError(status);

	return status;
}

uint8_t WaitMs(Dev_t dev, uint32_t TimeMs)
{
	uint8_t status = 255;

	HAL_Delay(TimeMs);
	
	return status;
}

void checkI2CError(uint8_t status)
{
	if (status != HAL_OK) {
		printf("I2C error: ");
		I2C_HandleTypeDef *hi2c; // Assume hi2c is initialized and points to your I2C handle

		if (hi2c->ErrorCode & HAL_I2C_ERROR_BERR) {
			printf("Bus error\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_ARLO) {
			printf("Arbitration lost error\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_AF) {
			printf("Acknowledge failure\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_OVR) {
			printf("Overrun error\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_DMA) {
			printf("DMA transfer error\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_TIMEOUT) {
			printf("Timeout error\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_SIZE) {
			printf("Size mismatch\n");
		}
		if (hi2c->ErrorCode & HAL_I2C_ERROR_NONE) {
			printf("No error\n");
		}
	}
}