基于位置式PID算法调节PWM占空比实现电机转速控制
基于位置式PID算法调节PWM占空比实现电机转速控制
一、系统架构设计
1. 硬件组成
模块 | 核心组件 | 功能说明 |
---|---|---|
主控单元 | STM32F407(TIM1+TIM2) | PWM生成与PID运算 |
电机驱动 | TB6612(PWMA/PWMB) | PWM输入控制电机转速 |
反馈装置 | 霍尔编码器(500线) | 转速检测(2000脉冲/转) |
电源模块 | 12V/2A DC电源 | 电机供电 |
2. 电路连接
STM32引脚连接 | 功能说明
----------------------------|----------------------------
TIM1_CH1 (PA8) | 电机PWM输出
TIM2_CH1 (PA0) | 编码器A相信号输入
TIM2_CH2 (PA1) | 编码器B相信号输入
PB6 (BOOT0) | 电机方向控制
3.3V | 编码器供电
GND | 公共地
二、PID算法实现
1. 位置式PID公式
u(k)=Kpe(k)+Kii=0∑ke(i)+Kd[e(k)−e(k−1)]u(k)=Kpe(k)+Kii=0∑ke(i)+Kd[e(k)−e(k−1)]u(k)=Kpe(k)+Kii=0∑ke(i)+Kd[e(k)−e(k−1)]
- 输入变量:目标转速(Setpoint)与实际转速(Feedback)的差值
- 输出变量:PWM占空比(0-100%)
2. 关键参数定义
typedef struct {float Kp; // 比例系数(建议初始值2.0-5.0)float Ki; // 积分系数(建议初始值0.1-0.5)float Kd; // 微分系数(建议初始值0.01-0.1)float integral;// 积分项累加值float prev_err;// 上一次误差float max_out; // 输出上限(PWM最大占空比)
} PID_HandleTypeDef;
3. PID初始化函数
void PID_Init(PID_HandleTypeDef *pid, float Kp, float Ki, float Kd) {pid->Kp = Kp;pid->Ki = Ki;pid->Kd = Kd;pid->integral = 0.0f;pid->prev_err = 0.0f;pid->max_out = 100.0f; // PWM占空比上限
}
4. PID计算函数
float PID_Compute(PID_HandleTypeDef *pid, float setpoint, float feedback, float dt) {float error = setpoint - feedback;// 比例项float Pout = pid->Kp * error;// 积分项pid->integral += error * dt;float Iout = pid->Ki * pid->integral;// 微分项float derivative = (error - pid->prev_err) / dt;float Dout = pid->Kd * derivative;// 计算总输出float output = Pout + Iout + Dout;// 输出限幅if(output > pid->max_out) {pid->integral -= error * dt; // 防止积分饱和output = pid->max_out;} else if(output < 0) {output = 0;}pid->prev_err = error;return output;
}
三、硬件驱动实现
1. PWM配置(STM32 HAL库)
void MX_TIM1_Init(void) {TIM_HandleTypeDef htim1;htim1.Instance = TIM1;htim1.Init.Prescaler = 84-1; // 84MHz / 84 = 1MHzhtim1.Init.CounterMode = TIM_COUNTERMODE_UP;htim1.Init.Period = 1000-1; // 1kHz PWM频率htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;HAL_TIM_PWM_Init(&htim1);// 配置通道1TIM_OC_InitTypeDef sConfigOC = {0};sConfigOC.OCMode = TIM_OCMODE_PWM1;sConfigOC.Pulse = 0; // 初始占空比0%sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
}
2. 编码器测速
volatile uint32_t encoder_count = 0;
volatile float motor_speed = 0.0f;// 编码器中断处理(TIM2)
void TIM2_IRQHandler(void) {if(TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) {if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_SET) {encoder_count++;}TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);}
}// 计算转速(每100ms更新一次)
void Calc_Speed() {static uint32_t last_count = 0;static float rpm = 0.0f;motor_speed = (encoder_count - last_count) * 60.0f / 0.1f; // 500线编码器last_count = encoder_count;
}
四、主控制循环
int main(void) {HAL_Init();SystemClock_Config();MX_TIM1_Init(); // PWM初始化MX_TIM2_Init(); // 编码器初始化PID_HandleTypeDef motor_pid;PID_Init(&motor_pid, 2.5f, 0.2f, 0.05f); // 初始参数while(1) {Calc_Speed(); // 更新转速测量值float duty = PID_Compute(&motor_pid, 1000.0f, motor_speed, 0.001f); // 1kHz采样__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, duty); // 更新占空比HAL_Delay(1);}
}
参考代码 位置式PID调节PWM占空比控制电动机转速 www.youwenfan.com/contentcsj/70961.html
五、参数整定方法
1. Ziegler-Nichols法
步骤 | 操作 | 结果记录 |
---|---|---|
1 | 关闭I/D项(Ki=0, Kd=0) | 基准Kp值 |
2 | 逐渐增大Kp至系统持续振荡 | 记录Ku和Tu |
3 | 计算PID参数: | |
Kp = 0.6*Ku | ||
Ki = 1.2*Ku/Tu | ||
Kd = 0.075KuTu |
2. 实际调试建议
- 初始参数:Kp=2.0, Ki=0.1, Kd=0.01
- 调整顺序:先调P→再调I→最后调D
- 典型调试现象: Kp过小:响应慢,稳态误差大 Kp过大:超调严重,振荡 Ki过大:积分饱和,爬行现象 Kd过大:噪声敏感,产生振荡