之前有很多朋友问过我,为什么不用Arduino自带的Servo库来控制电机。我在动手做四轴之前,其实也大概看了下Servo库的说明,当时看到
servo.write(angle) 这个函数,其中angle(int)是角度,取值范围是0 到 180
我想当然的认为,这个servo库最多也就是180级的梯度来设置PWM,这样说来精度完全不够啊;另外也没有看到有地方能修改PWM频率。
总结了下我当时不用Servo库的原因:
1. 控制的级数太少,不够精确;
2. 不可修改PWM频率;
3. 需要使用特殊的几个脚;(不知道在什么地方看错了,留下的错误印象)
这几天obK仔给了很多建议,我也看了看源代码。现在看来,上面这几点都是我瞎操心了。
首先,0~180是servo库对应的从min到max的控制,对应于0.9ms到2.1ms的电调来说,angle参数加1对应的时间变化为:
(2.1-0.9)*1000/180 = 6.7微秒,已经是比较精确了。
即使这样如果还觉得不够精确,还可以使用servo.writeMicroseconds,这个函数可以直接用微秒作为参数。
其次,PWM频率是可以修改的,在Servo.h文件中,修改下面这行可以把PWM频率升到400Hz:
#define REFRESH_INTERVAL 2500
不过这只能在编译之前改,不能在程序运行的过程中动态修改。当然修改源代码也可以解决这个问题,把这个参数做成一个变量,用接口进行修改控制即可。
最后,Servo库可以绑定所有digitalWrite的脚,这一点来说,比原生的PWM还方便!
做了一个简单的小程序,测试Servo库同时控制4个电机的情况。实验结果看上去还不错,不过没有测试4个电机转速各不相同的情况。
代码果然看上去简洁多了:
Servo powerServo[4]; void setup() { motorPins[0] = 38; //x1 motorPins[1] = 43; //x2 motorPins[2] = 42; //y1 motorPins[3] = 39; //y2 for(int i = 0; i < 4; i++) powerServo.attach(motorPins[i]); } void loop() { long t0 = micros(); //记录进入loop的时间 while(Serial.available()) { // 这里是获取控制指令 pushData(Serial.read()); } double T = 2500; // 一个周期的微秒值 double len = 900 + ctrlPower * 5; //(0~200对应总周期0.9ms~1.9ms) for(int i = 0; i < 4; i++) powerServo[i].writeMicroseconds(len); int leftMs = (int) (t0 + T - micros()); delayMicroseconds(leftMs);
原文地址:http://www.guokr.com/blog/127438/