2025-04-08 8:29 AM
Hi all,
I'm trying to get the VL53L8CX ToF sensor working for a university project, this is my first time using it. I made a little breakout PCB for it and soldered it, measured resistance between al neighbouring pins, none of them were shorts or open circuits which to me confirms that the sensor was soldered correctly. The breakout PCB includes 1.8V <-> 3.3V level shifting, here's the full circuit diagram:
I've connected it to an ESP32, but it seems like I can't communicate with the sensor over SPI. As I understand, the sensor should be mirroring the given register adres from the MOSI pin to the MISO pin, but there's no activity on MISO, the signal just seems to follow the CS signal. Here's what the waveforms look like, measured at the sensor (1.8V) side of the level shifters:
Zoomed in:
Here's the code:
#include <Arduino.h>
#include <SPI.h>
#include "vl53l8cx_api.h"
#include "platform.h"
VL53L8CX_Configuration Dev;
void setup()
{
pinMode(SS, OUTPUT);
SPI.begin();
SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE3));
Serial.begin(115200);
}
void loop()
{
uint8_t status, isAlive;
status = vl53l8cx_is_alive(&Dev, &isAlive);
if (!isAlive || status)
{
Serial.println("VL53L8CX not detected at requested address");
}
delay(1);
}
I'm unsure about my implementation of the functions in the sensor's driver platform.c file, but at the very least I should be seeing some activity on the MISO line right?
Any efforts to help me debug this would be greatly appreciated, I've been stuck here for a few days.
2025-04-08 8:53 AM
You scope has a USB socket to get screenshots - this will give far clearer results than photographing the screen!
2025-04-08 9:26 AM
I'm going to make a guess here.
in ST's API, there is a platform.c - and it's basically empty.
We ship a completed on in our example directory, but the one in the main bit of code is empty.
it's your job to fill that out for the MCU you are using.
ST has it own STM32 processors we think you should use - and we aren't about to ship ESP32 code.
But it should be an easy matter to go to github.com and find some ESP32 SPI basic functions.
Use that to fill out the functions in platform.c
Then I think it's going to work better.
As a software guy i might suggest print out your status after your is_alive() call. I'm pretty sure it's going to tell you that the IO failed.
- john
2025-04-08 11:08 AM
Hi John, thanks for the quick reply.
This is how the read and write byte functions are implemented so far:
#include "platform.h"
#include <SPI.h>
#include <Arduino.h>
uint8_t VL53L8CX_RdByte(
VL53L8CX_Platform *p_platform,
uint16_t RegisterAdress,
uint8_t *p_value)
{
uint8_t status = 0;
digitalWrite(SS, LOW);
SPI.write16(RegisterAdress & 0x7FFF); // Set MSB to 0 (read)
*p_value = SPI.transfer(0x00); // Write dummy byte to read data
digitalWrite(SS, HIGH);
return status;
}
uint8_t VL53L8CX_WrByte(
VL53L8CX_Platform *p_platform,
uint16_t RegisterAdress,
uint8_t value)
{
uint8_t status = 0;
digitalWrite(SS, LOW);
SPI.write16(RegisterAdress | (1 << 15)); // Set MSB to 1 (write)
SPI.write(value); // Write data
digitalWrite(SS, HIGH);
return status;
}
Looking at the waveforms, it's clear data is being sent to the sensor but it's not replying anything. Do you think this is expected behaviour due to an error in the software, or might it be a hardware issue?
2025-04-08 11:09 AM
I actually looked for a usb drive for this but didn't have one with me at the time of posting so I did my best to take some clear pictures without glare:)
2025-04-08 12:24 PM
I don't know anything about how your MCU writes to the SPI bus.
The best I can do is to include the platform.c used on the STM32.
Perhaps that will help.
Here we wrote the two functions WrMulti() and RdMulti(). Notice the RdByte and WrByte are just calls to the multi function with length 1.
What I notice is that there is a device structure that is absent in your code. (might not be a problem. I've no clue.)
status |= HAL_SPI_Transmit(&hspi1, data_write, data_size, 100*data_size);
In our code all the info about the SPI device is contained in that structure.
typedef struct __SPI_HandleTypeDef
{
SPI_TypeDef *Instance; /*!< SPI registers base address */
SPI_InitTypeDef Init; /*!< SPI communication parameters */
uint8_t *pTxBuffPtr; /*!< Pointer to SPI Tx transfer Buffer */
uint16_t TxXferSize; /*!< SPI Tx Transfer size */
__IO uint16_t TxXferCount; /*!< SPI Tx Transfer Counter */
uint8_t *pRxBuffPtr; /*!< Pointer to SPI Rx transfer Buffer */
uint16_t RxXferSize; /*!< SPI Rx Transfer size */
__IO uint16_t RxXferCount; /*!< SPI Rx Transfer Counter */
void (*RxISR)(struct __SPI_HandleTypeDef *hspi); /*!< function pointer on Rx ISR */
void (*TxISR)(struct __SPI_HandleTypeDef *hspi); /*!< function pointer on Tx ISR */
DMA_HandleTypeDef *hdmatx; /*!< SPI Tx DMA Handle parameters */
DMA_HandleTypeDef *hdmarx; /*!< SPI Rx DMA Handle parameters */
HAL_LockTypeDef Lock; /*!< Locking object */
__IO HAL_SPI_StateTypeDef State; /*!< SPI communication state */
__IO uint32_t ErrorCode; /*!< SPI Error code */
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
void (* TxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Tx Completed callback */
void (* RxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Rx Completed callback */
void (* TxRxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI TxRx Completed callback */
void (* TxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Tx Half Completed callback */
void (* RxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Rx Half Completed callback */
void (* TxRxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI TxRx Half Completed callback */
void (* ErrorCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Error callback */
void (* AbortCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Abort callback */
void (* MspInitCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Msp Init callback */
void (* MspDeInitCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Msp DeInit callback */
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
} SPI_HandleTypeDef;
i just don't see the equivalent in your code.
Given that the first function just reads one byte and that doesn't work, it's got to be here somewhere.
- john