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