DEV Community

Hedy
Hedy

Posted on

Using STM32 to make a tracking car

Creating a tracking car using an STM32 microcontroller involves integrating sensors, motors, and control algorithms to enable the car to follow a line or avoid obstacles. Below is a step-by-step guide to building a tracking car with STM32:

Image description

1. Define the Project Requirements

Type of Tracking:

Line-following: Use IR sensors to detect a line on the ground.

Obstacle avoidance: Use ultrasonic or IR sensors to detect and avoid obstacles.

Motor Control: Use DC motors with an H-bridge or motor driver.

Power Supply: Ensure the STM32, sensors, and motors are properly powered (e.g., using batteries).

Communication: Optional, for remote control or data logging (e.g., UART, Bluetooth, Wi-Fi).

2. Gather Components

STM32 Microcontroller: e.g., STM32F4 or STM32F1 series.

Motor Driver: e.g., L298N, TB6612FNG, or DRV8833.

DC Motors: Two or four motors for movement.

Wheels: Matching wheels for the motors.

Sensors:

Line-following: IR sensors (e.g., TCRT5000).

Obstacle avoidance: Ultrasonic sensors (e.g., HC-SR04) or IR distance sensors.

Chassis: A frame to hold all components.

Power Supply: Batteries (e.g., 9V or LiPo) and voltage regulators (e.g., 5V or 3.3V for STM32).

Optional: Bluetooth module (e.g., HC-05) for remote control.

3. Design the Hardware

a. Motor Control

  • Connect the motors to the motor driver.
  • Connect the motor driver to the STM32 GPIO pins for PWM control.
  • Example connections for L298N:

  • IN1, IN2, IN3, IN4 → STM32 GPIO pins.

  • ENA, ENB → STM32 PWM pins for speed control.

b. Sensor Integration

Line-following:

  • Place IR sensors at the front of the car.
  • Connect the sensor outputs to STM32 GPIO pins.

Obstacle avoidance:

  • Place ultrasonic sensors at the front and sides.
  • Connect the trigger and echo pins to STM32 GPIO pins.

c. Power Supply

  • Use a voltage regulator to provide 3.3V or 5V to the STM32 and sensors.
  • Connect the motor driver directly to the battery.

4. Write the Firmware

a. Initialize Peripherals

  • Configure GPIO pins for sensors and motor control.
  • Set up PWM for motor speed control.
  • Initialize ADC (if using analog sensors).

Example:

c

void GPIO_Init(void) {
    // Configure motor control pins
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;
    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);
}
Enter fullscreen mode Exit fullscreen mode

b. Read Sensor Data

Line-following:

Read the IR sensor outputs to detect the line.

Example:


c

uint8_t Read_IR_Sensors(void) {
    uint8_t left = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
    uint8_t right = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
    return (left << 1) | right;
}
Enter fullscreen mode Exit fullscreen mode

Obstacle avoidance:

Use the ultrasonic sensor to measure distance.

Example:

c

float Read_Ultrasonic_Sensor(void) {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET); // Trigger
    delay_us(10);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
    while (!HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3)); // Wait for echo
    uint32_t start = TIM2->CNT;
    while (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3));
    uint32_t end = TIM2->CNT;
    return (end - start) * 0.034 / 2; // Distance in cm
}
Enter fullscreen mode Exit fullscreen mode

c. Implement Control Logic

Line-following:

Use a PID controller or simple logic to adjust motor speeds based on sensor inputs.

Example:

c

void Line_Following(void) {
    uint8_t sensors = Read_IR_Sensors();
    if (sensors == 0b01) { // Turn left
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    } else if (sensors == 0b10) { // Turn right
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
    } else { // Move forward
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
    }
}
Enter fullscreen mode Exit fullscreen mode

Obstacle avoidance:

Adjust the car's direction based on distance measurements.

Example:

c

void Avoid_Obstacle(void) {
    float distance = Read_Ultrasonic_Sensor();
    if (distance < 20) { // Turn left if obstacle is close
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    } else { // Move forward
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
    }
}
Enter fullscreen mode Exit fullscreen mode

d. Main Loop

Continuously read sensor data and adjust motor control.

Example:

c

int main(void) {
    HAL_Init();
    SystemClock_Config();
    GPIO_Init();
    while (1) {
        Line_Following(); // or Avoid_Obstacle();
    }
}
Enter fullscreen mode Exit fullscreen mode

5. Test and Debug

  • Test the car on a line or in an obstacle-filled environment.
  • Adjust the control logic and sensor thresholds for optimal performance.
  • Use a debugger (e.g., STM32CubeIDE) to monitor variables and troubleshoot issues.

6. Optional Enhancements

  • Wireless Control: Add a Bluetooth module for remote control.
  • Data Logging: Use UART or an SD card to log sensor data.
  • Advanced Algorithms: Implement advanced control algorithms like PID for smoother tracking.

Example Code for Line-Following Car

c

#include "stm32f4xx.h"

void GPIO_Init(void) {
    // Configure motor control pins
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;
    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);

    // Configure IR sensor pins
    __HAL_RCC_GPIOB_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

uint8_t Read_IR_Sensors(void) {
    uint8_t left = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
    uint8_t right = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
    return (left << 1) | right;
}

void Line_Following(void) {
    uint8_t sensors = Read_IR_Sensors();
    if (sensors == 0b01) { // Turn left
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    } else if (sensors == 0b10) { // Turn right
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
    } else { // Move forward
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
    }
}

int main(void) {
    HAL_Init();
    SystemClock_Config();
    GPIO_Init();
    while (1) {
        Line_Following();
    }
}
Enter fullscreen mode Exit fullscreen mode

By following these steps, you can build a tracking car using an STM32 microcontroller. Customize the design and code based on your specific requirements and components.

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more