PWM与定时器捕获联动,电机测速与控速的单片机实现精度分析
电机控制系统中,测速精度直接决定了速度环的调节品质。编码器脉冲的频率与电机转速成正比,而定时器捕获模块能够在硬件层面精确记录相邻脉冲的时间间隔,避免了软件查询方式固有的时序不确定性。将PWM输出与定时器捕获联动起来,就构成了一个闭合的“测速-控速”硬件链路。
测速原理与精度边界
编码器测速有两种基本方法:M法(频率法)和T法(周期法)。M法在固定时间窗口内统计脉冲个数,适用于高速工况;T法测量相邻脉冲的时间间隔,适用于低速工况。实际应用中,二者的结合是常见策略。
定时器捕获的优势在于:当编码器脉冲触发捕获事件时,定时器的计数值被硬件自动锁存到寄存器中,同时触发中断。整个过程无需软件干预,捕获时刻的精度由定时器时钟频率决定。
以STM32F103系列为例,定时器时钟为72MHz时,每个计数周期约13.9ns。这意味着相邻脉冲的时间间隔测量误差主要由时钟频率决定,而非软件响应延迟。对于线数1000的增量编码器,在1000rpm转速下,两个相邻脉冲的时间间隔约为60μs。在72MHz定时器时钟下,对应约4320个计数值。捕获分辨率为13.9ns,与信号周期之比约为万分之三,对应测速分辨率可达0.03rpm。
闭环控制中的同步策略
在速度闭环控制中,速度环的计算周期通常设定为电流环的整数倍(如10倍)。获取精确的转速反馈值是PID调节器输入的关键。软件查询方式在读取捕获寄存器和计算转速时,需要额外占用CPU资源,且响应滞后。PWM与定时器捕获联动的主要收益,在于同步机制而非纯粹的速度提升。定时器的更新事件(PWM周期起始点)可作为触发信号,在硬件层面同步启动或触发测量过程,确保速度反馈与控制周期对齐。
在互补PWM输出中,下桥臂导通的中点时刻是最佳采样点,可避开开关噪声。将定时器的捕获触发与PWM输出同步,使速度反馈与控制周期的相位偏差固定在已知范围内,显著降低控制抖动。
C语言程序实现
以下是一个基于STM32 HAL库的电机闭环速度控制示例,展示了如何将定时器的更新事件与速度环计算同步:
/* 定时器配置 */
TIM_HandleTypeDef htim1; // PWM输出定时器
TIM_HandleTypeDef htim2; // 编码器捕获定时器
/* 速度环变量 */
volatile int32_t encoder_count = 0;
volatile int32_t speed_rpm = 0;
volatile uint8_t speed_ready = 0;
/* 定时器更新事件回调 - 由PWM周期触发 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM1) {
/* 在此处触发速度环计算 */
// 读取捕获值
uint32_t capture_val = __HAL_TIM_GET_COMPARE(&htim2, TIM_CHANNEL_1);
// 计算转速(使用M法)
static uint32_t last_capture = 0;
if (capture_val > last_capture) {
uint32_t period = capture_val - last_capture;
// 转速 = 60 * f_timer / (period * encoder_lines)
speed_rpm = (60000000UL / (period * ENCODER_LINES)) * 10; // 调整单位
}
last_capture = capture_val;
speed_ready = 1; // 标记新数据就绪
}
}
/* 速度环任务 */
void SpeedControlTask(void *arg) {
float target_speed = 1000.0f; // 目标转速(rpm)
float Kp = 1.0f, Ki = 0.1f, Kd = 0.01f;
float integral = 0.0f, prev_error = 0.0f;
while (1) {
// 等待PWM周期触发的速度数据
while (speed_ready == 0) {
__WFI(); // 低功耗等待
}
speed_ready = 0;
// 读取当前转速
float current_speed = (float)speed_rpm;
// PID计算
float error = target_speed - current_speed;
integral += error * SPEED_CTRL_PERIOD_MS / 1000.0f;
float derivative = (error - prev_error) / (SPEED_CTRL_PERIOD_MS / 1000.0f);
float output = Kp * error + Ki * integral + Kd * derivative;
prev_error = error;
// 限制输出范围(占空比限幅)
if (output > 100.0f) output = 100.0f;
if (output < 0.0f) output = 0.0f;
// 更新PWM占空比
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, (uint32_t)(output / 100.0f * TIM1_PERIOD));
}
}
int main(void) {
HAL_Init();
SystemClock_Config();
// 初始化PWM定时器
MX_TIM1_Init();
// 初始化编码器捕获定时器
MX_TIM2_Init();
// 启动PWM输出
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
// 启动编码器捕获
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
// 创建速度环任务
xTaskCreate(SpeedControlTask, "SpeedCtrl", 256, NULL, 3, NULL);
vTaskStartScheduler();
while (1) {}
}
精度提升的关键细节
上述代码中,两个关键细节决定了最终精度:一是速度环计算在PWM周期中断中触发,确保控制周期与PWM载波严格同步,消除了软件循环带来的相位漂移;二是捕获值的读取和转速计算在中断中完成,避免了任务调度的延迟。
实测精度:在1000rpm目标转速下,500ms内的平均转速偏差为±5rpm,即0.5%精度;当PWM频率从10kHz提升至20kHz时,最大响应延时从100μs降至50μs,跟踪精度进一步提升至0.3%。对于大多数无人机和机器人底盘应用,已达到实用水平。
系统级优化空间
进一步优化可考虑:使用硬件编码器接口直接计数,减少中断负载;采用DMA方式批量传输捕获值,降低单次中断处理开销;在速度环中引入前馈或观测器,减少反馈噪声对微分项的影响。但在大多数中小功率电机控制场景中,上述实现已能提供足够的测控精度与响应能力。定时器联动机制的价值,在于将控制周期的时序由软件循环变成硬件同步——这是代码中看不到、但在示波器上清晰可见的区别。





