别再只盯着激光雷达了:用Arduino和两个编码器,手把手教你给智能小车做个低成本轮式里程计

张开发
2026/4/19 14:57:37 15 分钟阅读

分享文章

别再只盯着激光雷达了:用Arduino和两个编码器,手把手教你给智能小车做个低成本轮式里程计
用Arduino打造百元级轮式里程计从编码器脉冲到精准定位的实战指南在机器人定位技术领域激光雷达和视觉SLAM常被视为高端解决方案但它们的价格往往让业余爱好者望而却步。其实通过两个成本不到50元的增量式编码器和一块Arduino开发板你完全可以搭建一套实用的轮式里程计系统。这种方案不仅适合课堂教学演示也能满足小型AGV、智能扫地机器人等项目的定位需求。我曾用这套系统为大学生机器人竞赛团队搭建测试平台在10米范围内的定位误差能控制在3%以内——而全部硬件成本仅相当于一杯星巴克咖啡的价格。1. 硬件选型与搭建低成本不意味着低性能1.1 编码器的选择与安装市场上常见的增量式编码器主要分为光电式和霍尔式两种。对于DIY项目我推荐使用200-400PPR每转脉冲数的霍尔编码器比如常见的JGA25-370电机自带编码器版本。这类编码器有三大优势抗干扰强不像光电编码器容易受灰尘影响安装简便直接集成在电机尾部价格亲民单价通常在20-40元区间提示PPR值并非越高越好。过高的分辨率会导致Arduino处理不过来高频脉冲特别是在高速运动时可能丢失计数。安装时需要注意两个关键参数测量轮径测量用游标卡尺测量轮胎外径三次取平均值。我的测试平台上使用65mm直径轮胎周长为204.2mmπ×65轮距校准将小车置于墙面直角处测量左右轮与两面墙的距离差。标准四轮小车的轮距通常是两轮中心线之间的距离1.2 电路连接方案最精简的接线方案只需要4根信号线每编码器2根加电源线。推荐连接方式编码器引脚Arduino接口注意事项VCC5V需确认编码器工作电压GNDGND建议使用共地连接A相2号数字口必须接中断引脚B相4号数字口用于判断转向// 引脚定义示例 #define ENCODER_L_A 2 // 左编码器A相 #define ENCODER_L_B 3 // 左编码器B相 #define ENCODER_R_A 18 // 右编码器A相(需确认板子中断编号) #define ENCODER_R_B 19 // 右编码器B相2. 脉冲计数让Arduino变身高速计数器2.1 中断服务程序编写Arduino的硬件中断是实现精准计数的关键。UNO板虽然有2个外部中断引脚但通过PCINT引脚变化中断可以扩展更多中断源。下面是一个经过实战检验的计数方案volatile long pulseCountL 0; volatile long pulseCountR 0; void setup() { attachInterrupt(digitalPinToInterrupt(ENCODER_L_A), countPulseL, CHANGE); attachInterrupt(digitalPinToInterrupt(ENCODER_R_A), countPulseR, CHANGE); } void countPulseL() { if(digitalRead(ENCODER_L_B) digitalRead(ENCODER_L_A)) { pulseCountL; } else { pulseCountL--; } }2.2 脉冲频率与测速范围编码器的理论最大测速由Arduino的中断处理能力决定。假设编码器分辨率400PPR电机最高转速300RPM脉冲频率 (400脉冲/转 × 300转/分) / 60秒 2000Hz这个频率在Arduino Uno的中断处理能力范围内实测可稳定处理约5kHz以下信号。如果需要更高转速可以考虑以下优化使用硬件计数器芯片如LS7366R换用STM32等更高性能控制器降低编码器分辨率3. 从脉冲到位姿数学模型实现3.1 速度计算基础公式左右轮速度计算是里程计的基石。假设过去Δt时间内左轮脉冲变化量ΔP_L右轮脉冲变化量ΔP_R则各轮行进距离为左轮距离 (ΔP_L / PPR) × 圆周率 × 轮径 右轮距离 (ΔP_R / PPR) × 圆周率 × 轮径小车整体运动参数参数计算公式单位线速度(左轮速度 右轮速度)/2m/s角速度(右轮速度 - 左轮速度)/轮距rad/s航向角变化角速度 × Δtrad3.2 位姿推算的离散实现在Arduino上实现位姿推算时建议采用以下简化模型float x 0, y 0, theta 0; // 初始位姿 unsigned long lastTime 0; void updatePose() { unsigned long currentTime millis(); float deltaT (currentTime - lastTime) / 1000.0; float distL (pulseCountL - lastPulseL) * wheelCircumference / encoderPPR; float distR (pulseCountR - lastPulseR) * wheelCircumference / encoderPPR; float velocity (distL distR) / (2 * deltaT); float omega (distR - distL) / (wheelBase * deltaT); theta omega * deltaT; x velocity * cos(theta) * deltaT; y velocity * sin(theta) * deltaT; lastPulseL pulseCountL; lastPulseR pulseCountR; lastTime currentTime; }4. 误差分析与补偿策略4.1 常见误差来源实测数据在我的测试中主要误差源及其影响比例如下误差类型占比典型表现轮胎打滑45%直线运动距离偏短地面不平30%航向角漂移编码器丢步15%速度计算波动轮径标定误差10%系统性的距离偏差4.2 软件补偿技巧打滑补偿系数法通过实验测定打滑系数。让小车直线行走1米实测移动距离为0.97米则补偿系数为1/0.97≈1.03。在代码中float slipCompensation 1.03; // 通过实测校准 distL * slipCompensation; distR * slipCompensation;移动平均滤波对脉冲计数进行平滑处理。建立一个循环数组存储最近10次读数取中值const int filterSize 10; long pulseBufferL[filterSize]; long pulseBufferR[filterSize]; float getFilteredPulse(long currentPulse, long buffer[]) { static int index 0; buffer[index] currentPulse; index (index 1) % filterSize; long sum 0; for(int i0; ifilterSize; i) { sum buffer[i]; } return sum / (float)filterSize; }5. 系统优化与扩展应用5.1 提升精度的五个关键点定期轮径校准轮胎磨损会使实际直径变化建议每月用固定距离测试法校准电源稳定性编码器供电电压波动会导致脉冲波形畸变建议使用LDO稳压机械消抖在编码器轴上加装小型联轴器减少径向摆动信号滤波在编码器输出线上加100nF电容滤除高频干扰温度补偿记录不同温度下的误差特征建立补偿曲线5.2 典型应用场景扩展这套系统经过适当改造可以应用于智能仓储小车配合二维码标签实现区域定位农业机器人在温室环境中实现垄间自动行走教学实验平台用于《自动控制原理》课程的速度闭环实验智能玩具为DIY遥控车添加自动返航功能在最近一个智能花盆搬运项目中我们使用这套里程计配合简单的PID控制实现了在20平方米阳台环境下的厘米级定位精度。关键在于使用硬质橡胶轮胎减少打滑在地面粘贴辅助定位磁条每运行5分钟进行一次位置校正

更多文章