ควบคุม servo motor 2 ตัวด้วย PWM (ATMEGA8 + WinAVR)

  • 0 Replies
  • 4384 Views
*

Offline JENG

  • *****
  • 808
  • รู้ทุกเรื่องเว้นเรื่องจริง
    • View Profile
atmega8 มี hardware pwm 3 ช่อง เอามาขับ servo ได้สองช่องโดยใช้ timer1 มีขนาด 16bit
ที่เห็นนี้คือ register ที่เกี่ยวข้องทั้งหมด ผมรวมไว้ให้ดูง่ายขึ้น


ตัวอย่างแรกควบคุมด้วยปุ่มกด
<a href="http://www.youtube.com/v/QZleo2ZOMjo" target="_blank" class="new_win">http://www.youtube.com/v/QZleo2ZOMjo</a>

Code: [Select]
//--------------------------------------------------
//Program :Control Servo motor
//Author :Somlak Mangnimit
//Date :01/02/2013
//MCU :ATmega8A
//XTAL :16Mhz
//Compiler  :WinAVR20100110
//Version   :-
//Note      :-
//--------------------------------------------------
//use analog build in library driver
#define use_analog

//my library
#include "../m8lib.c"

//define equ name
#define servo_min 1500
#define servo_max 4500

//main program
int main(void){
    unsigned int ch1,ch2;

    //configure timer 1 for fast pwm mode via ICR1, with no prescaling
    ICR1 = 0x9c3f;                               //period 20ms
    TCCR1A |= (1<<WGM11);
    TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS11);

    //enable PWM on port B1 B2 in non-inverted compare mode 2
    TCCR1A |= (1<<COM1A1)|(1<<COM1B1);

    //1ms pulse
    OCR1A = ch1 = servo_min;
    OCR1B = ch2 = servo_min;

    //set digital 9,10 as outputs
    ddr_digital_9 = output;
    ddr_digital_10 = output;

[color=red]for(;;){
        _delay_us(500);

        if(!pin_analog_1){
            if(ch1>1500){ch1--;}
            OCR1A = ch1;
        }

        else if(!pin_analog_0){
            if(ch1<4500){ch1++;}
            OCR1A = ch1;
        }

        if(!pin_analog_3){
            if(ch2>1500){ch2--;}
            OCR1B = ch2;
        }

        else if(!pin_analog_2){
            if(ch2<4500){ch2++;}
            OCR1B = ch2;
        }
}[/color]
    return 0;
}

ตัวอย่างที่สองควบคุมด้วย ADC
<a href="http://www.youtube.com/v/MFGJI3UG1nw" target="_blank" class="new_win">http://www.youtube.com/v/MFGJI3UG1nw</a>

Code: [Select]
//--------------------------------------------------
//Program :Control Servo motor
//Author :Somlak Mangnimit
//Date :26/01/2013
//MCU :ATmega8A
//XTAL :16Mhz
//Compiler  :WinAVR20100110
//Version   :-
//Note      :-
//--------------------------------------------------
//use analog build in library driver
#define use_analog

//my library
#include "../m8lib.c"

//define equ name
#define servo_min 1500
#define servo_max 4500

//main program
int main(void){
    unsigned long x;
    analog_initial();

    unsigned int ch1,ch2;

    //configure timer 1 for fast pwm mode via ICR1, with no prescaling
    ICR1 = 0x9c3f;                               //period 20ms
    TCCR1A |= (1<<WGM11);
    TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS11);

    //enable PWM on port B1 B2 in non-inverted compare mode 2
    TCCR1A |= (1<<COM1A1)|(1<<COM1B1);

    //1ms pulse
    OCR1A = ch1 = servo_min;
    OCR1B = ch2 = servo_min;

    //set digital 9,10 as outputs
    ddr_digital_9 = output;
    ddr_digital_10 = output;

for(;;){
x = analog_read(0);
OCR1A = (int)((x*(servo_max-servo_min))/1023)+servo_min;
x = analog_read(1);
OCR1B = (int)((x*(servo_max-servo_min))/1023)+servo_min;
}
    return 0;
}
สามารถติดตาม electoday ได้ที่

Facebook
www.facebook.com/groups/coopmicro

Google+
https://plus.google.com/communities/103482067769375459277

☺☺☺ความรู้ และความฉลาด ไม่ใช่สิ่งเดียวกัน จะมีประโยชน์อะไร ถ้าฉลาดแต่อยู่ในกะลา☺☺☺