Electoday 4.0

ไมโครคอนโทรลเลอร์ => AVR and Arduino => Topic started by: JENG on February 01, 2013, 10:31:36 pm

Title: ควบคุม servo motor 2 ตัวด้วย PWM (ATMEGA8 + WinAVR)
Post by: JENG on February 01, 2013, 10:31:36 pm
atmega8 มี hardware pwm 3 ช่อง เอามาขับ servo ได้สองช่องโดยใช้ timer1 มีขนาด 16bit
ที่เห็นนี้คือ register ที่เกี่ยวข้องทั้งหมด ผมรวมไว้ให้ดูง่ายขึ้น
(http://image.free.in.th/z/iq/bcpwm.jpg) (http://pic.free.in.th/id/2349358e7f2e5e1cd3975e92b0960d3a)

ตัวอย่างแรกควบคุมด้วยปุ่มกด
http://www.youtube.com/v/QZleo2ZOMjo

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
http://www.youtube.com/v/MFGJI3UG1nw

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;
}