2024-09-13 11:20 PM
I need to work with three tof sensors (VL53L0X) at once. First i checked one sensor and it worked well. the code is below.
#include "main.h"
#include "vl53l0x_api.h"
// Define the I2C handle
I2C_HandleTypeDef hi2c1;
// Define GPIO pins for XSHUT control
#define XSHUT_PIN GPIO_PIN_0
#define XSHUT_PORT GPIOA
// Define GPIO1 pin
#define GPIO1_PIN GPIO_PIN_3
#define GPIO1_PORT GPIOB
// Define new I2C address for the sensor
#define SENSOR_NEW_ADDR 0x30
// Global variable to store distance measurement
uint16_t sensor_distance = 0;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
void VL53L0X_Init_Sensor(VL53L0X_Dev_t *sensor, uint8_t new_address);
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
// Define sensor device
VL53L0X_Dev_t sensor;
// Initialize sensor
VL53L0X_Init_Sensor(&sensor, SENSOR_NEW_ADDR);
while (1) {
VL53L0X_RangingMeasurementData_t RangingData;
// Read distance from sensor
VL53L0X_PerformSingleRangingMeasurement(&sensor, &RangingData);
sensor_distance = RangingData.RangeMilliMeter;
HAL_Delay(50);
}
}
void VL53L0X_Init_Sensor(VL53L0X_Dev_t *sensor, uint8_t new_address) {
sensor->I2cHandle = &hi2c1;
sensor->I2cDevAddr = 0x52; // Default I2C address
// Initialize the sensor
VL53L0X_DataInit(sensor);
VL53L0X_StaticInit(sensor);
// Change the I2C address
VL53L0X_SetDeviceAddress(sensor, new_address);
sensor->I2cDevAddr = new_address;
// Declare necessary variables for calibration and SPAD management
uint8_t VhvSettings = 0;
uint8_t PhaseCal = 0;
uint32_t refSpadCount = 0;
uint8_t isApertureSpads = 0;
// Perform sensor calibration and initialization
VL53L0X_PerformRefCalibration(sensor, &VhvSettings, &PhaseCal);
VL53L0X_PerformRefSpadManagement(sensor, &refSpadCount, &isApertureSpads);
VL53L0X_SetDeviceMode(sensor, VL53L0X_DEVICEMODE_SINGLE_RANGING);
}
void SystemClock_Config(void) {
// System clock configuration code
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
Error_Handler();
}
}
static void MX_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
// GPIO Ports Clock Enable
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// Configure GPIO pin for XSHUT control
GPIO_InitStruct.Pin = XSHUT_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(XSHUT_PORT, &GPIO_InitStruct);
// Set XSHUT pin to high to enable sensor
HAL_GPIO_WritePin(XSHUT_PORT, XSHUT_PIN, GPIO_PIN_SET);
// Configure GPIO pin for GPIO1
GPIO_InitStruct.Pin = GPIO1_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIO1_PORT, &GPIO_InitStruct);
// Delay to ensure sensor is powered up
HAL_Delay(100);
}
static void MX_I2C1_Init(void) {
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 400000;
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) {
// Initialization Error
Error_Handler();
}
// Configure I2C SCL and SDA pins
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void Error_Handler(void) {
// Error handling code
while (1) {
// Stay here
}
}
// GPIO Ports Clock Enable
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// Configure GPIO pins for XSHUT control
GPIO_InitStruct.Pin = XSHUT1_PIN | XSHUT2_PIN | XSHUT3_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Set XSHUT pins to low to disable sensors initially
HAL_GPIO_WritePin(XSHUT1_PORT, XSHUT1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(XSHUT2_PORT, XSHUT2_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(XSHUT3_PORT, XSHUT3_PIN, GPIO_PIN_RESET);
// Configure GPIO1 pins
GPIO_InitStruct.Pin = GPIO1_1_PIN | GPIO1_2_PIN | GPIO1_3_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// Delay to ensure sensors are powered up
HAL_Delay(100);
Then I tried to work with all the three sensors at once in the stm32 cubeide. The code compiles and debugs without any error but the issue is that there isn't any feedback from any of the sensors. The code used is,
#include "main.h"
#include "vl53l0x_api.h"
// Define the I2C handle
I2C_HandleTypeDef hi2c1;
// Define GPIO pins for XSHUT control
#define XSHUT1_PIN GPIO_PIN_0
#define XSHUT1_PORT GPIOA
#define XSHUT2_PIN GPIO_PIN_1
#define XSHUT2_PORT GPIOA
#define XSHUT3_PIN GPIO_PIN_2
#define XSHUT3_PORT GPIOA
// Define GPIO1 pins
#define GPIO1_1_PIN GPIO_PIN_3
#define GPIO1_1_PORT GPIOB
#define GPIO1_2_PIN GPIO_PIN_4
#define GPIO1_2_PORT GPIOB
#define GPIO1_3_PIN GPIO_PIN_5
#define GPIO1_3_PORT GPIOB
// Define new I2C addresses for the sensors
#define LOX1_ADDRESS 0x30
#define LOX2_ADDRESS 0x31
#define LOX3_ADDRESS 0x32
// Global variables to store distance measurements
uint16_t sensor1_distance = 0;
uint16_t sensor2_distance = 0;
uint16_t sensor3_distance = 0;
// Declare sensor devices
VL53L0X_Dev_t sensor1;
VL53L0X_Dev_t sensor2;
VL53L0X_Dev_t sensor3;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
void VL53L0X_Init_Sensor(VL53L0X_Dev_t *sensor, uint8_t new_address);
void read_three_sensors(void);
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
// Initialize sensors one by one
HAL_GPIO_WritePin(XSHUT1_PORT, XSHUT1_PIN, GPIO_PIN_SET);
HAL_Delay(100);
VL53L0X_Init_Sensor(&sensor1, LOX1_ADDRESS);
HAL_GPIO_WritePin(XSHUT2_PORT, XSHUT2_PIN, GPIO_PIN_SET);
HAL_Delay(100);
VL53L0X_Init_Sensor(&sensor2, LOX2_ADDRESS);
HAL_GPIO_WritePin(XSHUT3_PORT, XSHUT3_PIN, GPIO_PIN_SET);
HAL_Delay(100);
VL53L0X_Init_Sensor(&sensor3, LOX3_ADDRESS);
while (1) {
read_three_sensors();
HAL_Delay(100);
}
}
void VL53L0X_Init_Sensor(VL53L0X_Dev_t *sensor, uint8_t new_address) {
sensor->I2cHandle = &hi2c1;
sensor->I2cDevAddr = 0x52; // Default I2C address
// Initialize the sensor
VL53L0X_DataInit(sensor);
VL53L0X_StaticInit(sensor);
// Change the I2C address
VL53L0X_SetDeviceAddress(sensor, new_address);
sensor->I2cDevAddr = new_address;
// Declare necessary variables for calibration and SPAD management
uint8_t VhvSettings = 0;
uint8_t PhaseCal = 0;
uint32_t refSpadCount = 0;
uint8_t isApertureSpads = 0;
// Perform sensor calibration and initialization
VL53L0X_PerformRefCalibration(sensor, &VhvSettings, &PhaseCal);
VL53L0X_PerformRefSpadManagement(sensor, &refSpadCount, &isApertureSpads);
VL53L0X_SetDeviceMode(sensor, VL53L0X_DEVICEMODE_SINGLE_RANGING);
}
void read_three_sensors(void) {
VL53L0X_RangingMeasurementData_t RangingData;
// Read distance from sensor 1
VL53L0X_PerformSingleRangingMeasurement(&sensor1, &RangingData);
sensor1_distance = RangingData.RangeMilliMeter;
// Read distance from sensor 2
VL53L0X_PerformSingleRangingMeasurement(&sensor2, &RangingData);
sensor2_distance = RangingData.RangeMilliMeter;
// Read distance from sensor 3
VL53L0X_PerformSingleRangingMeasurement(&sensor3, &RangingData);
sensor3_distance = RangingData.RangeMilliMeter;
}
void SystemClock_Config(void) {
// System clock configuration code
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
Error_Handler();
}
}
static void MX_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
// GPIO Ports Clock Enable
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// Configure GPIO pins for XSHUT control
GPIO_InitStruct.Pin = XSHUT1_PIN | XSHUT2_PIN | XSHUT3_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Set XSHUT pins to low to disable sensors initially
HAL_GPIO_WritePin(XSHUT1_PORT, XSHUT1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(XSHUT2_PORT, XSHUT2_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(XSHUT3_PORT, XSHUT3_PIN, GPIO_PIN_RESET);
// Configure GPIO1 pins
GPIO_InitStruct.Pin = GPIO1_1_PIN | GPIO1_2_PIN | GPIO1_3_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// Delay to ensure sensors are powered up
HAL_Delay(100);
}
static void MX_I2C1_Init(void) {
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 400000;
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) {
// Initialization Error
Error_Handler();
}
// Configure I2C SCL and SDA pins
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void Error_Handler(void) {
// Error handling code
while (1) {
// Stay here
}
}
Then I checked all three sensors on the arduino ide and it worked well. So I guess something is wrong in the above code and my guess is it should be with the Xshut pins. I will be very pleased if someone can sort out the matter.
2024-09-16 08:18 AM
Oh, so close.
The trick is you have to put all 3 sensors into Shutdown (Xshut=0).
The bring the first out of reset, issue an 'address change' command and then initialize it.
Now that that chip is not on address 0x29 base address, (0x52/0x53 write address/read address) you can bright the next chip out of reset and repeat the process for each chip.
then when in use, you will have 3 sensors - each with its own I2C address.
- john