51单片机编码器测速实战:从原理到避坑指南

1次阅读
没有评论

共计 1869 个字符,预计需要花费 5 分钟才能阅读完成。

image.webp

旋转编码器测速原理

旋转编码器通过光电或磁电方式,将机械转动转换为电脉冲信号。常见的有增量式编码器(A/ B 相)和绝对式编码器,我们主要讨论增量式。当电机转动时,编码器输出两路相位差 90 度的方波(正交信号),通过检测脉冲数量和方向即可计算转速。

51 单片机编码器测速实战:从原理到避坑指南

测速需求广泛存在于:

  • 直流电机闭环控制
  • 工业设备转速监控
  • 机器人关节位置反馈

外部中断法 vs 定时器捕获法

外部中断法

  • 优点:硬件资源占用少,只需一个 IO 口 + 外部中断
  • 缺点:高速时可能丢失脉冲,需要严格优化中断服务程序

定时器捕获法

  • 优点:自动记录脉冲时间戳,测量更精确
  • 缺点:需要特定定时器硬件支持,资源受限时难以实现

对于 51 单片机,通常推荐外部中断法 + 定时器辅助的方案。

核心实现步骤

硬件电路设计

  1. 上拉电阻 :编码器输出接 10kΩ 上拉电阻,避免浮空状态
  2. 消抖电路 :并联 0.1uF 电容 +100Ω 电阻构成低通滤波
  3. 信号隔离 :高速场合建议使用光耦隔离(如 HCPL2630)
// 硬件连接示例(STC89C52)#define ENCODER_A P3_2  // INT0
#define ENCODER_B P3_3  // 普通 IO

状态机脉冲计数

采用 4 倍频计数可提高分辨率:

volatile long pulse_count = 0;  // 必须加 volatile

void INT0_ISR() interrupt 0 {
    static unsigned char last_state = 0;
    unsigned char new_state = (ENCODER_A << 1) | ENCODER_B;

    // 状态转移判断
    switch(last_state) {case 0: if(new_state == 2) pulse_count++; else if(new_state == 1) pulse_count--; break;
        case 1: if(new_state == 0) pulse_count++; else if(new_state == 3) pulse_count--; break;
        case 2: if(new_state == 3) pulse_count++; else if(new_state == 0) pulse_count--; break;
        case 3: if(new_state == 1) pulse_count++; else if(new_state == 2) pulse_count--; break;
    }
    last_state = new_state;
}

移动平均滤波

#define FILTER_WINDOW 5
float speed_buffer[FILTER_WINDOW] = {0};

float get_filtered_speed(float new_speed) {
    static int index = 0;
    float sum = 0;

    speed_buffer[index++] = new_speed;
    if(index >= FILTER_WINDOW) index = 0;

    for(int i=0; i<FILTER_WINDOW; i++) {sum += speed_buffer[i];
    }
    return sum / FILTER_WINDOW;
}

转速计算公式

假设编码器每转产生 N 个脉冲,采样周期为 T 秒:

 转速 (RPM) = (Δpulse_count / N) × (60 / T)

性能测试数据

设定转速 (RPM) 测量均值 (RPM) 误差率
300 298.2 0.6%
1000 992.4 0.76%
2000 1973.8 1.31%

中断响应时间测试方法:

  1. 在中断入口翻转 IO 电平
  2. 用示波器测量信号跳变间隔
  3. 实测 STC89C52 响应时间约 2.5μs

常见问题解决方案

信号干扰处理

  • 使用双绞线传输信号
  • 信号线长度不超过 50cm
  • 添加 TVS 二极管防护

脉冲丢失优化

  1. 降低中断服务程序复杂度
  2. 改用 PCA 模块硬件计数
  3. 提高单片机时钟频率

电源噪声抑制

  • 编码器电源与 MCU 电源隔离
  • 每颗 IC 加 0.1uF 去耦电容
  • 模拟地 / 数字地单点连接

拓展思考

如何实现双向测速?提示:

  1. 同时监测 A / B 相相位差
  2. 设置方向标志位
  3. 脉冲计数根据方向增减
// 方向判断示例
if((last_state == 0 && new_state == 2) || 
   (last_state == 2 && new_state == 3) ||
   (last_state == 3 && new_state == 1) ||
   (last_state == 1 && new_state == 0)) {direction = FORWARD;} else {direction = BACKWARD;}

通过本文介绍的方法,我在多个项目中实现了 50-5000RPM 范围内的稳定测速,误差控制在 1.5% 以内。特别提醒新手注意:一定要用示波器观察实际波形,很多问题都是信号质量引起的。

正文完
 0
评论(没有评论)