johnsonzzd 发表于 2012-11-12 17:54:05

中断方式产生高频舵机信号

本帖最后由 johnsonzzd 于 2012-11-14 21:10 编辑

arduino自带的舵机库产生的标准舵机信号频率50Hz,周期20ms。如果希望控制系统的响应速度更快,以更高的频率控制舵机或者电调之类的装置,50Hz是不够的。很多舵机和电调可以接受更高的控制频率,比如好盈电调信号频率为50-432Hz,数码舵机可以到333Hz。下面的程序用中断的方式产生244Hz舵机信号,改变设置后可以达到487Hz。
参考:http://scolton.blogspot.com/2010/07/arduino-interrupt-driven-servo-routine.html


// servo PWM value
//|-----------|-----------|
// 250         375         500
// 1ms      1.5ms      2ms
unsigned int servopwm;
const int pwm_pin=9;


void setup()
{
        Serial.begin(9600);        // opens serial port, sets data rate to 9600 bps

        cli();      // disable interrupts while messing with their settings

        // TIMER1 SETUP FOR SERVOS
        // set Timer1 to clk/64 and 10-bit fast PWM
        // this is a period of 4.1ms for 16MHz clk. 16000000/(64*(1+2^10))=243.9Hz, 4.1mm
        // 好盈电调响应频率范围50Hz—432Hz;若设为clk/64,10-bit,则487Hz,超出电调响应能力。
        // -----------------------
        // Timer 1 register: WGM12, WGM11 and WGM10 sets Fast PWM, 10-bit mode.
        //"ATmega4_88_168_328_DataSheet,Table 16-4"
        TCCR1A = 0;
        TCCR1A =_BV(WGM12) | _BV(WGM11) | _BV(WGM10);
        // Set the prescaler to 64
        TCCR1B = 0;
        TCCR1B = _BV(WGM12) | _BV(CS11) | _BV(CS10);
        // enable Timer1 compare match and overflow interrupts
        TIMSK1 =_BV(OCIE1A) | _BV(TOIE1);

        sei();       // turn interrupts back on

        pinMode(pwm_pin, OUTPUT);
}

// timer1比较中断,控制高电平脉宽。
// --------------------------
ISR(TIMER1_COMPA_vect)
{
        // interrupt on Timer1 compare match
        // (end of the servo pulse)

        digitalWrite(pwm_pin, LOW);

        // set the compare match to the new servo pulse duration
        OCR1AH = servopwm >> 8;
        OCR1AL = servopwm & 0xFF;

        return;
}

//timer1溢出中断,控制总周期
ISR(TIMER1_OVF_vect)
{
        // interrupt on Timer1 overflow
        // start of the next servo pulse

        digitalWrite(pwm_pin, HIGH);

        return;
}

void loop()
{
        static int i=250;
        Serial.println(i);

        i+=2;
        if(i<=400)
                servopwm = i;
        else
                i=250;
       
        delay(500);
}


下面是用示波器观察到的servopwm=375时产生的1.5ms脉冲


====================================================
重复造轮子了。在动力老男孩的网页上看到可以直接修改自带的舵机库达到这个目的。自带的servo库默认的频率是50Hz,但是可以在它的头文件Servo.h中修改。修改下面这行可以把PWM频率升到400Hz:
#define REFRESH_INTERVAL 2500
刷新间隔改为2.5ms,但是这时就只能容纳一个舵机的信号了。servo库也是通过上面这种中断方式实现的

yifabin023 发表于 2012-11-12 19:12:43

其实真看不懂:dizzy:

ewx_boy 发表于 2012-11-12 19:29:23

这里厉害~~~学习了~~~~

nengcai0313 发表于 2012-11-12 20:07:59

示波器很贵

xpaul 发表于 2012-11-12 20:22:27

学习学习学习

zintiger 发表于 2013-8-6 19:49:42

”刷新间隔改为2.5ms,但是这时就只能容纳一个舵机的信号了“,不太明白这就话是什么意思。如果刷新间隔改为5毫秒,是不是就可以容纳2个舵机的信号了?是芯片的速度的原因吗?

zintiger 发表于 2013-8-6 19:52:58

另外,我理解一个舵机的PWM频率应该是出厂设计好的,而不是可以随意设置的。对吗?

拾瑞 发表于 2013-8-7 08:43:24

zintiger 发表于 2013-8-6 19:49 static/image/common/back.gif
”刷新间隔改为2.5ms,但是这时就只能容纳一个舵机的信号了“,不太明白这就话是什么意思。如果刷新间隔改为 ...

20ms长度的舵信号,只有前2.5ms的各种高电平时间是控制字,后面(20-2.5)全是低电平时间!所以50HZ的舵机控制信号单次周期内,理论上可以容纳20/2.5=8个,刚刚正好......

zintiger 发表于 2013-8-11 20:57:56

拾瑞 发表于 2013-8-7 08:43 static/image/common/back.gif
20ms长度的舵信号,只有前2.5ms的各种高电平时间是控制字,后面(20-2.5)全是低电平时间!所以50HZ的舵机控 ...

谢谢。可以理解为20ms的信号周期内,高电平的时间不小于2.5ms吧。

7face 发表于 2017-5-26 09:02:06

这个厉害,刚好最近在弄舵机~
页: [1]
查看完整版本: 中断方式产生高频舵机信号