最近在调试一个机械臂项目时,发现舵机在特定角度区间存在明显的非线性响应。这个问题直接影响了末端执行器的定位精度,于是决定专门对舵机驱动模块的线性特性进行系统性测试。所谓线性特性,指的是舵机输出角度与输入PWM信号之间的对应关系是否呈现理想的线性比例。
在实际工程中,舵机的线性度会直接影响控制系统的设计复杂度。理想情况下,给舵机发送1500μs的脉冲宽度,舵机应该精确转动到90度位置;发送2000μs脉冲则对应180度。但现实中的舵机受齿轮间隙、电位器精度、电机特性等因素影响,往往存在非线性区段。通过本次测试,我希望能够:
测试平台采用模块化设计,便于更换不同型号的舵机:
特别注意:舵机必须单独供电!直接使用Arduino的5V输出会导致板载稳压芯片过载,引发复位或控制异常。
根据舵机标称参数,有效控制脉冲宽度范围为500-2500μs,对应0-180度转动。测试点按以下原则分布:
总计形成18个测试点位,每个点位采集3组数据取平均值。
为减少人为误差,编写了自动化测试脚本(Arduino IDE):
cpp复制#include <Servo.h>
Servo testServo;
void setup() {
Serial.begin(115200);
testServo.attach(9); // 信号线接D9
}
void testCycle(int pulseWidth) {
testServo.writeMicroseconds(pulseWidth);
delay(500); // 等待舵机稳定
Serial.print("PWM=");
Serial.print(pulseWidth);
Serial.println(",READY"); // 提示用户记录角度
}
void loop() {
int testPoints[] = {500,600,700,800,900,1000,1100,1200,1300,
1400,1500,1600,1700,1800,1900,2000,2100,2500};
for(int i=0; i<18; i++){
testCycle(testPoints[i]);
delay(2000); // 留出测量时间
}
}
| PWM(μs) | 标称角度(°) | 实测角度(°) | 偏差(°) |
|---|---|---|---|
| 500 | 0 | 2.1 | +2.1 |
| 700 | 18 | 20.3 | +2.3 |
| 900 | 36 | 38.7 | +2.7 |
| 1100 | 54 | 55.2 | +1.2 |
| 1300 | 72 | 72.8 | +0.8 |
| 1500 | 90 | 90.5 | +0.5 |
| 1700 | 108 | 107.3 | -0.7 |
| 1900 | 126 | 124.1 | -1.9 |
| 2100 | 144 | 141.0 | -3.0 |
| 2300 | 162 | 157.5 | -4.5 |
| 2500 | 180 | 175.8 | -4.2 |
从数据中可以发现两个显著的非线性区:
特别值得注意的是1500μs基准点表现良好,偏差仅0.5度,说明厂家在校准时可能优先保证了中点精度。
通过微调PWM宽度(步进10μs),发现在以下区间存在明显死区:
这提示在需要高精度定位的场景,应避免将工作点设置在这些区间。
基于测试数据,可以建立PWM-角度的逆映射函数。采用三线段拟合:
cpp复制float pwmCompensate(float targetAngle) {
if(targetAngle <= 50) {
return map(targetAngle, 2.1, 38.7, 500, 900);
}
else if(targetAngle <= 130) {
return map(targetAngle, 55.2, 124.1, 1100, 1900);
}
else {
return map(targetAngle, 141.0, 175.8, 2100, 2500);
}
}
cpp复制float cubicCompensate(float angle) {
return 0.0002*pow(angle,3) - 0.022*pow(angle,2) + 11.34*angle + 492.6;
}
实测显示,采用三次多项式补偿后,整体误差可控制在±0.8度以内。
经过这次系统测试,最大的收获是认识到标称参数只能作为参考。在实际项目中,针对每批舵机进行单独校准非常必要。下次我会尝试用激光测距仪+反射镜的方案实现闭环校准,应该能得到更精确的结果。