Vous êtes sur la page 1sur 3

Controlling servo motors using AVR microcontrollers:

Servo motors works at 50 Hz. So, total time in 1 cycle would be 20ms.
Time period = 1/Frequency = 1/50Hz = 0.02 secs = 20 ms
The only way you can control your servo is by changing the dutycycle.
If 50Hz signal have:
1ms high pulse (remaining 19ms is low pulse) - servo rotates to original position
1.5ms high pulse (remaining 18.5 is low pulse) - servo rotate 90 degree
2ms high pulse (remaining 18 is low pulse) - servo rotate 180 degree
Now, Lets, first, generate 50Hz signal. I am using TIMER1 for this purpose.
I assume you are using 8Mhz crystal.
DDRD=(1<<DDD5); //for PWM always set your pin in OUTPUT mode
//please see data sheet FAST PWM mode for below two lines
TCCR1A=(1<<COM1A1)|(1<<WGM11);
TCCR1B=(1<<WGM12)|(1<<WGM13)|(1<<CS11); //prescale 8
//This line is responsible for generating 50Hz signal
ICR1=19999;
Formula is:
F_CPU/((1+OCR)*PRESCALE)
8MHz/(1+19999)*8
50Hz
Now you only need to change the duty cycle to control your servo. Use OCR1A pin:
for example if I want to rotate my servo 180 degree. I need 2ms high pulse
That means if 19999 ~ 20000 is total time
OCR1A = 20000 //would give me high pulse for 20ms

I need it only for 2ms use UNITARY METHOD that you have learnt in lower grades
20ms is 20000
1ms is 20000/20 = 1000
1.5ms is 1000*1.5 = 1500
2ms is 1000*2 = 2000
SO, if OCR1A = 1000; //my servo comes back to original position
if OCR1A = 1500; //it rotates 90 degree
if OCR1A = 2000; //it rotates 180 degree
FINALLY, one complete example:
#define F_CPU 8000000UL
#include<avr/io.h>
#include<avr/interrupt.h>
#include<util/delay.h>
int main()
{
DDRD=(1<<DDD5);
TCCR1A=(1<<COM1A1)|(1<<WGM11);
TCCR1B=(1<<WGM12)|(1<<WGM13)|(1<<CS11);
ICR1=19999;
while(1)
{
OCR1A = 1500; //rotate 90
_delay_ms(500); //wait for 500ms
OCR1A = 2000; //rotate 180 from original position not from above position
_delay_ms(500);
OCR1A = 1000; //come back to original position
_delay_ms(500);
}
return 0;

Vous aimerez peut-être aussi