8-STM32 DC MOTOR CONTROL-PWM
- ramazanycel
- May 15, 2024
- 5 min read
Updated: May 22, 2024
This project demonstrates how to control a DC motor using PWM (Pulse Width Modulation) with the STM32L476RG microcontroller. The motor driver L293D is used to interface the DC motor with the microcontroller. PWM signals are used to control the speed of the motor. This project provides an introduction to basic motor control applications and illustrates how to generate and utilize PWM signals.
L293D and STM32 PWM Method with HAL Functions
The L293D is a dual H-bridge motor driver IC that can control two DC motors or one bipolar stepper motor. PWM signals from the STM32L476RG microcontroller are applied to the input pins of the L293D to control the motor speed.
The HAL (Hardware Abstraction Layer) library for STM32 provides functions to generate PWM signals. This library offers a hardware-independent API, making it easy to generate PWM signals using the microcontroller's hardware resources.
Understanding HAL PWM Duty Cycle Functions
Pulse Width Modulation (PWM) is a technique used to control the amount of power delivered to a device by switching it on and off at a high frequency. The proportion of time the signal is on compared to the total period of the signal is called the duty cycle. In STM32 microcontrollers, the HAL (Hardware Abstraction Layer) library provides functions to configure and control PWM signals.
Here’s an explanation of the key HAL functions used to manage the PWM duty cycle:
HAL_TIM_PWM_Init
HAL_TIM_PWM_ConfigChannel
HAL_TIM_PWM_Start
__HAL_TIM_SET_COMPARE
1. HAL_TIM_PWM_Init
This function initializes the TIM (timer) peripheral for PWM generation.
HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim);
htim: A pointer to the TIM handle structure.
This function configures the timer for PWM mode but does not start the PWM signal.
2. HAL_TIM_PWM_ConfigChannel
This function configures the PWM channel of the timer.
HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OC_InitTypeDef *sConfig, uint32_t Channel);
htim: A pointer to the TIM handle structure.
sConfig: A pointer to the TIM_OC_InitTypeDef structure that contains the configuration information for the PWM channel.
Channel: Specifies the TIM channel to be configured (e.g., TIM_CHANNEL_1).
3. HAL_TIM_PWM_Start
This function starts the PWM signal generation.
HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
%htim: A pointer to the TIM handle structure.
Channel: Specifies the TIM channel to start (e.g., TIM_CHANNEL_1).
4. __HAL_TIM_SET_COMPARE
This macro sets the compare value for the PWM duty cycle. The compare value determines the duty cycle of the PWM signal.
__HAL_TIM_SET_COMPARE(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t Compare);
htim: A pointer to the TIM handle structure.
Channel: Specifies the TIM channel to set the compare value (e.g., TIM_CHANNEL_1).
Compare: Specifies the compare value. This value determines the duty cycle.
The HAL library functions make it straightforward to initialize and configure PWM signals for controlling devices like motors. By setting the appropriate compare value, you can control the duty cycle of the PWM signal, which in turn controls the speed of the motor. The example provided demonstrates the basic setup and usage of these functions.
Required Parts For Example:
STM32L476RG Nucleo Board
L293D Motor Driver IC
DC Motor
Power Supply (suitable voltage for the motor)
Jumper Wires
Breadboard
CUBEIDE Configuration Steps:
Create a Project:
Open STM32CubeIDE and create a new project for STM32L476RG.
Pin Configuration:
Select a timer and corresponding GPIO pins for PWM output (e.g., TIM2_CH1, PA0).
Timer Settings:
Configure the timer in PWM mode.
Set the frequency and duty cycle.
GPIO Settings:
Ensure the pin used for PWM output is set to alternate function mode.
Generate and Compile Code:
Use the code generation wizard to create necessary HAL functions and compile the project.
Success is walking from failure to failure with no loss of enthusiasm."- Winston Churchill
CODE:
#include "main.h"
TIM_HandleTypeDef htim2;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init();
// Start the PWM signal
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
// Initially set duty cycle to 50%
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, htim2.Init.Period / 2);
while (1) {
// Adjust the duty cycle to control motor speed
for (int i = 0; i < htim2.Init.Period; i++) {
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, i);
HAL_Delay(10);
}
}
}
void SystemClock_Config(void) {
// System clock configuration
}
static void MX_GPIO_Init(void) {
// GPIO configuration
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
static void MX_TIM2_Init(void) {
// TIM2 configuration
__HAL_RCC_TIM2_CLK_ENABLE();
htim2.Instance = TIM2;
htim2.Init.Prescaler = 79;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 999;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) {
Error_Handler();
}
TIM_OC_InitTypeDef sConfigOC = {0};
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) {
Error_Handler();
}
}
void Error_Handler(void) {
// Error handling
while (1) {}
}
Result
In this example, the speed of a DC motor is controlled using PWM signals generated by the STM32L476RG microcontroller. The L293D motor driver IC is used to control the motor's direction and speed. This project demonstrates basic techniques for generating PWM signals and controlling motor speed. By following these steps, you can control the speed and direction of a DC motor, learn how to generate and use PWM signals, and gain a solid foundation for more complex motor control systems and robotic projects.
DC MOTOR CONTROL WITH LIBRARY
Step 1: Project Setup
First, use STM32CubeMX to configure the basic setup:
Configure GPIO and PWM Pins:
Select two GPIO pins for motor direction control.
Select one PWM pin for motor speed control.
Configure a timer (TIM) for PWM output.
Step 2: Create Library Files
Create two main files: dc_motor.h and dc_motor.c.
dc_motor.h
#ifndef DC_MOTOR_H
#define DC_MOTOR_H
#include "stm32l4xx_hal.h"
// Enumeration for motor direction
typedef enum {
MOTOR_STOP,
MOTOR_FORWARD,
MOTOR_BACKWARD
} MotorDirection;
// Motor control structure
typedef struct {
TIM_HandleTypeDef* htim; // PWM Timer handle
uint32_t pwm_channel; // PWM channel number
GPIO_TypeDef* dir_port; // GPIO port for direction control
uint16_t dir_pin1; // GPIO pin for direction control 1
uint16_t dir_pin2; // GPIO pin for direction control 2
} DC_Motor_HandleTypeDef;
// Function prototypes for motor library
void DC_Motor_Init(DC_Motor_HandleTypeDef* motor);
void DC_Motor_SetDirection(DC_Motor_HandleTypeDef* motor, MotorDirection direction);
void DC_Motor_SetSpeed(DC_Motor_HandleTypeDef* motor, uint8_t speed);
#endif // DC_MOTOR_H
dc_motor.c
#include "dc_motor.h"
void DC_Motor_Init(DC_Motor_HandleTypeDef* motor) {
// Start PWM
HAL_TIM_PWM_Start(motor->htim, motor->pwm_channel);
}
void DC_Motor_SetDirection(DC_Motor_HandleTypeDef* motor, MotorDirection direction) {
switch (direction) {
case MOTOR_FORWARD:
HAL_GPIO_WritePin(motor->dir_port, motor->dir_pin1, GPIO_PIN_SET);
HAL_GPIO_WritePin(motor->dir_port, motor->dir_pin2, GPIO_PIN_RESET);
break;
case MOTOR_BACKWARD:
HAL_GPIO_WritePin(motor->dir_port, motor->dir_pin1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(motor->dir_port, motor->dir_pin2, GPIO_PIN_SET);
break;
case MOTOR_STOP:
default:
HAL_GPIO_WritePin(motor->dir_port, motor->dir_pin1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(motor->dir_port, motor->dir_pin2, GPIO_PIN_RESET);
break;
}
}
void DC_Motor_SetSpeed(DC_Motor_HandleTypeDef* motor, uint8_t speed) {
// Speed is expected to be in the range 0-100
// Calculate pulse length based on timer's period
uint32_t pulse_length = (motor->htim->Init.Period * speed) / 100;
__HAL_TIM_SET_COMPARE(motor->htim, motor->pwm_channel, pulse_length);
}
Step 3: Use the Motor Library in Main Code
To use this library to control the motor, follow these steps in your main code file:
Include necessary header files and define the motor structure in main.c:
Initialize and control the motor in main.c:
int main(void) {
// HAL and GPIO initialization code
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init(); // Initialize PWM timer
// Motor configuration
motor.htim = &htim2; // PWM timer handle
motor.pwm_channel = TIM_CHANNEL_1; // PWM channel
motor.dir_port = GPIOB; // GPIO port for direction pins
motor.dir_pin1 = GPIO_PIN_0; // Direction pin 1
motor.dir_pin2 = GPIO_PIN_1; // Direction pin 2
// Initialize motor
DC_Motor_Init(&motor);
while (1) {
// Set motor to move forward and set speed
DC_Motor_SetDirection(&motor, MOTOR_FORWARD);
DC_Motor_SetSpeed(&motor, 50); // 50% speed
HAL_Delay(2000); // Wait for 2 seconds
// Set motor to move backward and set speed
DC_Motor_SetDirection(&motor, MOTOR_BACKWARD);
DC_Motor_SetSpeed(&motor, 50); // 50% speed
HAL_Delay(2000); // Wait for 2 seconds
// Stop the motor
DC_Motor_SetDirection(&motor, MOTOR_STOP);
DC_Motor_SetSpeed(&motor, 0); // Set speed to 0
HAL_Delay(2000); // Wait for 2 seconds
}
}
Now it's your turn.
DC MOTOR speed control with Potantiometer.
Comments