Motor Control with STM32F103

ampheoampheo
4 min read

The STM32F103 microcontroller is widely used for motor control applications, including DC motors, stepper motors, and BLDC motors. Below is a comprehensive guide on implementing motor control using PWM, H-bridge drivers, and sensor feedback.


1. Types of Motor Control

A. DC Motor Control (Brushed)

  • Control Method: PWM (Pulse Width Modulation) for speed, direction via H-bridge.

  • Key Components:

    • L298N or DRV8871 (H-bridge driver).

    • STM32 PWM Timer (TIM1, TIM2, TIM3, TIM4).

B. Stepper Motor Control

  • Control Methods:

    • Full-step, Half-step, Microstepping (using A4988 or DRV8825 drivers).

    • STM32 Timer + GPIO for step/direction signals.

C. BLDC Motor Control (Sensorless or with Hall Sensors)

  • Control Methods:

    • 6-step Commutation (Trapezoidal) – Simple, uses Hall sensors.

    • FOC (Field-Oriented Control) – Advanced, requires STM32 hardware acceleration (e.g., TIM1 for PWM, ADC for current sensing).


2. Hardware Setup

A. DC Motor with L298N H-Bridge

L298N PinSTM32F103 Connection
IN1GPIO (e.g., PA0)
IN2GPIO (e.g., PA1)
ENAPWM (e.g., TIM2_CH1)
12V, GNDMotor Power Supply

B. Stepper Motor with A4988 Driver

A4988 PinSTM32F103 Connection
STEPPWM/Timer (e.g., TIM3_CH1)
DIRGPIO (e.g., PA4)
ENABLEGPIO (e.g., PA5)

C. BLDC Motor with 3-Phase Inverter (DRV8301)

DRV8301 PinSTM32F103 Connection
PWM_H1, H2, H3TIM1_CH1, CH2, CH3
Hall SensorsGPIO/TIMx_ETR (for speed feedback)
Current SenseADC1 (PA0, PA1, PA2)

3. PWM Generation for Motor Speed Control

A. Configuring PWM on STM32F103

  • TIM1 (Advanced Timer): Best for BLDC motor control (6-channel PWM).

  • TIM2, TIM3, TIM4 (General Timers): Suitable for DC/stepper motors.

Example: PWM Setup for DC Motor (TIM2_CH1)

c

#include "stm32f1xx_hal.h"

TIM_HandleTypeDef htim2;

void PWM_Init() {
  TIM_OC_InitTypeDef sConfigOC = {0};

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 72 - 1;  // 72 MHz / 72 = 1 MHz
  htim2.Init.Period = 999;         // 1 MHz / 1000 = 1 kHz PWM
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  HAL_TIM_PWM_Init(&htim2);

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 500;  // 50% Duty Cycle (500/1000)
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);

  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}

int main() {
  HAL_Init();
  SystemClock_Config();
  PWM_Init();

  while (1) {
    // Adjust speed by changing PWM duty cycle
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 700);  // 70% speed
  }
}

4. Motor Direction Control (H-Bridge Logic)

A. DC Motor Direction Control

c

void Set_Motor_Direction(bool forward) {
  if (forward) {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);   // IN1 = HIGH
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); // IN2 = LOW
  } else {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // IN1 = LOW
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);   // IN2 = HIGH
  }
}

B. Stepper Motor Direction Control

c

void Stepper_Step(uint32_t steps, bool dir) {
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, dir);  // DIR pin
  for (uint32_t i = 0; i < steps; i++) {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);  // STEP pulse
    HAL_Delay(1);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
    HAL_Delay(1);
  }
}

5. Closed-Loop Control (PID for Speed Regulation)

A. Encoder Feedback Setup (TIMx Encoder Mode)

  • Connect Quadrature Encoder (A, B channels) to TIM3_CH1, CH2.

  • Configure in Encoder Mode for speed measurement.

c

TIM_Encoder_InitTypeDef encoder;
encoder.EncoderMode = TIM_ENCODERMODE_TI12;  // A+B channels
encoder.IC1Polarity = TIM_ICPOLARITY_RISING;
encoder.IC2Polarity = TIM_ICPOLARITY_RISING;
HAL_TIM_Encoder_Init(&htim3, &encoder);
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);

B. PID Speed Control Example

c

float Kp = 0.5, Ki = 0.1, Kd = 0.01;
float error, last_error, integral, derivative;

void PID_Control(float target_speed) {
  int32_t encoder_count = __HAL_TIM_GET_COUNTER(&htim3);
  float current_speed = encoder_count;  // Convert to RPM if needed

  error = target_speed - current_speed;
  integral += error;
  derivative = error - last_error;

  float pwm = Kp * error + Ki * integral + Kd * derivative;
  __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pwm);

  last_error = error;
}

6. BLDC Motor Control (6-Step Commutation)

  • TIM1 generates 3-phase PWM (CH1, CH2, CH3).

  • Hall sensors trigger commutation via EXTI/TIMx_ETR.

c

void BLDC_Commutation(uint8_t hall_state) {
  switch (hall_state) {
    case 0b101:  // Phase A High, B Low, C Floating
      __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 500);
      __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, 0);
      break;
    // Add other commutation states...
  }
}

7. Key Considerations

  1. PWM Frequency:

    • DC Motors: 1–20 kHz (higher reduces audible noise).

    • BLDC Motors: 8–16 kHz (for smooth operation).

  2. Current Sensing:

    • Use shunt resistors + ADC for overcurrent protection.
  3. Protection Circuits:

    • Fuse, MOSFET drivers, and freewheeling diodes for H-bridge safety.

Conclusion

The STM32F103 is capable of controlling various motors efficiently using PWM, timers, and GPIOs. For advanced applications like FOC, consider STM32F4/F7 with hardware FPU.

0
Subscribe to my newsletter

Read articles from ampheo directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

ampheo
ampheo