第 6 章:正交编码器速度测量(PCNT)
📂 示例代码:06_encoder
6.1 知识要点
- 正交编码器的工作原理(A/B 相,方向判断)
- ESP-IDF PCNT(脉冲计数)新 API 的配置
- 溢出回调与累积计数的实现
- 脉冲数到线速度的换算公式
6.2 课程内容
OSRCORE 配备了一个带减速箱的直流电机,电机轴上安装了 1024 PPR 的正交编码器。通过 PCNT 外设对编码器脉冲计数,结合减速比(10.55)和轮径(42.5 mm),可以精确计算车轮线速度,为 PID 闭环控制提供反馈。
6.3 基础学习
正交编码器原理
正交编码器输出两路相位差 90° 的方波(A 相和 B 相):
- 正转时:A 相超前 B 相 90°
- 反转时:B 相超前 A 相 90°
通过检测 A 相边沿时 B 相的电平,可以判断旋转方向。
PCNT 配置为:A 相(EA)上升沿计数,B 相(EB)电平控制方向(高电平正计数,低电平反计数)。
速度换算公式
每转脉冲数 = PPR × 减速比 = 1024 × 10.55 = 10803.2
轮周长 = 2π × 0.0425 = 0.2670 m
每脉冲距离 = 0.2670 / 10803.2 = 2.471×10⁻⁵ m/pulse
速度 (m/s) = Δpulses × 每脉冲距离 / ΔtPCNT 硬件累加(accum_count)
将 pcnt_unit_config_t.flags.accum_count = 1 置位后,PCNT 硬件在计数器到达 watch point 时自动将溢出量累加到内部 64-bit 累加器。pcnt_unit_get_count() 直接返回真实累计值,无需软件溢出回调,代码更简洁,也不存在中断延迟导致的计数丢失风险。
6.4 程序学习
PCNT 初始化(accum_count 硬件累加模式):
c
pcnt_unit_config_t unit_cfg = {
.low_limit = -30000,
.high_limit = 30000,
.flags.accum_count = 1, // 启用硬件级累加,无需软件溢出回调
};
pcnt_new_unit(&unit_cfg, &s_unit);
pcnt_chan_config_t chan_a = {
.edge_gpio_num = 3, // EA
.level_gpio_num = 9, // EB
};
pcnt_channel_handle_t ch_a;
pcnt_new_channel(s_unit, &chan_a, &ch_a);
pcnt_channel_set_edge_action(ch_a,
PCNT_CHANNEL_EDGE_ACTION_INCREASE, // 上升沿 +1
PCNT_CHANNEL_EDGE_ACTION_HOLD); // 下降沿不计
pcnt_channel_set_level_action(ch_a,
PCNT_CHANNEL_LEVEL_ACTION_KEEP, // EB 高:正方向
PCNT_CHANNEL_LEVEL_ACTION_INVERSE); // EB 低:反方向
/* watch point 供硬件累加器使用 */
pcnt_unit_add_watch_point(s_unit, 30000);
pcnt_unit_add_watch_point(s_unit, -30000);
pcnt_unit_enable(s_unit);
pcnt_unit_clear_count(s_unit);
pcnt_unit_start(s_unit);直接读取累计计数(无需软件 accum 变量):
c
static int32_t encoder_get_count(void)
{
int raw = 0;
pcnt_unit_get_count(s_unit, &raw);
return raw; // 硬件已累加,直接返回真实计数
}速度计算(20 ms 周期):
c
int32_t delta = encoder_get_count() - last_count;
float speed = delta * DIST_PER_PULSE / 0.020f; // m/s6.5 课程总结
本章掌握了正交编码器的工作原理和 PCNT 外设的配置,通过 accum_count=1 启用硬件级累加,消除了软件溢出回调的复杂性。PPR 从 512 更新为 1024,每转脉冲数 10803.2,线速度计算更精确。这是 PID 速度闭环控制的核心反馈环节。