别再只让电机转!用Arduino+TB6612给编码电机做个“速度仪表盘”(附完整代码)

张开发
2026/4/19 1:58:40 15 分钟阅读

分享文章

别再只让电机转!用Arduino+TB6612给编码电机做个“速度仪表盘”(附完整代码)
用ArduinoTB6612打造编码电机速度仪表盘从脉冲计数到可视化实战当你已经能让编码电机乖乖转动时是时候给项目加点黑科技了。想象一下电机转速不再是一串冰冷的数字而是像汽车仪表盘一样实时跳动的可视化界面。这不仅是炫酷的展示更是调试闭环控制系统的重要工具。本文将带你用最常见的Arduino Uno和TB6612驱动模块实现三种不同精度的测速方案并最终构建一个OLED速度仪表盘。1. 硬件配置的艺术超越基础连接TB6612驱动模块与编码电机的组合在创客圈堪称经典CP。但要让测速系统稳定工作电源配置才是真正的隐形杀手。我曾在三个不同项目中遇到过因电源问题导致的脉冲计数异常最终发现都是同一个原因电机启停时的电压波动。优化后的供电方案使用独立12V/2A电源适配器为TB6612供电VM引脚Arduino的5V输出同时给编码器供电在电机电源输入端并联470μF电解电容0.1μF陶瓷电容组合// 推荐引脚配置基于UNO const int PWMA 5; // 电机PWM控制 const int AIN1 6; // 方向控制1 const int AIN2 7; // 方向控制2 const int STBY 8; // 使能引脚 const int ENCA 2; // 编码器A相必须接中断引脚 const int ENCB 3; // 编码器B相推荐接中断引脚提示Arduino Uno的中断引脚只有2和3这是选择编码器接口时的硬性限制。Mega2560用户则有更多选择余地。2. 测速算法的三重境界精度与性能的权衡编码器测速本质上是对脉冲边缘的计数游戏。根据捕获的边沿数量可分为三种精度等级测速模式捕获条件精度系数适用场景CPU负载单倍频仅A相上升沿1x低速高扭矩低双倍频A相上升沿和下降沿2x常规速度控制中四倍频A/B相所有边沿变化4x高速精密控制高四倍频实现代码中断服务程序核心逻辑volatile long encoderPos 0; void updateEncoder() { static uint8_t oldAB 0; oldAB 2; // 保留前次状态 oldAB | (digitalRead(ENCA) 1) | digitalRead(ENCB); switch (oldAB 0x0F) { case 0x03: case 0x06: case 0x09: case 0x0C: encoderPos; break; case 0x01: case 0x07: case 0x0E: case 0x08: encoderPos--; break; } }在测试360线编码器30:1减速比的电机时不同模式的实测数据对比单倍频理论分辨率 360×30 10,800脉冲/转双倍频实际测量 21,600脉冲/转四倍频达到 43,200脉冲/转3. 速度计算的时空魔法避免浮点抖动获取脉冲计数只是第一步将其转换为有物理意义的转速RPM才是难点。常见新手错误是直接在中断服务程序中计算速度这会导致两个问题计算耗时影响中断响应短时间采样带来的数值跳动改进的定时采样法unsigned long lastTime 0; long lastPos 0; float rpm 0; void calculateRPM() { noInterrupts(); long currentPos encoderPos; interrupts(); unsigned long now millis(); unsigned long timeElapsed now - lastTime; if (timeElapsed 100) { // 100ms采样周期 rpm (currentPos - lastPos) * 60000.0 / (pulsesPerRevolution * timeElapsed); lastPos currentPos; lastTime now; // 低通滤波系数0.1-0.3 filteredRPM 0.2 * rpm 0.8 * filteredRPM; } }注意pulsesPerRevolution需要根据实际编码器线数和测速模式计算。例如四倍频模式下360线编码器就是360×4×减速比。4. 可视化仪表盘的三种实现方案4.1 串口绘图器最快验证方案Arduino IDE内置的串口绘图器是最快捷的可视化工具只需简单输出数据void loop() { calculateRPM(); Serial.println(filteredRPM); delay(10); }优化技巧添加时间戳Serial.print(millis()); Serial.print(,); Serial.println(rpm);多曲线显示同时输出目标转速和实际转速4.2 OLED显示屏迷你仪表盘使用SSD1306 OLED屏打造实体仪表盘需要以下组件0.96寸I2C OLED屏幕U8g2库图形显示功能强大#include U8g2lib.h U8g2 oled(U8G2_R0, /* reset*/ U8X8_PIN_NONE); void setup() { oled.begin(); oled.setFont(u8g2_font_profont15_tf); } void drawDashboard(float rpm) { oled.firstPage(); do { oled.drawStr(10, 15, Motor RPM:); oled.setCursor(10, 35); oled.print(rpm, 1); oled.drawCircle(100, 20, 15, U8G2_DRAW_ALL); // 指针动画 float angle map(rpm, 0, 300, -135, 135); oled.drawLine(100, 20, 100 12*cos(angle*PI/180), 20 12*sin(angle*PI/180)); } while (oled.nextPage()); }4.3 Processing可视化专业级界面对于需要PC端复杂可视化的场景Processing可以与Arduino完美配合// Processing代码片段 import processing.serial.*; Serial myPort; float rpm; void setup() { size(400, 300); myPort new Serial(this, COM3, 57600); myPort.bufferUntil(\n); } void draw() { background(0); fill(255); text(Motor Speed: nf(rpm,1,0) RPM, 20, 50); // 绘制模拟表盘 drawDial(200, 150, 100, rpm, 0, 300); } void serialEvent(Serial p) { String inString p.readString().trim(); rpm float(inString); }5. 实战调试那些手册没告诉你的坑在实验室理想环境下测速表现良好的系统到了真实场景可能会出现各种异常。以下是几个典型问题的解决方案问题1高速时计数丢失原因中断服务程序执行时间过长解决方案简化ISR代码仅做计数使用硬件计数器如ATMega328的输入捕获单元问题2正反转识别错误典型现象反转时转速显示为正值检查清单确认A/B相接线是否正确验证编码器电源稳定性测试四倍频模式下的方向判断逻辑问题3低速时转速跳动优化策略增加采样周期500ms-1s采用滑动平均滤波改用M法测速测量固定脉冲数的时间// 改进的滤波算法示例 #define FILTER_SIZE 5 float rpmBuffer[FILTER_SIZE]; byte filterIndex 0; float applyFilter(float newValue) { rpmBuffer[filterIndex] newValue; filterIndex (filterIndex 1) % FILTER_SIZE; float sum 0; for (byte i0; iFILTER_SIZE; i) { sum rpmBuffer[i]; } return sum / FILTER_SIZE; }当我把这套系统应用在自制3D打印机送料电机上时最初的速度波动达到±15%经过上述优化后控制在±2%以内。关键发现是电机PWM频率对编码器干扰很大将TB6612的PWM频率从默认的490Hz提升到20kHz后信号质量明显改善。

更多文章