AVR/AVR Servo

AVR Servo(버튼, UART)

ElectricShock 2016. 7. 4. 15:30

▼버튼기반 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);

}

}

}

//----------------------------------


http://extremeelectronics.co.in/avr-tutorials/servo-motor-control-by-using-avr-atmega32-microcontroller/

▲ATmega16용


▼UART기반 Servo 제어

http://miobot.tistory.com/34

#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