2024-06-24
04:57 AM
- last edited on
2024-06-26
08:47 AM
by
Lina_DABASINSKA
Hardware Setup:
Problem Description: I am currently facing an issue where the VL53L0X sensors fail to provide correct distance measurements when the DC motors are running.
Here are the specific observations:
Troubleshooting Steps Taken:
The following is the main.c
void forward()
{
HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, EN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, IN4_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, EN2_Pin, GPIO_PIN_SET);
}
void backward()
{
HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, EN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, IN4_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, EN2_Pin, GPIO_PIN_SET);
}
void right()
{
HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, EN1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, IN4_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, EN2_Pin, GPIO_PIN_SET);
}
void left()
{
HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, EN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, IN4_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, EN2_Pin, GPIO_PIN_RESET);
}
void ruturn()
{
HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, EN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, IN4_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, EN2_Pin, GPIO_PIN_SET);
}
void luturn()
{
HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, EN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, IN4_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, EN2_Pin, GPIO_PIN_SET);
}
void rightback()
{
HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, EN1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, IN4_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, EN2_Pin, GPIO_PIN_SET);
}
void leftback()
{
HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, EN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, IN4_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, EN2_Pin, GPIO_PIN_RESET);
}
void stop()
{
HAL_GPIO_WritePin(GPIOA, EN1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, EN2_Pin, GPIO_PIN_RESET);
//GPIOA -> ODR &= ~(EN1_Pin | EN2_Pin);
}
void InitializeVL53L0X(VL53L0X_DEV Dev, uint8_t address, uint16_t pin) {
uint32_t refSpadCount;
uint8_t isApertureSpads;
uint8_t VhvSettings;
uint8_t PhaseCal;
HAL_GPIO_WritePin(GPIOB, pin, GPIO_PIN_RESET);
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, pin, GPIO_PIN_SET);
HAL_Delay(10);
VL53L0X_WaitDeviceBooted( Dev );
//Two sensors are on i2c1 and other two are on i2c2
if(Dev == DevFront || Dev == DevBack)
{
Dev->I2cHandle = &hi2c1;
}
else if(Dev == DevLeft || Dev == DevRight)
{
Dev->I2cHandle = &hi2c2;
}
Dev->I2cDevAddr = 0x52;
HAL_GPIO_WritePin(GPIOB, pin, GPIO_PIN_RESET);
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, pin, GPIO_PIN_SET);
HAL_Delay(10);
VL53L0X_WaitDeviceBooted( Dev );
if(VL53L0X_SetDeviceAddress(Dev, address) != 0)
{
MessageLen1 = sprintf((char*)Message1, "Failed to change address\n\r");
HAL_UART_Transmit(&huart2, Message1, MessageLen1, 10);
}
HAL_Delay(10);
Dev->I2cDevAddr = address;
VL53L0X_DataInit( Dev );
VL53L0X_StaticInit( Dev );
VL53L0X_PerformRefCalibration(Dev, &VhvSettings, &PhaseCal);
VL53L0X_PerformRefSpadManagement(Dev, &refSpadCount, &isApertureSpads);
VL53L0X_SetDeviceMode(Dev, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING);
VL53L0X_SetLimitCheckEnable(Dev, VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 1);
VL53L0X_SetLimitCheckEnable(Dev, VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 1);
VL53L0X_SetLimitCheckValue(Dev, VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, (FixPoint1616_t)(0.1*65536));
VL53L0X_SetLimitCheckValue(Dev, VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, (FixPoint1616_t)(60*65536));
VL53L0X_SetMeasurementTimingBudgetMicroSeconds(Dev, 33000);
VL53L0X_SetVcselPulsePeriod(Dev, VL53L0X_VCSEL_PERIOD_PRE_RANGE, 18);
VL53L0X_SetVcselPulsePeriod(Dev, VL53L0X_VCSEL_PERIOD_FINAL_RANGE, 14);
}
void SetupVL53L0X() {
//Set up all sensors with unique addresses
InitializeVL53L0X(DevFront, I2C_ADDRESS_FRONT, XSHUT_FRONT_Pin);
HAL_Delay(10);
InitializeVL53L0X(DevBack, I2C_ADDRESS_BACK, XSHUT_BACK_Pin);
HAL_Delay(10);
InitializeVL53L0X(DevLeft, I2C_ADDRESS_LEFT, XSHUT_LEFT_Pin);
HAL_Delay(10);
InitializeVL53L0X(DevRight, I2C_ADDRESS_RIGHT, XSHUT_RIGHT_Pin);
HAL_Delay(10);
}
void ReadAllSensors() {
status1 = VL53L0X_Perform (DevFront, &RangingData1);
MessageLen1 = sprintf((char*)Message1, "%d %d, ", RangingData1.RangeMilliMeter , status1);
HAL_UART_Transmit(&huart2, Message1, MessageLen1, 10);
HAL_UART_Transmit(&huart1, Message1, MessageLen1, 10);
HAL_Delay(50);
status2 = VL53L0X_PerformSingleRangingMeasurement(DevBack, &RangingData2);
MessageLen2 = sprintf((char*)Message2, "%d %d, ", RangingData2.RangeMilliMeter, status2);
HAL_UART_Transmit(&huart2, Message2, MessageLen2, 10);
HAL_UART_Transmit(&huart1, Message2, MessageLen2, 10);
HAL_Delay(50);
status3 = VL53L0X_PerformSingleRangingMeasurement(DevLeft, &RangingData3);
MessageLen3 = sprintf((char*)Message3, "%d %d, ", RangingData3.RangeMilliMeter, status3);
HAL_UART_Transmit(&huart2, Message3, MessageLen3, 10);
HAL_UART_Transmit(&huart1, Message3, MessageLen3, 10);
HAL_Delay(50);
status4 = VL53L0X_PerformSingleRangingMeasurement(DevRight, &RangingData4);
MessageLen4 = sprintf((char*)Message4, "%d %d, ", RangingData4.RangeMilliMeter, status4);
HAL_UART_Transmit(&huart2, Message4, MessageLen4, 10);
HAL_UART_Transmit(&huart1, Message4, MessageLen4, 10);
HAL_Delay(50);
MessageLen4 = sprintf((char*)Message4, "%c, ", rxdata[0]);
HAL_UART_Transmit(&huart2, Message4, MessageLen4, 10);
HAL_UART_Transmit(&huart1, Message4, MessageLen4, 10);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
MX_I2C2_Init();
MX_TIM3_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
SetupVL53L0X();
while (1)
{
ReadAllSensors();
HAL_Delay(10);
}
}
void USART1_IRQHandler(void)
{
__disable_irq();
USART1 -> SR &= (0<<5); // clear rxne flag
rxval = USART1 -> DR;
if(rxval == '#')
{
CNT = 0;
}
else if(rxval == '*')
{
state = 0x01;
}
else
{
rxdata[CNT] = rxval;
CNT++;
}
if(state)
{
state = 0;
CNT = 0;
switch(rxdata[0])
{
case 'F':
forward();
break;
case 'B':
backward();
break;
case 'L':
left();
break;
case 'R':
right();
break;
case 'S':
stop();
break;
}
}
__enable_irq();
}
2024-07-02 09:05 AM
It's an I2C bus issue. The I2C bus is VERY sensitive to electrical noise. The slightest glitch will clock an extra bit and the interface hangs. If you put a scope on the bus you will see the tell-tale 'bus stuck low' problem. It's legendary.
Stronger pull-ups, decoupling caps, better insulation, bigger wire gauge, shorter lines, twisted wire with ground. It's basically anything you can do to prevent that motor noise from causing a small glitch on your line.
Google 'i2c bus stuck low'. Every main supplier of MCUs has a series of articles on it.
It's not the sensor. The VL53L0 is every bit as good - or bad - when it comes to I2C as any other sensor.
When it happens, you can get your MCU to toggle the SCL line a few times (up to 8 times). This will finish sending the 'ghost' byte and the sensors will clear. After that everything will be normal.
- john