cancel
Showing results for 
Search instead for 
Did you mean: 

Issue with VL53L0X Sensors Interference from DC Motors on STM32F401RET6

Suchit_Niranjan
Associate

Hardware Setup:

  • Microcontroller: STM32F401RET6
  • Distance Sensors: 4 x VL53L0X (mounted for forward, backward, left, and right measurements)
  • Motor Driver: L298N
  • Motors: 2 x 12V DC motors
  • Power Supply: 12V battery for all components

 

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:

  • When the motors are off, the VL53L0X sensors provide accurate distance readings.
  • As soon as the motors start rotating, the PerformSingleRangingMeasurement function returns an error code (-20), indicating a failure in the control interface.

 

Troubleshooting Steps Taken:

  • Isolated the sensors and tested them individually: Each sensor works perfectly when the motors are not rotating.
  • Added capacitors: Added capacitors to the power supply to help filter out noise.

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();
}
1 REPLY 1
John E KVAM
ST Employee

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


Our community relies on fruitful exchanges and good quality content. You can thank and reward helpful and positive contributions by marking them as 'Accept as Solution'. When marking a solution, make sure it answers your original question or issue that you raised.

ST Employees that act as moderators have the right to accept the solution, judging by their expertise. This helps other community members identify useful discussions and refrain from raising the same question. If you notice any false behavior or abuse of the action, do not hesitate to 'Report Inappropriate Content'