单片机:实现使用PWM驱动电机转动(附带源码)
单片机:实现使用PWM驱动电机转动
1. 项目背景与目标
脉宽调制(PWM)是一种通过改变信号的占空比来控制功率的技术,广泛应用于控制电机、LED亮度、音频信号生成等领域。PWM信号的占空比(即高电平持续的时间与周期时间之比)决定了输出功率的大小。在电机控制中,PWM可以用来控制电机的转速和方向。
本项目的目标是通过单片机使用PWM信号来驱动直流电机的转动。通过调整PWM信号的占空比,来实现对电机转速的调节,从而控制电机的运行。
2. 硬件设计
2.1 硬件组件
- 单片机:使用STM32系列单片机(如STM32F103)或8051系列单片机(如AT89C51),根据具体需求选择。
- 直流电机:普通直流电机,可以是小型电动机,常用于实验和小型项目中。
- 电机驱动模块:如L298N或L293D,它们是常见的用于控制直流电机的H桥驱动模块。可以通过控制输入端的PWM信号来调节电机的转速。
- 外部电源:为电机提供稳定的电源,通常与单片机的电源分开。电机驱动模块需要的电压可能会大于单片机工作电压(如电机驱动模块使用12V,单片机使用5V)。
- 电位器(可选):用于模拟调节PWM信号的占空比,进而控制电机的转速。
- 显示设备(可选):如LCD显示器,用来显示当前PWM占空比或者电机转速。
2.2 硬件连接
- 单片机PWM输出端口(如STM32的TIM1或TIM2模块)通过GPIO口输出PWM信号,连接到电机驱动模块的输入端。
- 电机驱动模块的输出端连接到电机的正负极。
- 电源管理:为电机驱动模块和电机提供单独的电源,同时保证单片机的电源稳定。
3. 软件设计
3.1 PWM信号原理
PWM信号通过调节高电平持续时间和低电平持续时间的比例(即占空比)来控制输出功率。当占空比为100%时,信号始终为高电平,电机处于最大速度;当占空比为0%时,信号始终为低电平,电机不转动;占空比介于0%和100%之间时,电机的转速与占空比成正比。
3.2 控制电机转动
- 占空比调节:通过单片机的PWM模块,设置一个定时器来输出不同占空比的PWM信号,从而控制电机的转速。
- 电机方向控制:使用H桥电路(如L298N)控制电机的转动方向。可以通过设置PWM信号的两个输入端,来改变电机的转动方向(正转或反转)。
3.3 程序设计思路
- 初始化PWM输出:配置单片机的定时器(如STM32的TIM2)产生PWM信号。
- PWM占空比调节:通过调节PWM的占空比来控制电机的转速。可以使用外部电位器来调整占空比,或者通过串口命令来动态调整。
- 电机方向控制:通过改变H桥驱动模块的输入信号来控制电机的转动方向。
- 显示与调试:将当前PWM占空比和电机状态(如转速、方向)通过串口或LCD显示出来,方便调试。
3.4 代码实现
以下是基于STM32单片机的PWM驱动电机转动的程序实现,使用STM32的定时器(如TIM2)产生PWM信号来控制电机转速,同时使用L298N电机驱动模块来控制电机方向
#include "stm32f4xx_hal.h"
// PWM输出引脚
#define MOTOR_PWM_PIN GPIO_PIN_6 // 假设PWM输出连接到PA6
#define MOTOR_PWM_PORT GPIOA
// 电机方向控制引脚
#define MOTOR_DIR_PIN1 GPIO_PIN_7 // 假设方向控制连接到PA7
#define MOTOR_DIR_PIN2 GPIO_PIN_8 // 假设方向控制连接到PA8
#define MOTOR_DIR_PORT GPIOA
// 定义PWM占空比的初始值
#define PWM_MAX 1000 // 最大占空比
#define PWM_MIN 0 // 最小占空比
// 全局变量
TIM_HandleTypeDef htim2; // 定时器2,用于PWM产生
int pwm_value = 500; // 初始占空比(50%)
// 初始化PWM输出
void PWM_Init(void) {
__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
__HAL_RCC_TIM2_CLK_ENABLE(); // 使能TIM2时钟
// 配置GPIOA6为PWM输出模式
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = MOTOR_PWM_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 推挽复用
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(MOTOR_PWM_PORT, &GPIO_InitStruct);
// 配置TIM2作为PWM输出
htim2.Instance = TIM2;
htim2.Init.Prescaler = 84 - 1; // 预分频器设置为1us
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = PWM_MAX - 1; // PWM频率1kHz
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_PWM_Init(&htim2);
// 配置PWM通道
TIM_OC_InitTypeDef sConfigOC = {0};
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = pwm_value; // 初始占空比
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
// 启动PWM输出
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}
// 控制电机的方向
void Motor_Direction(int direction) {
if (direction == 1) { // 顺时针
HAL_GPIO_WritePin(MOTOR_DIR_PORT, MOTOR_DIR_PIN1, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_DIR_PORT, MOTOR_DIR_PIN2, GPIO_PIN_RESET);
} else if (direction == -1) { // 逆时针
HAL_GPIO_WritePin(MOTOR_DIR_PORT, MOTOR_DIR_PIN1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_DIR_PORT, MOTOR_DIR_PIN2, GPIO_PIN_SET);
} else { // 停止
HAL_GPIO_WritePin(MOTOR_DIR_PORT, MOTOR_DIR_PIN1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_DIR_PORT, MOTOR_DIR_PIN2, GPIO_PIN_RESET);
}
}
// 调节PWM占空比
void Set_PWM_DutyCycle(int dutyCycle) {
if (dutyCycle < PWM_MIN) {
dutyCycle = PWM_MIN;
} else if (dutyCycle > PWM_MAX) {
dutyCycle = PWM_MAX;
}
pwm_value = dutyCycle; // 更新占空比
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pwm_value); // 更新PWM占空比
}
// 主程序
int main(void) {
HAL_Init();
PWM_Init(); // 初始化PWM
// 设置电机顺时针转动
Motor_Direction(1);
// 循环调节PWM占空比,控制电机转速
while (1) {
for (int i = PWM_MIN; i <= PWM_MAX; i += 10) {
Set_PWM_DutyCycle(i); // 增加占空比
HAL_Delay(100); // 延时100ms
}
for (int i = PWM_MAX; i >= PWM_MIN; i -= 10) {
Set_PWM_DutyCycle(i); // 减少占空比
HAL_Delay(100); // 延时100ms
}
}
}
3.5 代码解释
- PWM初始化:
PWM_Init()
函数通过配置STM32的TIM2定时器生成PWM信号,使用GPIOA6作为PWM输出。 - 电机方向控制:
Motor_Direction()
函数通过控制L298N电机驱动模块的方向引脚来控制电机的转动方向。 - PWM占空比调节:
Set_PWM_DutyCycle()
函数根据给定的占空比调节PWM信号的占空比,从而控制电机的转速。 - 主程序:主程序中,首先设置电机为顺时针转动,然后通过改变PWM的占空比来控制电机转速,形成一个动态调节电机转速的效果。
4. 仿真与测试
4.1 电路设计
- 在Proteus中创建STM32单片机的仿真项目。
- 连接PWM输出端口(如PA6)到L298N电机驱动模块的PWM输入端。
- 将L298N的输出端连接到直流电机。
- 配置电源:单片机使用3.3V电源,电机驱动模块使用12V电源。
4.2 仿真步骤
- 编译并上传代码到仿真环境。
- 运行仿真,观察电机的转速变化(通过改变PWM占空比)。
- 检查电机转动的方向是否可以通过调整方向控制引脚来改变。
5. 总结
本项目成功实现了使用PWM信号控制直流电机的转速和方向。通过调节PWM信号的占空比,可以精确控制电机的转速,达到精细调节电机运转的目的。此外,通过使用L298N电机驱动模块,我们能够实现电机的正反转控制。该项目展示了如何结合单片机的PWM功能和外部电机驱动模块,实现对电机的精准控制。
作者:Katie。