▼버튼기반 Servo 제어
http://winavr.scienceprog.com/example-avr-projects/servo-motor-control-using-avr.html
//Program code written for WinAVR toolset:
//-------------------------
#include <avr\io.h>
int main(void)
{
DDRD=0x00; //Input으로 지정 //Port D pins as input
//Enable internal pull ups
PORTD=0xFF; //High값을 Default로 지정 (풀업저항을 Vcc에 연결)
DDRB=0xFF; //Output으로 지정 //Set PORTB1 pin as output
//TOP=ICR1;
//Output compare OC1A 8 bit non inverted PWM
//Clear OC1A on Compare Match, set OC1A at TOP
//Fast PWM
//ICR1=20000 defines 50Hz PWM //Hz 그림설명 링크
//50Hz = 1/50sec = 2/100sec = 0.02sec = 20msec = 20000usec
ICR1=20000; //Input Capture Register
//2000*8 = 160000 clocks
TCCR1A|=(0<<COM1A0)|(1<<COM1A1)|(0<<COM1B0)|(0<<COM1B1)|
(0<<FOC1A)|(0<<FOC1B)|(1<<WGM11)|(0<<WGM10);
//https://gist.github.com/mkleemann/1552059
//set Fast PWM mode with ICR1 as compare rigister
//WGM11을 1로 Set
TCCR1B|=(0<<ICNC1)|(0<<ICES1)|(1<<WGM13)|(1<<WGM12)|
(0<<CS12)|(1<<CS11)|(0<<CS10);
//set Fast PWM mode with ICR1 as compare rigister
//WGM13, WGM12를 1로 set
//
//start timer with prescaler 8
for (;;)
{
if(bit_is_clear(PIND, 0))
{
//increase duty cycle
OCR1A+=10;
loop_until_bit_is_set(PIND, 0);
}
if(bit_is_clear(PIND, 1))
{
//decease duty cycle
OCR1A-=10;
loop_until_bit_is_set(PIND, 1);
}
}
}
//----------------------------------
▲ATmega16용
▼UART기반 Servo 제어
#include<stdio.h>
#include<avr/io.h>
#include<avr/interrupt.h>
#define PERIOD 1729
#define MAX 198
#define MIN 60
#define CENTER 129
volatile unsigned int p_width = 0;
volatile unsigned int duty = CENTER;
ISR(TIMER0_OVF_vect)
{
TCNT0 = 0x60; //8-bit comparator continuously compares TCNT0 and OCR0.
p_width++;
if(p_width <= duty)
PORTA |= 0x01;
else
PORTA &= ~(0x01);
if(p_width >= PERIOD)
p_width = 0;
}
void init_timer0(void)
{
TCCR0 = 0x00; //Stop
ASSR = 0x00; //set async mode
TCNT0 = 0x60; //set count start from 96 to 255+1
TCCR0 = 0x01;
TCNT0 = 0xFE;
}
static int putch_uart1(char message, FILE *stream) //4 using printf()
{
if(message == '\n')
putch_uart1('\r', stream);
while((UCSR1A & 0x20) == 0x00);
UDR1 = message;
return 0;
}
int getch_u1(void)
{
while ((UCSR1A & 0x80) == 0);
return UDR1;
}
void init_port(void)
{
PORTA = 0x00; DDRA = 0x00;
PORTB = 0x00; DDRB = 0x00;
PORTC = 0x00; DDRC = 0x00;
PORTD = 0x00; DDRD = 0x00;
PORTE = 0x00; DDRE = 0x00;
PORTF = 0x00; DDRF = 0x00;
PORTG = 0x00; DDRG = 0x00;
}
void init_uart1(void)
{
UCSR1B = 0x00;
UCSR1A = 0x00;
UCSR1B = 0x06;
UBRR1L = 0x67;
UBRR1H = 0x00;
UCSR1B = 0x18;
}
void init_devices(void)
{
cli();
init_port();
init_uart1();
init_timer0();
fdevopen(putch_uart1,0);
TIMSK = 0x01;
sei();
}
int main(void)
{
unsigned int duty_ctrl = CENTER; //90 degree
char ch;
init_devices();
DDRA = 0xFF; //PortA Output
printf("\n Servo Motor test... \n");
printf("type '<' or '>' to control servo \n");
while(1)
{
ch = getch_ul();
if((ch == '.') || (ch == '>')) duty_ctrl++;
if((ch == ',') || (ch == '>')) duty_ctrl--;
if(duty_ctrl >= MAX) duty_ctrl = MAX;
if(duty_ctrl <= MIN) duty_ctr = MIN;
duty = duty_ctrl;
printf("duty : %3d\n", duty_ctrl);
}
}
▼PWM 제어 기초자료 (Servo 제어에 필수)
http://instructables.tistory.com/474
'AVR > AVR Servo' 카테고리의 다른 글
AVR Servo(다이나믹셀) (0) | 2016.07.27 |
---|