Motor Control with STM32F103


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:
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 Pin | STM32F103 Connection |
IN1 | GPIO (e.g., PA0) |
IN2 | GPIO (e.g., PA1) |
ENA | PWM (e.g., TIM2_CH1) |
12V, GND | Motor Power Supply |
B. Stepper Motor with A4988 Driver
A4988 Pin | STM32F103 Connection |
STEP | PWM/Timer (e.g., TIM3_CH1) |
DIR | GPIO (e.g., PA4) |
ENABLE | GPIO (e.g., PA5) |
C. BLDC Motor with 3-Phase Inverter (DRV8301)
DRV8301 Pin | STM32F103 Connection |
PWM_H1, H2, H3 | TIM1_CH1, CH2, CH3 |
Hall Sensors | GPIO/TIMx_ETR (for speed feedback) |
Current Sense | ADC1 (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
PWM Frequency:
DC Motors: 1–20 kHz (higher reduces audible noise).
BLDC Motors: 8–16 kHz (for smooth operation).
Current Sensing:
- Use shunt resistors + ADC for overcurrent protection.
Protection Circuits:
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.
Subscribe to my newsletter
Read articles from ampheo directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
