ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用N20减速电机DIY舵机:从PID控制到磁编码器应用实战

用N20减速电机DIY舵机:从PID控制到磁编码器应用实战 最近在做一个需要精确角度控制的小项目原本打算用标准舵机但手头正好有几个闲置的N20减速电机。标准舵机虽然方便但扭矩、速度、尺寸都固定了想定制化就得花大价钱。于是萌生了一个想法能不能用N20减速电机配合简单的电路和代码自己“攒”出一个舵机来说干就干折腾一番后效果还不错成功实现了角度闭环控制。不过过程中也发现N20电机的输出轴普遍偏短安装联轴器或舵盘时有点捉襟见肘不禁感慨“这电机轴能再长点就好了”本文将完整分享这次DIY舵机的全过程从核心原理、硬件选型、电路搭建到Arduino代码编写、PID参数整定最后还会探讨优化空间和常见问题。无论你是电子爱好者、学生做课设还是创客想自制机械臂关节这篇实战笔记都能提供一套可行的闭环解决方案。1. 舵机原理与N20电机改造可行性分析在开始动手之前我们必须搞清楚标准舵机是如何工作的以及我们自制的系统需要实现哪些功能。1.1 标准舵机的工作原理舵机Servo是一种位置角度伺服的驱动器它内部是一个闭环控制系统。其核心组件通常包括直流电机提供动力。减速齿轮组将电机的高转速、低扭矩转换为低转速、高扭矩这正是N20电机的特性。电位器或编码器作为位置传感器实时反馈输出轴的角度。控制电路板核心是一个简单的控制器过去常是模拟电路现在多是MCU它接收外部的控制信号读取电位器的反馈值通过比较两者差异来驱动电机正转或反转直到输出轴到达指定位置。外部通过PWM脉冲宽度调制信号进行控制。常见的舵机控制信号是周期为20ms频率50Hz的脉冲其高电平的宽度脉宽决定了目标角度。例如0.5ms脉宽对应0度1.5ms对应90度2.5ms对应180度。这是一种开环指令但舵机内部通过电位器实现了闭环。1.2 为什么选择N20减速电机N20电机是一种微型直流减速电机其特点非常鲜明优点体积小巧、价格低廉、规格多样有多种减速比和电压可选、自带减速箱输出扭矩较大。缺点输出轴短通常只有4-6mm、不带位置反馈、需要外部驱动电路。我们的目标就是为N20电机加上“眼睛”位置传感器和“大脑”控制器让它能像舵机一样根据PWM指令精确地走到指定角度并保持。这本质上是一个位置闭环伺服系统的项目。1.3 系统总体方案设计自制舵机系统需要三大模块执行机构N20减速电机。我们需要选择一个合适的减速比。减速比越大输出扭矩越大转速越慢定位可能更平稳但响应也慢。对于舵机应用通常选择100:1到300:1之间的型号。本次演示使用一个6V减速比约为298:1的N20电机。位置反馈这是实现闭环的关键。有几种方案电位器最经典、成本最低的方案但存在机械磨损和分辨率限制。磁编码器如AS5600非接触式测量寿命长、精度高是当前DIY高性能舵机的热门选择。光电编码器精度高但安装相对复杂。 考虑到易用性和精度本项目选用AS5600磁编码器。它通过I2C通信可以轻松读取绝对角度。控制核心负责接收PWM指令、读取当前位置、计算误差并驱动电机。我们可以使用Arduino Uno/Nano入门首选资源丰富。树莓派Pico性能更强双核价格有优势更适合多舵机控制。 本文将以最普及的Arduino Nano为例进行讲解代码原理同样适用于Pico。2. 硬件准备与电路连接2.1 所需材料清单组件型号/规格数量说明主控板Arduino Nano1或其他Arduino兼容板减速电机N20 (6V, 减速比~298:1)1核心执行器位置传感器AS5600磁编码器模块1提供角度反馈电机驱动DRV8833双H桥模块1或L298N、TB6612等电源5V-6V直流电源1为电机和Arduino供电磁铁径向磁化圆片磁铁1需安装在电机轴上结构件联轴器、支架、螺丝若干用于固定电机和磁铁连接线杜邦线公对公、公对母若干用于电路连接重要提醒N20电机轴很短选择联轴器时务必注意其夹持长度和孔径是否匹配。这是整个项目在机械上最大的挑战。2.2 电路接线图与说明整个系统的信号流是PWM指令 - Arduino - 电机驱动 - N20电机 - 磁编码器 - Arduino形成一个闭环。以下是详细的接线表Arduino Nano引脚连接目标功能D2外部PWM信号线如接收机输入接收标准舵机控制信号A4 (SDA)AS5600模块的SDAI2C数据线读取角度A5 (SCL)AS5600模块的SCLI2C时钟线D5DRV8833模块的AIN1控制电机方向/速度D6DRV8833模块的AIN2控制电机方向/速度5VAS5600模块的VCC, DRV8833模块的VCC (逻辑部分)提供5V逻辑电源GNDAS5600模块的GND, DRV8833模块的GND, 外部电源GND共地非常重要DRV8833模块连接目标AOUT1, AOUT2连接到N20电机的两个电极VM连接到外部6V电源正极为电机供电GND连接到外部电源负极并与Arduino GND相连AS5600模块连接目标VCCArduino 5VGNDArduino GNDSDAArduino A4SCLArduino A5电源注意事项务必使用独立电源为电机供电或者使用足以提供电机堵转电流的电源。电机启动瞬间电流很大可能拉低Arduino电压导致复位。所有模块的GND必须连接在一起即电源地、Arduino地、驱动板地、编码器地要共地这是电路正常工作的基础。3. 核心代码实现与PID控制硬件连接好后大脑程序是关键。我们需要完成三件事1. 解析外部PWM信号2. 读取当前角度3. 根据角度差驱动电机。3.1 读取标准舵机PWM信号标准舵机信号是周期20ms的PWM我们需要测量其高电平的脉宽。使用Arduino的pulseIn()函数可以轻松实现。// 定义PWM信号输入引脚 const int pwmInputPin 2; unsigned long readServoPulseWidth() { // 读取高电平脉冲宽度单位微秒(us)超时设置为25000us(25ms) unsigned long pulseWidth pulseIn(pwmInputPin, HIGH, 25000); // 将异常值限制在合理范围500us - 2500us pulseWidth constrain(pulseWidth, 500, 2500); return pulseWidth; }3.2 读取AS5600磁编码器角度AS5600库简化了操作。首先需要在Arduino IDE中安装Adafruit_AS5600库。#include Adafruit_AS5600.h Adafruit_AS5600 as5600; void setup() { Serial.begin(115200); if (!as5600.begin()) { Serial.println(无法找到AS5600传感器请检查接线); while (1); } } float getCurrentAngle() { // 读取原始角度值0-4095对应0-360度 int rawAngle as5600.readAngle(); // 转换为角度值0.0 - 360.0 float angle (rawAngle * 360.0) / 4096.0; return angle; }3.3 将PWM脉宽转换为目标角度我们需要将读取到的脉宽例如1000us映射到我们的舵机运动范围。假设我们希望自制舵机有180度的运动范围。// 定义PWM脉宽范围和你希望舵机运动的角度范围 const int pwmMin 500; // 对应0度 const int pwmMax 2500; // 对应180度 const float angleMin 0.0; const float angleMax 180.0; float pulseWidthToAngle(unsigned long pulseWidth) { // 使用map函数进行线性映射再转换为浮点数以提高精度 float targetAngle map(pulseWidth, pwmMin, pwmMax, angleMin * 100, angleMax * 100) / 100.0; return targetAngle; }3.4 实现PID控制驱动电机这是最核心的部分。PID控制器根据“目标角度”和“当前角度”的误差计算出一个控制量来驱动电机。我们使用简单的P比例控制先实现功能再加入I积分和D微分来优化性能。// 电机驱动引脚 const int motorPin1 5; const int motorPin2 6; // PID参数 float Kp 1.5; // 比例系数决定响应速度太大易震荡 float Ki 0.05; // 积分系数消除静态误差 float Kd 0.2; // 微分系数抑制超调 float integral 0; float previousError 0; // 电机驱动函数 void driveMotor(int speed) { // speed范围-255 到 255。负值反转正值正转0停止。 speed constrain(speed, -255, 255); if (speed 0) { analogWrite(motorPin1, speed); analogWrite(motorPin2, 0); } else if (speed 0) { analogWrite(motorPin1, 0); analogWrite(motorPin2, -speed); } else { analogWrite(motorPin1, 0); analogWrite(motorPin2, 0); } } void pidControl(float targetAngle, float currentAngle) { // 1. 计算误差 float error targetAngle - currentAngle; // 处理角度跨越360度/0度边界的问题例如目标5度当前355度实际误差是10度 if (error 180) error - 360; else if (error -180) error 360; // 2. PID计算 integral error; // 积分限幅防止积分饱和 integral constrain(integral, -100, 100); float derivative error - previousError; float output Kp * error Ki * integral Kd * derivative; previousError error; // 3. 输出到电机 int motorSpeed (int)output; driveMotor(motorSpeed); }3.5 完整主程序逻辑将以上所有部分组合起来并在loop()中循环执行。#include Adafruit_AS5600.h Adafruit_AS5600 as5600; // 引脚定义和变量声明同上此处省略 // ... void setup() { Serial.begin(115200); // 初始化编码器 if (!as5600.begin()) { Serial.println(AS5600初始化失败); while (1); } // 设置电机驱动引脚为输出 pinMode(motorPin1, OUTPUT); pinMode(motorPin2, OUTPUT); // 设置PWM输入引脚为输入 pinMode(pwmInputPin, INPUT); Serial.println(系统初始化完成等待PWM信号...); } void loop() { // 1. 读取目标PWM信号并转换为角度 unsigned long pulse readServoPulseWidth(); float targetAngle pulseWidthToAngle(pulse); // 2. 读取当前角度 float currentAngle getCurrentAngle(); // 3. 在串口监视器显示用于调试 Serial.print(目标: ); Serial.print(targetAngle); Serial.print(度, 当前: ); Serial.print(currentAngle); Serial.print(度, 误差: ); Serial.print(targetAngle - currentAngle); Serial.println(度); // 4. 执行PID控制 pidControl(targetAngle, currentAngle); // 5. 短暂延时控制循环频率 delay(10); // 约100Hz的更新频率 }将代码上传到Arduino后打开串口监视器波特率115200然后给D2引脚输入一个标准的舵机PWM信号可以用另一个Arduino生成或者用舵机测试器就能看到角度反馈和误差信息电机应该会开始运动并尝试对准目标角度。4. 调试技巧与PID参数整定上传代码后电机可能不动或者疯狂震荡这都需要调试。4.1 基础排查检查供电电机是否供电所有GND是否共地检查信号用pulseIn读取的脉宽值是否在500-2500us之间正常变化可以在setup里只读PWM并打印排除信号问题。检查编码器磁铁是否靠近AS5600芯片距离1-2mm为宜能否读到变化的角度值可以单独写个程序只读角度并打印。检查电机驱动将driveMotor函数写死一个速度值如driveMotor(100)看电机能否单向转动。4.2 PID参数整定“调参”这是让系统稳定、快速、准确的关键。遵循先P再I最后D的原则。初始化将Ki和Kd设为0Kp设为一个较小的值如0.5。调P比例给系统一个固定的目标角度比如90度。观察电机行为。如果完全不动或非常慢缓慢增大Kp。电机会开始向目标运动。如果到达目标后在目标点附近来回震荡“发抖”说明Kp太大了需要稍微减小。目标是找到一个Kp让电机能较快地到达目标附近且只有轻微抖动或刚好不抖。此时系统可能有“静差”始终差一点到不了目标。调I积分加入一个很小的Ki如0.01。积分的作用是累积误差可以消除静差。观察之前差的那一点角度是否被补上了。如果系统开始出现缓慢的周期性震荡说明Ki太大了需要减小。积分太强会导致系统“反应迟钝”然后“矫枉过正”。调D微分微分能预测误差变化趋势抑制超调和震荡。在P和I调好的基础上加入一个小的Kd如0.1。观察电机到达目标的过程是否更“柔和”、更“干脆”抖动是否进一步减小。Kd对噪声敏感如果AS5600读数有跳动过大的Kd反而会引起高频抖动。调试心得对于N20减速电机这种大减速比、有一定惯性的系统Kp不需要很大Ki可以适当给一点以消除齿轮间隙带来的死区误差Kd能有效让运动停下来时更稳。我的一个参考参数是Kp1.5, Ki0.05, Kd0.2但你的电机、负载、机械结构不同参数会差异很大必须亲手调试。5. 机械安装要点与轴长问题优化电路和代码调通了机械部分是最后一道坎也是本项目最大的痛点。5.1 磁铁安装AS5600需要检测磁场变化。必须将径向磁化的圆片磁铁牢固地安装在电机输出轴上且磁铁中心与AS5600芯片中心对准。磁铁与芯片表面的距离建议在1-3mm以内。可以使用热熔胶或专用的磁铁座固定。确保磁铁在旋转时不会碰到芯片。5.2 “电机轴太短”的解决方案这是文章标题里吐槽的核心问题。标准N20电机轴长约4-6mm安装联轴器、磁铁、舵盘非常困难。寻找长轴版N20电机有些厂家提供“加长轴”版本的N20电机轴长可能达到10mm这是最根本的解决方案。使用超薄联轴器或定制零件寻找夹持长度更短的联轴器。或者用3D打印一个套筒一端紧配套在电机轴上另一端提供更长的安装界面。改变安装思路不一定要把磁铁或负载直接装在电机轴上。可以设计一个支架将电机和编码器平行放置通过同步带或齿轮传动。这样电机轴只连接一个小齿轮对轴长要求降低还能进一步减速或改变传动比。5.3 结构刚性自制舵机往往用于机械臂等场合需要承受一定的侧向力。务必确保电机被牢固地安装在支架或底板上避免晃动否则会影响定位精度和寿命。6. 进阶优化与扩展思路基础功能实现后可以考虑以下优化让这个自制舵机更强大、更可靠。6.1 软件优化滤波给AS5600读取的角度值添加一个低通滤波器如一阶互补滤波可以平滑读数减少抖动让Kd参数更好用。float filteredAngle 0.9 * filteredAngle 0.1 * currentRawAngle;死区补偿齿轮存在回差背隙当电机换向时需要先走过一段空程。可以在PID输出很小时给一个固定的最小驱动电压来“顶住”齿轮消除晃动。运动曲线规划不让电机直接冲向目标而是规划一条速度曲线如S型曲线让启停更平滑减少对齿轮的冲击。6.2 硬件优化使用树莓派PicoPico有更快的CPU和更多的PWM通道非常适合同时控制多个这样的自制舵机且成本低廉。升级编码器AS5600是12位分辨率4096步。如果需要更高精度可以考虑14位或16位的绝对式编码器。升级电机驱动DRV8833电流较小约1.5A。如果使用更大功率的N20电机或负载较重可以换用TB6612、BTN7971等驱动芯片。6.3 扩展应用串行总线控制放弃PWM输入改用串口UART或I2C接收角度指令。这样可以方便地由主控板如STM32、Pico通过一条总线控制多个关节。力矩控制通过测量电机电流需要电流采样芯片可以估算输出扭矩实现简单的力矩控制让机械臂更柔顺。集成到ROS为这个自制舵机编写一个ROS节点发布其关节状态订阅目标角度话题可以轻松地将其融入机器人操作系统。7. 常见问题与故障排除问题现象可能原因排查与解决电机完全不动1. 电源未接通或电压不足。2. 电机驱动模块使能端未接。3. Arduino与驱动板控制线接错。4. PID参数Kp太小或误差计算有误。1. 检查电源电压用万用表测量电机两端电压。2. 查阅驱动板手册确保使能引脚接高电平。3. 写一个简单测试程序让两个控制引脚输出固定PWM看电机是否转动。4. 在串口打印目标角度和当前角度确认误差值是否正常。电机单向持续旋转1. 编码器接线错误或损坏反馈角度值不变。2. 磁铁未安装或距离太远编码器读数无效。3. PID输出极性反了。1. 检查I2C接线运行AS5600示例代码确认能否读到变化的角度。2. 调整磁铁与编码器的距离和角度。3. 尝试将PID输出乘以-1或者交换电机驱动两根线的极性。电机在目标点剧烈震荡1.Kp参数过大。2. 机械结构松动有较大间隙。3.Kd参数为0或太小无法抑制超调。1. 大幅降低Kp值重新调试。2. 紧固所有螺丝和连接件。3. 适当增加Kd值。电机响应迟钝有静差1.Kp参数过小。2. 未加入积分项Ki或Ki太小。3. 电机扭矩不足带不动负载。1. 缓慢增大Kp。2. 加入一个较小的Ki值。3. 换用更高扭矩的电机或降低负载。角度读数跳动大1. 磁铁安装不牢固或偏心旋转时距离变化。2. I2C总线受到电机干扰。3. 电源噪声大。1. 重新固定磁铁确保其与编码器平行且距离恒定。2. 给电机电源并联一个大电容如100uF电解电容并在I2C数据线上加上拉电阻通常模块已集成。3. 为Arduino和编码器使用独立的线性稳压电源与电机电源分离。通过这个项目我们不仅得到了一个可用的自制舵机更重要的是深入理解了位置闭环伺服系统的工作原理。从PWM信号解析、传感器数据采集到PID算法实现和调试每一步都是对嵌入式控制和机电一体化的实践。虽然N20电机轴短的缺点的确带来了安装上的麻烦但通过灵活的机械设计总能找到解决办法。这种自制的舵机在成本、扭矩和尺寸上都有自定义的优势非常适合在机器人、模型改造等创客项目中应用。希望这篇详细的教程能帮助你成功复现并改进这个项目。
返回列表