Skip to main content
Visitor II
May 29, 2018
Question

Ported VL53L0X Pololu code to STM32 - Always times out, can't find error!

  • May 29, 2018
  • 14 replies
  • 5817 views
Posted on May 29, 2018 at 04:06

Hi all

In lieu of the VL53L0X API being so awkward to use, I've made an effort to port the Pololu version of the VL53L0X library to STM32-compatible C code, using HAL functions to manage I2C communication.

Using an STM32F072RB board, with fast mode I2C (400KHz) and the 'D3' pin as XSHUT1, the setup and operation of the sensor in main.c goes as follows (removed surrounding code for readability)

VL53L0X sensor1;
char msg[64];
main()
{
setup_VL53L0X(&sensor1);
HAL_GPIO_WritePin(XSHUT1_GPIO_Port, XSHUT1_Pin,false);
 HAL_Delay(100);
HAL_GPIO_WritePin(XSHUT1_GPIO_Port, XSHUT1_Pin,true);
 HAL_Delay(20);
if(!init(&sensor1,true))
 {
 snprintf(msg,sizeof(msg),'Failed to initialize\r\n');
 HAL_UART_Transmit(UART, (uint8_t*)msg, strlen(msg), 0xFFFF);
 }
 else
 {
 snprintf(msg,sizeof(msg),'Successfully initialized\r\n');
 HAL_UART_Transmit(UART, (uint8_t*)msg, strlen(msg), 0xFFFF);
 }
setTimeout(&sensor1,500);
 startContinuous(&sensor1,0);
while(1)
{
snprintf(msg,sizeof(msg),'Read value: %u\r\n');//,readRangeContinuousMillimeters(&sensor1));
 HAL_UART_Transmit(UART, (uint8_t*)msg, strlen(msg), 0xFFFF);
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Unfortunately the function readRangeContinuousMillimeters(...) always returns a timeout (65536), as if the sensor is never initialised to read continuously (but, as shown in the code, it definitely is). Furthermore, reading WHO_AM_I always returns 0xEE which is correct and proves that the I2C bus is working.

Every function in the VL53L0X library has been ported over appropriately, and I've scanned every line of code to try and find the source of the problem. However, zero luck as of yet.

I have attached both the Pololu and my own version of the VL53L0X library, plus a custom I2C library which makes use of HAL functions, and the full main.c of this project.

If anyone is able to play spot-the-difference in order to get this working I'd be eternally grateful, as I'm completely stumped. Not that it's much in return, but this code is free for anyone to use if they can get it working.

Cheers

#port #vl53l0x
    This topic has been closed for replies.

    14 replies

    Visitor II
    May 31, 2018
    Posted on May 31, 2018 at 18:51

    Hello there,

    I'd like to help you, but cannot compile the code you've given, because some I2C libraries seem to be missing. Are you using any custom libraries (I2CDev.h?), if so - could you provide it for me? I am using STM32F407VGTx Discovery Board, but the code should be portable without major issues.

    Visitor II
    June 4, 2018
    Posted on June 04, 2018 at 11:38

    Hi Primoz B

    Thanks for offering to help.

    Please see the updated attachment which now has the I2CDev library, as well as the main.c of my project.

    Cheers

    Explorer
    August 14, 2018

    Hi

    Did you find a problem in your code?

    Thank you.

    Visitor II
    November 15, 2018

    Your code is absolute working. I tested on STM32F4DISCOVERY.

    It is necessary to implement two functions readMulti () and writeMulti (),

    I inserted them into main.c

    SLAVE_ADDRESS= 0x29 Channel hi2c1

    Also in the main.c add lines after init (& sensor1, true)

     setVcselPulsePeriod (& sensor1, VcselPeriodPreRange, 18);

     setVcselPulsePeriod (& sensor1, VcselPeriodFinalRange, 14);

    Adding project archive to COOCOX I2C_PROBA.ZIP

    Good luck

    Visitor II
    February 10, 2019

    I appreciate that you migrated this program into one genetared by STM32CubeMX.

    Apparently, I have the same issue as other mates, after approximately 20 seconds I get 65536 from "readRangeContinuousMillimeters" function

    Visitor II
    February 10, 2019

    Finally, I understood the problem and I solved it

    Visitor II
    November 16, 2018

    Hi Sergii and Vitalij

    Yes I found the problem a while back - sorry for not updating the thread.

    The code itself does work. The problem was in my custom I2C functions.

    Writebyte worked correctly

    HOWEVER when writing more than one byte ( e.g. 16 bits) a brackets error made me typecast the data before bit shifting! Very stupid!

    Example:

    Wrong pseudocode:

    void Write16Bits(uint16_t data)
    {
    uint8_t temp[2];
    temp[0]=(uint8_t)data;
    temp[1]=(uint8_t)data >> 8;
    Write_I2C((uint8_t*)temp);
    }

    Correct pseudocode:

    void Write16Bits(uint16_t data)
    {
    uint8_t temp[2];
    temp[0]=(uint8_t)data;
    temp[1]=(uint8_t)(data >> 8);
    Write_I2C((uint8_t*)temp);
    }

    It took a logic analyser looking at every packet before I realised that my multiple-byte sending functions were sending the first byte only, followed by 0x00 for the remaining bytes.

    Visitor II
    November 17, 2018

    Yes, this is true

    Thank you.

    Visitor II
    February 8, 2019

    Hi @Adam Halliwell​ 

    I programmed the files attached by @ZVita​ .

    I displayed the results in a seven segment TM1637. I have uploaded the files that are exactly the same as what @ZVita​ has uploaded. My Project has been carried out by STM32F030F4. All Settings have adjusted. For instance, XSHUT Pin and other needed pins.

    I have only a problem. My code results in displaying the number "65536" after 20 seconds.

    I have correct results for 20 seconds and after that, I have "65536".

    This error is persistent. It remians. I have the same problem exactly the same as you.

    You solve the problem in the final comment in this page. But I did not understand it. Is it possible for you to solve my problem? I have attached my project. Please answer me because I have spent many days to solve it. A million thanks to you. @ZVita​ Can you help me? @Adam Halliwell​ Can you help me? How did you solve your problem?

    See my project. typcasting after >>8 or typcasting after many different codes?

    Visitor II
    February 11, 2019

    @AMaci.14​  I never had the 20-second problem, but it seems like it's common to the code provided by vitalij.zhurik. How did you solve it? @Mahdi Bayati​ has the same problem you did.

    Visitor II
    February 11, 2019

    Practically, after some tests I figured out that it wasn't a 20 seconds. If I wanted to measure a large distance, I had got that 65536. 

    However, in the library you can find "writeReg" function which writes an uint8_t value in the register. If this value is grater 255 (max uint8_t), the value will be segmented and in register will arive a wrong value. You can find in library other functions which resolve this problem, such as: writeReg16Bit, writeReg32Bit. A quicker solution (which I implemented) is to make a condition in "writeReg": 

    void writeReg(VL53L0X * lidar,uint8_t reg, uint8_t value)

    {

    if (value > 255)

    writeByte(I2C,lidar->address,reg,255);

    else

    writeByte(I2C,lidar->address,reg,value);

    lidar->last_status = 0;

    }

    In this case, I think you will not receive a correct value for large distance. I proposed myself to make more some tests to understand better

    Visitor II
    March 3, 2019

    Dear all

    I observed the same 20-second trouble with the library provided by vitalij.

    I decided to modify the library originally developed for the STM32duino.

    Please find attached a functional library. I tested it with a Nucleo-L476RG board and a VL53L0X sensor.

    XShut pin is connected to PC8 pin. I2C1 via PB8(SCL) and PB9(SDA) pins is used for communication.

    Enjoy

    JC

    Visitor II
    March 3, 2019

    Thank you for your support. I have a question about that XShut pin from VL53L0X. Could I develop without the VL53L0X reset through XShut? I tried without restarting the sensor, but I couldn't communicate with the sensor after the first build. I suppose the driver is implemented to wait some flag from the sensor after it is restarted.

    Visitor II
    March 3, 2019

    Dear Alexandru

    I try to help hobbies like me. I have also developed small tutorials for my students.

    https://community.st.com/s/group/0F90X000000AXupSAG/inp-phelma-grenoble

    The initialization of the VL53L0X takes place in the function VL53L0X_InitSensor. It starts with a shutdown followed by a 100ms delay and then a restart and a 100ms delay using the XSHUT pin. The presence of the sensor is then detected. In case of a problem, the function returns -1.

    I think that this hardware initialization phase is mandatory for the sensor to be in a stable state.

    Bye

    Visitor II
    August 26, 2019

    Bonjour Jean-Christophe,

    Je travaille sur STM32L476 Nucleo avec µphone PDM/DFSDM et également sur STM32F469 Discovery, carte sur laquelle se souhaite implémenter ton super projet.

    Je suis un (vieux) copain d'Erwan Le-Saint, je travaille à l'INRS.

    Bien cordialement.

    Visitor II
    August 26, 2019

    Bonjour Dominique

    Tiens-moi au courant.

    Bien cordialement

    JC

    Visitor II
    August 26, 2019

    Bonjour Jean-Christophe,

    Réponse rapide pour un prof qui doit être encore en vacances...

    Je souhaite utiliser la carte "Flow breakout" de SeeedStudio avec son VL53L0X mais également son PWM3901 (optical flow motion).

    Je n'ai pas trouvé de projet porté sur STM32 (HAL) à partir de sa bibliothèque Arduino,

    Peut-être connais tu quelqu'un qui l'a réalisé et pas encore publié ... :>)

    Bonne reprise scolaire

    Dominique

    Visitor II
    April 9, 2020

    Bonjour Jean-Christophe,

    J'espère que tu vas bien ainsi que tes proches dans cette période difficile.

    Hier, je t'ai envoyé un mail sur ta messagerie NEEL, je suppose que ton temps est précieux et que tu dois gérer beaucoup d'urgences.

    J'ai terminé l'implémentation du PWM3901 (optical flow motion) platine "flowBreakout" sur STM32F469 Discovery, j'ai été agréablement surpris par ses performances (linéarité et vitesse maxi de tracking).

    Cela fait 1 semaine que je travaille sur ton code VL53L0X , j'ai résolu un problème d'adressage I2C, pour mon F469, il ne faut pas réalisé le décalage d'un bit vers la gauche dans VL53L0X_I2CRead(). Après correction, la fonction "VL53L0X_Start()" s'exécute normalement.

    J'ai un autre bug que je ne parviens pas à résoudre : l'exécution de "VL53L0X_GetDistance()" génère un timeout après 4 s dans VL53L0X_measurement_poll_for_completion() après les 2000 tentatives de 2ms infructueuses.

    Configuration de mon GPIO : XSHUT sur PG10, GPIO1 non connecté car le pcb de ma platine "flowBreakout" n'est pas routée.

    Merci pour ton aide.