用一块Arduino输出多路PWM
由 动力老男孩 发表于 2012/07/17 22:49:47【经wwwtiger同学提醒,关于Arduino原生PWM的频率,我之前的理解是错的,应该是490Hz左右,特此更正】
周末有朋友来家里玩,看到了放在角落里的那个大的四轴飞行器。拿下来看了看,发现上面已经落满了灰尘。应该有几个月没动了,当时写的攻略目录也好久没更新了。这段时间打算抽空陆陆续续把这个页面里的目录内容都补齐,免得成为烂尾工程。可惜实验还没有成功,所以不能算是经验,各位兄弟权当教训看吧
四轴飞行器最终的控制手段,就是分别调节4个电机的转速。对于常见的无刷电机,一般通过高电平在0.9ms~2.1ms左右的PWM来控制转速。这就涉及到如何用arduino输出多路PWM的问题,在Arduino中,一般可以通过下面这些方式来输出PWM方波:
1. 用原生的PWM输出功能
把pinMode定义为输出,然后用analogWrite就可以输出PWM。以Arduino Mega 1280为例,它有14路PWM输出。analogWrite的参数范围是0~255,对应的是0~2ms的高电平。
一般情况下,原生的PWM频率固定为490Hz,通过一些参数的修改,可以提高PWM频率,但是参数范围只能是0~255。
int pin = 8; //0~13 void setup() { pinMode(pin, OUTPUT); } void loop() { analogWrite(pin, 128); delay(500); }
2. 通过普通的输出管脚手动控制PWM
PWM归根结底无非就是输出0,1序列的方波,所以我们还可以简单的通过digitalWrite和delay来生成PWM方波。
这种方式的特点是可以非常精确的控制高电平时间和PWM周期,缺点是CPU时间不好充分利用,多路时编程有点复杂。
void loop() { long t0 = micros(); //记录进入loop的时间 double T = 20000; //一个周期的微秒值 double len = 900; //高电平时间 for(int i = 0; i < 4; i++) digitalWrite(pins[i], HIGH); delayMicroseconds(len); for(int i = 0; i < 4; i++) digitalWrite(pins[i], LOW); /* *在这里干别的事情 */ int leftMs = (int) (t0 + T - micros()); //剩余时间 if(leftMs < 0 ) leftMs = 0; //万一超出周期,只能立刻中止 delayMicroseconds(leftMs); }
3. 用servo库
Servo库是Arduino用来控制伺服电机的,印象中是使用了内部中断来触发的,所以主程序只管干自己的事情,时间到了PWM就会自动触发。
它默认的频率是50Hz,但是可以在头文件中修改。文件位置是arduino-0023\libraries\Servo.h,修改下面这行可以把PWM频率升到400Hz:
#define REFRESH_INTERVAL 2500
具体的细节在之前的一篇小结里提到了:Arduino自带的Servo库小实验
先记录这些,希望在把全部的“教训”写完之前,能有空把四轴飞起来