cancel
Showing results for 
Search instead for 
Did you mean: 

Struggling to successfully operate the satel vl53l8a with the NRF5340

antshiv
Associate II

I am attempting to connect the satel-vl53l8a to the Nordic Semiconductor nRF5340 using the I2C protocol, but I am not receiving any acknowledgment (ACK). I have followed the wiring diagrams provided in this document: AN5945. Additionally, I have captured the output of my logic analyzer for reference.

Startup sequence and signal sent to VL53L8AStartup sequence and signal sent to VL53L8Athe i2c address is always NAKthe i2c address is always NAK

1 ACCEPTED SOLUTION

Accepted Solutions
John E KVAM
ST Employee

Something is clearly wrong - You cannot get large negative distances. And the status byte is always between 0 and 20 (plus 255).

Step one - meticulously check all the status returns on every call.

But all the problems I've seen with this chip are I2C problems. 

There are two types: 1 is a byte-swap or word-swap. Your data is transmitted, so it looks right, but the sensor gets the wrong meaning. 

The other issue is the long WrMulti. Some MCUs cannot handle those long writes at initialization. 

As you are getting a result - even a bad one, it looks like you are past the long write issue. 

So I'm going to guess you have a word swap issue.  

Take that bit of code above and try this. 

Use 4 WrByte calls to write 4 consecutive bytes starting at location 100. Then read it back with 2 WrWord() calls, and 1 WrDWord. You should get the data you wrote - in the correct order. 

And if you wanted to be complete you, could do a 4-byte WrMulti, and read it back 3 other ways. 

-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'

View solution in original post

8 REPLIES 8
John E KVAM
ST Employee

The sensor is pretty complicated, but the I2C is not. It needs power, ground, and an I2C. And you need to lift the LPn pin. I'm betting it the LPn pin. Essentially, this pin enables the I2C. That app note tells you to connect the pin, but does not provide much in the way of protocol.  It assumes you are using the ST provided software. 

When you get the ACK, try this bit of code:

/* --------------------------------------------------
 * --- This function can be used to test VL53L5CX I2C 
 * --------------------------------------------------
 */

uint8_t vl53l5cx_test_i2c(VL53L5CX_Configuration *p_dev){
	uint8_t status = VL53L5CX_STATUS_OK;
	printf("Starting VL53L5CX I2C test...\n");

/* To check the I2C RdByte/WrByte function :
 * Inside the function “vl53l5cx_is_alive()”, it will call I2C RdByte/WrByte to
 * read device and verion ID. which can help you to verify the I2C RdByte/WrByte
 * functions at same time.
 */
	uint8_t device_id, revision_id;
	status |= WrByte(&(p_dev->platform), 0x7fff, 0x00);
	status |= RdByte(&(p_dev->platform), 0, &device_id);
	status |= RdByte(&(p_dev->platform), 1, &revision_id);
	status |= WrByte(&(p_dev->platform), 0x7fff, 0x02);

	if(status)
	{
		printf("Error Rd/Wr byte: status %u\n", status);
		return status;
	}

/* To check the I2C RdMulti/WrMulti function:
 * Below is example codes which can help you vefify the I2C RdMulti/WrMulti
 * function.
 */

	uint8_t Data_write[4]={0x5A,0xA5,0xAA,0x55};
	uint8_t Data_read[4]={0,0,0,0};
	uint8_t Data_default[4]={0,0,0,0};

	status |= RdMulti(&(p_dev->platform), 0x100, Data_default, 4);
	if(status)
	{
		printf("Error RdMulti: status %u\n", status);
		return status;
	}

	printf("Read default value and save it at begging\n");
	printf("Data_default (0x%x)\n", Data_default[0]);
	printf("Data_default (0x%x)\n", Data_default[1]);
	printf("Data_default (0x%x)\n", Data_default[2]);
	printf("Data_default (0x%x)\n", Data_default[3]);

	status |= WrMulti(&(Dev.platform), 0x100, Data_write, 4);
	if(status)
	{
		printf("Error WrMulti: status %u\n", status);
		return status;
	}
	printf("Writing values 0x5A 0xA5 0xAA 0x55\n");

	status |= RdMulti(&(p_dev->platform), 0x100, Data_read, 4);
	if(status)
	{
		printf("Error RdMulti: status %u\n", status);
		return status;
	}

	printf("Reading:\n");
	printf("Data_read (0x%x)\n", Data_read[0]);
	printf("Data_read (0x%x)\n", Data_read[1]);
	printf("Data_read (0x%x)\n", Data_read[2]);
	printf("Data_read (0x%x)\n", Data_read[3]);


	status |= WrMulti(&(Dev.platform), 0x100, Data_default, 4);
	printf("Write back default value\n");
	if(status)
	{
		printf("Error WrMulti: status %u\n", status);
		return status;
	}

	status |= RdMulti(&(Dev.platform), 0x100, Data_default, 4);
	if(status)
	{
		printf("Error RdMulti: status %u\n", status);
		return status;
	}

	printf("Read value again to make sure default value was correct loaded\n");
	printf("Data_default (0x%x)\n", Data_default[0]);
	printf("Data_default (0x%x)\n", Data_default[1]);
	printf("Data_default (0x%x)\n", Data_default[2]);
	printf("Data_default (0x%x)\n", Data_default[3]);

	printf("I2C test done - everything works fine.\n");

	return status;
}

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'

Thank you very much for responding promptly. I've produced a video to illustrate my problem: YouTube link.

Essentially, I've ensured that all the pins are correctly configured, yet I'm still unable to receive an ACK from the sensor. I'm uncertain about what mistake I might be making.

 
antshiv
Associate II

Ok, so I got the i2c working. I was interpreting the 8-bit address as a 7-bit address. Hence the confusion. And now i am facing another issue. It is with the code provided where it says to mandatory update the firmware by calling the int function. When that function is called it fails. Do we need to update the firmware or use that function?

I am currently testing your above code to see if the Read/Write i2c functions work. Thank you.

 

John E KVAM
ST Employee

there are a few common issues with I2C. 

1) the STM32 can do a very long I2C write. Most other MCUs cannot. So I'm guessing the init fails because your MCU writes smaller chunks. Some max out at 255 bytes, others at 127 or 128. 

re-write the Init with a 'chunk' size.

There is another thread on this topic.

Re: VL53L5CX driver vl53l5cx_init() fails - Page 5 - STMicroelectronics Community

Next issue is byte swap. Or word swap. Thing wont work out until you figure out if your machines endian matches with the STM32. 

That other thread has come code that can help.

- 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'
antshiv
Associate II

Dear John,

I appreciate your prompt response. I have once again created a video illustrating my ongoing struggle https://youtube.com/live/NKhth-AvypM. There are a few points I am certain about:

  1. The I2C code you provided functions effectively.
  2. Nordic indeed supports transmitting more than 255 bytes of data. I can write nearly 32768 bytes or so in one go when downloading the firmware.

I have two inquiries:

  1. I am utilizing the VL53LMZ API. Is this the correct API to employ? Based on your code, it appears you are using the VL53L5CX API. Is there a distinction between the two?
  2. Concerning writing the firmware code - the VL53mz_buffers.h file contains a substantial firmware code. Is it mandatory to write the firmware to the sensor every time it starts up?

Thank you for your ongoing assistance.

antshiv
Associate II

Hello John,

I've managed to get the VL53L8CX ULD ready (Version: VL53L8CX_1.2.1) operational, at least it progresses beyond the initialization phase. I'm currently attempting to execute Example 1 - Ranging basis. However, the output appears to not make too much sense.

During the 1st iteration: VL53L8CX ULD ready (Version: VL53L8CX_1.2.1)

Status is : 0
Print data no : 0
Zone : 0, Status : 41, Distance : -3369 mm
Zone : 1, Status : 187, Distance : 4839 mm
Zone : 2, Status : 218, Distance : -4285 mm
Zone : 3, Status : 30, Distance : 2845 mm
Zone : 4, Status : 181, Distance : 1439 mm
Zone : 5, Status : 10, Distance : -1048 mm
Zone : 6, Status : 226, Distance : -7736 mm
Zone : 7, Status : 11, Distance : 6499 mm
Zone : 8, Status : 119, Distance : 5283 mm
Zone : 9, Status : 187, Distance : -2201 mm
Zone : 10, Status : 160, Distance : 1291 mm
Zone : 11, Status : 12, Distance : 5704 mm
Zone : 12, Status : 184, Distance : -4217 mm
Zone : 13, Status : 170, Distance : -6485 mm
Zone : 14, Status : 1, Distance : 5729 mm
Zone : 15, Status : 214, Distance : 3365 mm

By the 10th iteration, all values are zero:

Status is : 0
Print data no : 9
Zone : 0, Status : 41, Distance : 0 mm
Zone : 1, Status : 187, Distance : 0 mm
Zone : 2, Status : 218, Distance : 0 mm
Zone : 3, Status : 30, Distance : 0 mm
Zone : 4, Status : 181, Distance : 0 mm
Zone : 5, Status : 10, Distance : 0 mm
Zone : 6, Status : 226, Distance : 0 mm
Zone : 7, Status : 11, Distance : 0 mm
Zone : 8, Status : 119, Distance : 0 mm
Zone : 9, Status : 187, Distance : 0 mm
Zone : 10, Status : 160, Distance : 0 mm
Zone : 11, Status : 12, Distance : 0 mm
Zone : 12, Status : 184, Distance : 0 mm
Zone : 13, Status : 170, Distance : 0 mm
Zone : 14, Status : 1, Distance : 0 mm
Zone : 15, Status : 214, Distance : 0 mm

I'm perplexed by this output. Could you assist me in deciphering its meaning? Additionally, do you know if there's a datasheet available for this sensor that provides explanations for each of the register values and their functions?

antshiv
Associate II

Hello John,

I hope you're well. I'm reaching out regarding the issues I've outlined above, and I'm hoping you might be able to assist me. I've been facing this challenge for some time now. While the firmware successfully updates, it encounters difficulties retrieving ranging information. Specifically, the code anticipates receiving 532 bytes from the sensor, but my logic analyzer indicates that only 21 bytes are being sent. How should I proceed to troubleshoot this problem and make progress? Any insights you can provide would be greatly appreciated.

John E KVAM
ST Employee

Something is clearly wrong - You cannot get large negative distances. And the status byte is always between 0 and 20 (plus 255).

Step one - meticulously check all the status returns on every call.

But all the problems I've seen with this chip are I2C problems. 

There are two types: 1 is a byte-swap or word-swap. Your data is transmitted, so it looks right, but the sensor gets the wrong meaning. 

The other issue is the long WrMulti. Some MCUs cannot handle those long writes at initialization. 

As you are getting a result - even a bad one, it looks like you are past the long write issue. 

So I'm going to guess you have a word swap issue.  

Take that bit of code above and try this. 

Use 4 WrByte calls to write 4 consecutive bytes starting at location 100. Then read it back with 2 WrWord() calls, and 1 WrDWord. You should get the data you wrote - in the correct order. 

And if you wanted to be complete you, could do a 4-byte WrMulti, and read it back 3 other ways. 

-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'