2024-06-24
	
		
		4:57 AM
	
	
	
	
	
	
	
	
	
	
	
	
	
	
 - last edited on 
    
	
		
		
		2024-06-26
	
		
		8:47 AM
	
	
	
	
	
	
	
	
	
	
	
	
	
	
 by 
				
		![]() Lina_DABASINSKA
		
			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 9: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