系列文章目录
1.元件基础
2.电路设计
3.PCB设计
4.元件焊接
5.板子调试
6.程序设计
7.算法学习
8.编写exe
9.检测标准
10.项目举例
11.职业规划
文章目录
一、硬件选型与原理
1. A4950电机驱动芯片
A4950是一款高性能全桥电机驱动芯片,相比传统L298N,具有以下优势:
- 高效低功耗:内置MOSFET,支持宽电压输入(8V~40V),最大输出电流±3.5A。
- 保护功能:集成过流保护、过热关断和欠压锁定。
- 控制简单:仅需PWM信号和方向信号即可控制电机。
引脚功能:
VMOTOR
:电机电源(接电池正极)VCC
:逻辑电源(3.3V~5V,接STM32)OUT1/OUT2
:电机输出端IN1/IN2
:控制信号输入(接STM32的PWM和方向引脚)
2. STM32微控制器
以STM32F103C8T6为例,其PWM输出和定时器功能可精准控制电机转速。核心功能:
- PWM输出:通过定时器生成占空比可调的方波信号。
- 编码器接口:用于读取电机转速(闭环控制的关键)。
3. 电机与编码器
- 直流电机:需搭配编码器(如霍尔编码器)反馈转速。
- 编码器原理:电机转动时,编码器输出脉冲信号,STM32通过计数脉冲频率计算实际转速。
–
二、PID控制原理
PID(比例-积分-微分)是闭环控制的核心算法,通过实时调整输出值,使系统实际值(如转速)逼近目标值。
1. PID公式分解
- 比例(P):误差越大,调整力度越大。
P_out = Kp × Error
- 积分(I):消除历史误差累积(如电机长时间负载导致的偏差)。
I_out = Ki × Σ(Error)
- 微分(D):预测未来误差变化,抑制震荡。
D_out = Kd × (Error - Last_Error)
总输出:
PID_output = P_out + I_out + D_out
2. PID在小车中的应用
- 输入:目标转速(设定值)与实际转速(编码器反馈)。
- 输出:调整PWM占空比,动态调节电机功率。
–
三、硬件连接与电路设计
1. A4950与STM32接线
IN1
→ STM32的PWM引脚(如TIM2_CH1)IN2
→ STM32的GPIO(方向控制,高电平正转,低电平反转)OUT1/OUT2
→ 直流电机两端VMOTOR
→ 电池正极(12V)GND
→ 共地(STM32与电池负极)
2. 编码器接口
- 编码器A/B相 → STM32的定时器编码器模式引脚(如TIM3_CH1/CH2)
四、软件实现(代码详解)
1. PWM初始化(以TIM2为例)
// 初始化TIM2_CH1为PWM输出
void PWM_Init() {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 定时器频率 = 72MHz / (7200-1) = 10kHz
TIM_TimeBaseStructure.TIM_Period = 7200 - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// PWM模式:占空比可调
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; // 初始占空比0%
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_Cmd(TIM2, ENABLE);
}
2. 编码器测速
// 初始化TIM3为编码器模式
void Encoder_Init() {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // 16位计数器
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// 配置编码器接口(双通道计数)
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_Cmd(TIM3, ENABLE);
}
// 读取编码器计数值(单位时间内的脉冲数)
int16_t Get_Speed() {
int16_t cnt = TIM_GetCounter(TIM3);
TIM_SetCounter(TIM3, 0); // 清零计数器
return cnt;
}
3. PID算法实现
typedef struct {
float Kp, Ki, Kd;
float integral;
float last_error;
} PID_Controller;
float PID_Calculate(PID_Controller *pid, float target, float actual) {
float error = target - actual;
pid->integral += error;
float derivative = error - pid->last_error;
pid->last_error = error;
return pid->Kp * error + pid->Ki * pid->integral + pid->Kd * derivative;
}
–
五、调试与优化
-
PID参数整定
- Kp:先调大至电机开始震动,再减小到稳定。
- Ki:逐步增加以消除静差,但过大会导致超调。
- Kd:抑制震荡,但过大会响应变慢。
-
串口打印数据
通过串口输出实际转速与目标转速,使用工具(如SerialPlot)绘制曲线。 -
常见问题
- 电机抖动:降低Kp或增加Kd。
- 响应慢:增大Kp或Ki。
六、完整代码框架
int main() {
PWM_Init();
Encoder_Init();
PID_Controller pid = {0.5, 0.01, 0.1, 0, 0}; // 初始参数
while(1) {
float target_speed = 100; // 目标转速(脉冲数/秒)
float actual_speed = Get_Speed();
float pwm = PID_Calculate(&pid, target_speed, actual_speed);
// 限制PWM范围(0~7200对应0%~100%)
if (pwm > 7200) pwm = 7200;
else if (pwm < 0) pwm = 0;
TIM_SetCompare1(TIM2, (uint16_t)pwm);
Delay_ms(10);
}
}
–
七、总结
本文从硬件选型到PID算法实现,详细讲解了如何利用STM32和A4950构建智能小车的闭环调速系统。通过实际代码演示和调试技巧,即使是零基础开发者也能快速掌握电机控制的核心技术。后续可扩展功能如超声波避障、蓝牙遥控等,打造更智能的小车项目。