news 2026/7/16 1:44:48

编码器测速原理与STM32实战:从分类到代码实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
编码器测速原理与STM32实战:从分类到代码实现

1. 编码器基础:从分类到工作原理

第一次接触编码器是在大四的智能车竞赛上,当时为了精确控制小车的电机转速,不得不硬着头皮研究这个"会输出脉冲的小玩意儿"。现在回想起来,编码器确实是运动控制系统中不可或缺的"眼睛"。

编码器本质上是一种将机械运动转换为电信号的传感器。根据不同的分类标准,编码器可以分为多种类型:

  • 按工作原理:增量式、绝对式、霍尔式
  • 按检测方式:光电式、磁电式
  • 按运动形式:旋转式、直线式

1.1 增量式编码器:工业界的"脉搏计数器"

增量式编码器就像是一个精密的脉搏计数器。它通过输出连续的脉冲信号来反映位移变化,每转过一个固定角度就会输出一个脉冲。我实验室里用的逐飞科技编码器就是典型的增量式,有A、B、Z三相信号:

  • A、B相:相位差90°的方波,用于计数和判断方向
  • Z相:每转一圈输出一个脉冲,作为零位参考

实际使用中发现,这种编码器的优势是结构简单、成本低,但断电后需要重新找零位。在智能车项目中,我们就是通过Z相信号来校准初始位置的。

1.2 绝对式编码器:自带"记忆功能"的高端货

绝对式编码器更像是自带GPS定位的装置。它的码盘上刻有独特的二进制编码,每个位置都有唯一的数字编码。这就好比摩斯电码,不同的排列组合对应不同的信息。

我拆解过一个多圈绝对编码器,内部采用齿轮组结构记录圈数。这种编码器最大的优点就是断电后位置信息不会丢失,在工业机械臂上应用广泛。不过价格也确实"美丽",一个高精度的绝对编码器能顶我一个月工资。

1.3 霍尔编码器:经济实用的选择

霍尔编码器利用霍尔效应检测磁场变化,输出两路正交信号。相比前两种,它的结构更简单、抗干扰能力更强。我在淘宝上买的20元一个的霍尔编码器,用在直流减速电机上效果就很不错。

实测发现,霍尔编码器虽然分辨率较低(常见16-64PPR),但对于一般的速度控制已经足够。而且它不怕灰尘油污,在恶劣环境下也能稳定工作,这点在工业现场特别重要。

2. 编码器测速原理深度剖析

2.1 脉冲计数:编码器测速的核心

编码器测速的本质就是统计脉冲数量。想象一下高速公路的车辆计数器:通过统计单位时间内经过的车辆数,就能估算出车流量。编码器测速也是这个道理,只不过"车辆"变成了电脉冲。

在实际项目中,我常用三种测速方法:

  1. M法(频率法):固定时间内统计脉冲数
  2. T法(周期法):测量相邻脉冲的时间间隔
  3. M/T法:结合前两种的优势

2.2 四倍频技术:精度提升的秘诀

刚开始做项目时,我发现编码器的实际分辨率比标称值高很多。后来才知道这是用了四倍频技术——通过检测A、B相的上升沿和下降沿,将分辨率提高4倍。

以常见的100PPR编码器为例:

  • 原始分辨率:100脉冲/转
  • 四倍频后:400脉冲/转

这个技巧在低速测量时特别有用。我曾经用STM32的编码器模式实现了四倍频,代码配置后面会详细介绍。

2.3 方向判断:AB相的秘密

AB相信号的相位差不仅用于倍频,还能判断旋转方向。这里有个简单规律:

  • 正转时:A相上升沿对应B相低电平
  • 反转时:A相上升沿对应B相高电平

在STM32中,通过读取计数器的计数方向(CR1寄存器的DIR位)就能知道电机转向,非常方便。

3. STM32硬件配置实战

3.1 定时器编码器模式配置

STM32的定时器外设内置了编码器接口,配置起来比用外部中断方便多了。以TIM3为例,最关键的几个配置步骤:

  1. GPIO初始化:配置PA6、PA7为浮空输入
  2. 时基设置:ARR设为最大值,PSC为0
  3. 编码器模式:选择TI1和TI2边沿计数
  4. 滤波器设置:根据信号质量调整ICF值
void Encoder_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; GPIO_InitTypeDef GPIO_InitStructure; // 1. 时钟使能 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 2. GPIO配置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM3); GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_TIM3); // 3. 时基配置 TIM_TimeBaseStructure.TIM_Period = 0xFFFF; TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); // 4. 编码器接口配置 TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); TIM_ICStructInit(&TIM_ICInitStructure); TIM_ICInitStructure.TIM_ICFilter = 6; TIM_ICInit(TIM3, &TIM_ICInitStructure); TIM_Cmd(TIM3, ENABLE); }

3.2 中断配置与计数处理

为了处理计数器溢出,我们需要配置更新中断。在中断服务函数中记录溢出次数:

volatile int32_t Encoder_Overflow = 0; void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET) { if(TIM_GetCounter(TIM3) > 0x7FFF) Encoder_Overflow--; else Encoder_Overflow++; TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } }

3.3 速度计算:从脉冲到转速

速度计算的关键是理解几个参数的关系:

  • PPR:编码器每转脉冲数(物理分辨率)
  • 倍频数:通常为4(四倍频)
  • 采样周期:计算速度的时间窗口

速度计算公式:

转速(rpm) = (ΔCount / (PPR×4)) × (60 / 采样时间(s))

实现代码:

int32_t Get_Speed(uint32_t PPR, float sample_time) { static int32_t last_count = 0; int32_t current_count = TIM_GetCounter(TIM3) + Encoder_Overflow * 65536; int32_t delta = current_count - last_count; last_count = current_count; return (delta * 60) / (PPR * 4 * sample_time); }

4. 常见问题与优化技巧

4.1 信号抖动:硬件滤波很重要

在第一个智能车项目上,我遇到过信号抖动导致计数不准的问题。后来发现是接线太长引入了干扰。解决方法有两个:

  1. 硬件方面

    • 使用屏蔽线
    • 在信号线上加100pF电容
    • 缩短走线距离
  2. 软件方面

    • 调整输入捕获滤波器
    • 增加软件去抖算法

4.2 低速测量:T法的优势

当电机转速很低时,M法会出现分辨率不足的问题。这时可以切换到T法测量:

float Get_Speed_T_Method(uint32_t PPR) { uint32_t period = Get_Pulse_Period(); // 获取脉冲周期(us) return 60000000.0f / (PPR * 4 * period); // rpm }

4.3 多电机同步:定时器资源分配

在四轮驱动项目中,需要同时测量四个电机的转速。STM32F103的定时器资源有限,我是这样分配的:

电机定时器引脚
左前TIM2PA0-PA1
右前TIM3PA6-PA7
左后TIM4PB6-PB7
右后TIM5PA0-PA1(重映射)

对于没有足够编码器接口的MCU,可以考虑使用外部中断+定时器的方式,不过这会增加CPU负担。

5. 完整项目实战:智能车测速系统

5.1 硬件连接示意图

[电机] -> [编码器] A相 -> TIMx_CH1 B相 -> TIMx_CH2 VCC -> 5V GND -> GND

5.2 软件架构设计

  1. 底层驱动层

    • 编码器初始化
    • 定时器配置
  2. 算法层

    • 速度计算
    • 滤波处理
  3. 应用层

    • PID控制
    • 数据传输

5.3 关键代码实现

typedef struct { int32_t raw_count; int32_t last_count; float speed_rpm; uint32_t ppr; } Encoder_TypeDef; Encoder_TypeDef encoder[4]; void Encoder_Update(Encoder_TypeDef *enc, TIM_TypeDef *TIMx) { enc->raw_count = TIMx->CNT + Encoder_Overflow * 65536; int32_t delta = enc->raw_count - enc->last_count; enc->last_count = enc->raw_count; // 低通滤波 enc->speed_rpm = 0.2f * (delta * 60.0f / (enc->ppr * 4 * 0.01f)) + 0.8f * enc->speed_rpm; } void Control_Loop(void) { for(int i=0; i<4; i++) { Encoder_Update(&encoder[i], TIMx[i]); PID_Calculate(&pid[i], encoder[i].speed_rpm, target_speed); Set_PWM(MOTOR[i], pid[i].output); } }

6. 进阶话题:从速度到位置控制

当项目要求更高时,单纯的测速就不够用了。我在机械臂项目中实现了位置控制,关键点包括:

  1. 位置计算

    position = (count_total / (PPR×4)) × 轮周长
  2. 多圈计数

    • 利用Z相信号校准
    • 软件记录圈数
  3. 闭环控制

    • 位置环+速度环双闭环
    • 梯形加减速算法

这些年在不同项目中使用过各种编码器,从几块钱的霍尔编码器到上万元的绝对式编码器都有接触。实测下来,STM32的编码器接口模式确实稳定可靠,配合适当的滤波算法,完全能满足大多数工业应用的需求。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/16 1:44:41

C++项目glog日志库实战:从编译集成到高级配置全解析

1. 项目概述如果你在C项目里用过Google Logging&#xff08;glog&#xff09;&#xff0c;大概率对它又爱又恨。爱的是它那套基于C流式风格的日志API&#xff0c;用起来确实顺手&#xff0c;LOG(INFO) << “Something happened: “ << value;这种写法&#xff0c;既…

作者头像 李华
网站建设 2026/7/16 1:42:03

LinkSwift:一站式网盘直链下载助手,告别九大网盘限速烦恼

LinkSwift&#xff1a;一站式网盘直链下载助手&#xff0c;告别九大网盘限速烦恼 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移…

作者头像 李华
网站建设 2026/7/16 1:40:36

Understat Python库终极指南:三步解锁专业足球数据分析

Understat Python库终极指南&#xff1a;三步解锁专业足球数据分析 【免费下载链接】understat An asynchronous Python package for https://understat.com/. 项目地址: https://gitcode.com/gh_mirrors/un/understat 想要获取专业的足球统计数据却苦于技术壁垒&#x…

作者头像 李华
网站建设 2026/7/16 1:38:10

分布式锁的工程实践:Redlock算法的正确实现与边界条件分析

分布式锁的工程实践&#xff1a;Redlock算法的正确实现与边界条件分析 一、引言 分布式锁是微服务架构中最基础的同步原语之一。很多团队引入Redis后&#xff0c;顺手用SET NX EX实现了锁&#xff0c;以为这样就能解决并发问题。直到某天线上出现重复扣款或者数据不一致&#x…

作者头像 李华
网站建设 2026/7/16 1:36:48

【避坑指南】MyBatis-Plus中TypeHandler不生效的常见场景与解决方案

1. 为什么你的TypeHandler突然失效了&#xff1f;第一次在MyBatis-Plus里用TableField(typeHandler)注解时&#xff0c;很多人都会遇到这样的场景&#xff1a;明明按照文档配置了自定义TypeHandler&#xff0c;但查询时字段死活返回null&#xff0c;更新时类型转换直接报错。这…

作者头像 李华