2021-02-04 08:36 AM
Hey! Sorry for my english.
I am facing a problem. when trying to read 2 VL53L1XV2 sensors, the program execution stops in a loop. in this loop I am using:
VL53L1X_BootState(dev, &Bootstate);
... and exit it when Bootstate is 0x03 ...
I use the HAL_Delay (100) delay to blink LD2 on the NUCLEO-F401RE. Without delay, the program behaves the same.
When I debug the program, I see that when I try to get Model_ID, Module_Type, I get 0.
Most likely the problem is in initiating the sensors. I tried many similar codes and also took the Pololu library
in which similar actions occur. but I keep getting it.
I am using a NUCLEO-F401RE board, a VL53L1X_ULD driver from ST, and two VL53L1XV2 sensors.
I would be grateful for any help in solving my question.
the code I wrote:
#include "stm32xxx_hal.h"
#include "main.h"
#include "VL53L1X_API.h"
#include "VL53l1X_calibration.h"
#include "X-NUCLEO-53L1A1.h"
I2C_HandleTypeDef hi2c1;
UART_HandleTypeDef huart2;
uint16_t dev = 0x52;
int status = 0;
volatile int IntCount;
#define isInterrupt 1
int SystemClock_Config(void);
static void MX_GPIO_Init(void);
static int MX_USART2_UART_Init(void);
static int MX_I2C1_Init(void);
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define VL53L1_DISTANCEMODE_SHORT 1
#define VL53L1_DISTANCEMODE_LONG 2
#define SET_ZERO_POSITION "\033[0;0H"
#define CLEAR_WINDOW "\033[2J"
#define CLEAR_LINE "\r\033[K"
uint8_t clear_window[] = CLEAR_WINDOW;
uint8_t str[] = "\r\n\0";
uint8_t set_zero_position[] = SET_ZERO_POSITION;
uint8_t clear_line[] = CLEAR_LINE;
uint8_t str1[] = "test\r\n\0";
#define NumOfTOFSensors 2
#define ROWS_OF_SPADS 4
#define DISTANCES_ARRAY_SIZE ROWS_OF_SPADS
#define ROWS 8
#define COLS 8
#define TIMING_BUDGET 33
#define DISTANCE_MODE VL53L1_DISTANCEMODE_LONG // VL53L1_DISTANCEMODE_SHORT // VL53L1_DISTANCEMODE_LONG
uint16_t dictanse_array[DISTANCES_ARRAY_SIZE];
#define ZONE_CENTER_1 227
#define ZONE_CENTER_2 92
#define ZONE_CENTER_3 28
#define ZONE_CENTER_4 163
uint16_t Devs[NumOfTOFSensors] = {0x62, 0x64/*, 0x66, 0x68, 0x6A, 0x6C, 0x6E, 0x70, 0x72*/};
PUTCHAR_PROTOTYPE {
HAL_UART_Transmit(&huart2, (uint8_t*)&ch, 1, 0xFFFF);
return ch;
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == VL53L1X_INT_Pin) {
IntCount++;
}
}
void dump_depths_2x2() {
HAL_UART_Transmit(&huart2, set_zero_position, sizeof(set_zero_position), 30);
HAL_UART_Transmit(&huart2, clear_line, sizeof(clear_line), 30);
printf("%d", dictanse_array[0]);
for(uint8_t idx = 1; idx < DISTANCES_ARRAY_SIZE; idx++) {
if (idx == 2 || idx == 4) {
printf("\n");
HAL_UART_Transmit(&huart2, clear_line, sizeof(clear_line), 30);
} else printf("\t");
printf("%d", dictanse_array[idx]);
}
}
void TurnOnSensor(uint8_t SensorNum) {
printf("GPIO Sensor_%d:", SensorNum + 1);
switch (SensorNum) {
case 0:
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET); // GPIO PC2
printf("Active\r\n");
break;
case 1:
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET); // GPIO PC3
printf("Active\r\n");
break;
default:
printf("Error: Number sensor is invalid!");
break;
}
}
void ResetAllSensors(void) {
printf("ResetAllSensors...");
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET); // Sensor_1
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_RESET); // Sensor_2
printf("Done\r\n");
}
void ResetAndInitializeAllSensors(void) {
uint8_t i, Sensor, error = 0;
uint8_t Bootstate = 0;
uint8_t byteData = 0;
uint16_t wordData;
printf("ResetAndInitializeAllSensors...\r\n");
ResetAllSensors();
HAL_Delay(10);
for (i = 0; i < NumOfTOFSensors; i++) {
TurnOnSensor(i);
HAL_Delay(20);
printf("Sensor_%d loading...\r\n", i + 1);
status = VL53L1_RdByte(dev, 0x010F, &byteData);
printf("VL53L1X Model_ID: %X\r\n", byteData);
status = VL53L1_RdByte(dev, 0x0110, &byteData);
printf("VL53L1X Module_Type: %X\r\n", byteData);
status = VL53L1_RdWord(dev, 0x010F, &wordData);
printf("VL53L1X: %X\r\n", wordData);
error += VL53L1X_BootState(dev, &Bootstate);
while (Bootstate != 0x03) {
HAL_Delay(100);
error += VL53L1X_BootState(dev, &Bootstate);
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
}
printf("Chip booted\r\n");
printf("reading!\r\n");
printf("[%d]\tSensor_%d SetI2CAddress: 0x%X\r\n", VL53L1X_SetI2CAddress(dev, Devs[i]), i + 1, Devs[i]);
printf("[%d]\tSensor_%d init: \r\n", VL53L1X_SensorInit(dev), i + 1);
}
for (Sensor = 0; Sensor < NumOfTOFSensors; Sensor++) {
VL53L1X_SetDistanceMode(Devs[Sensor], DISTANCE_MODE);
VL53L1X_SetTimingBudgetInMs(Devs[Sensor], TIMING_BUDGET);
VL53L1X_SetInterMeasurementInMs(Devs[Sensor], TIMING_BUDGET);
VL53L1X_SetROI(Devs[Sensor], ROWS, COLS);
VL53L1X_SetROICenter(Devs[Sensor], ZONE_CENTER_1);
}
for (Sensor = 0; Sensor < NumOfTOFSensors; Sensor++) {
VL53L1X_StartRanging(Devs[Sensor]);
HAL_Delay(1);
}
}
int main(void) {
VL53L1X_ERROR error = 0;
uint16_t Distance;
uint8_t RangeStatus;
uint8_t dataReady;
int center_2x2[4] = {ZONE_CENTER_1, ZONE_CENTER_2, ZONE_CENTER_3, ZONE_CENTER_4};
HAL_Init();
error = SystemClock_Config();
MX_GPIO_Init();
error += MX_USART2_UART_Init();
error += MX_I2C1_Init();
HAL_UART_Transmit(&huart2, clear_window, sizeof(clear_window), 30);
HAL_UART_Transmit(&huart2, set_zero_position, sizeof(set_zero_position), 30);
if (error != 0) {
printf("Could not initialize the nucleo board\n");
return -1;
}
ResetAndInitializeAllSensors();
/* Initialize and configure the device according to people counting need */
status = VL53L1X_SensorInit(dev);
status += VL53L1X_SetDistanceMode(dev, DISTANCE_MODE); /* 1=short, 2=long */
status += VL53L1X_SetTimingBudgetInMs(dev, TIMING_BUDGET); /* in ms possible values [15, 20, 50, 100, 200, 500] */
status += VL53L1X_SetInterMeasurementInMs(dev, TIMING_BUDGET);
status += VL53L1X_SetROI(dev, ROWS, COLS);
if (status != 0) {
printf("Initialization or configuration of the device\n");
return (-1);
}
status = VL53L1X_StartRanging(dev); /* This function has to be called to enable the ranging */
while (1) {
error = 0;
for(uint8_t Zone = 0; Zone < ROWS_OF_SPADS; Zone++) {
for (uint8_t Sensor=0; Sensor < NumOfTOFSensors ; Sensor++)
VL53L1X_SetROICenter(Devs[Sensor], center_2x2[Zone]);
for (uint8_t Sensor = 0; Sensor < NumOfTOFSensors ; Sensor++) {
while (dataReady == 0) {
status = VL53L1X_CheckForDataReady(Devs[Sensor], &dataReady);
HAL_Delay(1);
}
dataReady = 0;
status += VL53L1X_GetRangeStatus(Devs[Sensor], &RangeStatus);
status += VL53L1X_GetDistance(Devs[Sensor], &Distance);
status += VL53L1X_ClearInterrupt(Devs[Sensor]);
if (status != 0) {
printf("Error in operating the device\n");
return (-1);
}
dictanse_array[Zone] = (RangeStatus != 0 && RangeStatus != 4 && RangeStatus != 7) ? 0 : Distance;
}
}
}
}
int SystemClock_Config(void) {
...
}
/* I2C1 init function */
static int MX_I2C1_Init(void) {
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
return -1;
return 0;
}
/* USART2 init function */
int MX_USART2_UART_Init(void) {
...
}
static void MX_GPIO_Init(void) {
...
// Sensor_1
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
// Sensor_2
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
full code i attached below.
Thank you!
Volodymyr.
where the ellipsis is the code that does not matter. for correct display I use ESC-sequences.
2021-12-21 11:25 AM
An absolutely classic I2C issue. All the VL53 addresses boot at 7-bit address 0x29 (Same as 8-bit address 0x52).
So the solution is to start up with all your sensors in reset (use the XSHUT line).
Bring the first one out, and issue the I2CAddressChange command (it's in the API somewhere.)
Then bring the second sensor out of reset and repeat.
Do that for all your sensors - although technically you can leave the last sensor at the default address.
Try that - you will be happier.