«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

ITGenerations

[avr]서보모터+LCD 본문

Univ/AVR atmega128

[avr]서보모터+LCD

ITGenerations 2017. 12. 10. 00:43

// source 30

//서보모터+LCD 

// 오렌지=PWM-> PB5번 연결 


#include <avr/interrupt.h> 

#include <avr/io.h> // I/O 레지스터정의

#include <util/delay.h> // 시간지연함수 

#include <string.h>

#include "lcd.h" // LCD 제어프로그램 헤더파일

#include "rcservo.h"



#define DEBOUNCING_DELAY 20

#define MAX_ANGLE 90

#define MIN_ANGLE -90


float degree = 0;

unsigned short on_width[3]={NEUTRAL_WIDTH, NEUTRAL_WIDTH, NEUTRAL_WIDTH}; // 중립일 때의 펄스폭

char string[20]; // 문자열을 구성할 배열

 

void msec_delay(int n); // 시간지연함수

static char lcdtitle[] = "ANGLE:"; // 실습 제목


void set_angle(int n, float angle)

{

on_width[n] = (unsigned short)(-100.f * angle / 9.f + 1500.f);// +- 90degree일 때의 수식

}


ISR(INT0_vect) // + 5 deg

{

TIMSK &= ~(1 << OCIE2);

msec_delay(DEBOUNCING_DELAY);

while (~PIND & 0x01);

msec_delay(DEBOUNCING_DELAY);


degree += 5.f;// data를 10 증가한다.

if (degree > MAX_ANGLE)

degree = MAX_ANGLE;


set_angle(0, degree);

RCServoSetOnWidth(on_width);

LcdMove(1,0); // HOME

sprintf(string,"%d        ", (int)degree);

LcdPuts(string);


EIFR = (1 << INTF0);


}

ISR(INT1_vect) // -5 deg

{

TIMSK &= ~(1 << OCIE2);

msec_delay(DEBOUNCING_DELAY);

while (~PIND & 0x02);

msec_delay(DEBOUNCING_DELAY);


degree -= 5.f ;// data reset

if (degree <  MIN_ANGLE)

degree = MIN_ANGLE;


set_angle(0, degree);

RCServoSetOnWidth(on_width);

LcdMove(1,0); // HOME

sprintf(string,"%d        ", (int)degree);

LcdPuts(string);

EIFR = (1 << INTF1);

}



ISR(INT2_vect) // Auto Mode Setting

{

if (TIMSK & (1 << OCIE2))

{

TIMSK &= ~(1 << OCIE2);

}

else

{

TIMSK |= (1 << OCIE2);

}

msec_delay(DEBOUNCING_DELAY);

while (~PIND & 0x04);

msec_delay(DEBOUNCING_DELAY);


EIFR = (1 << INTF2);

}



ISR(TIMER2_COMP_vect) // Auto Mode

{

static int n_enter2 = 0;

static int direction = 1; // 1: + direction, -1: - direction

n_enter2+=50;

if (n_enter2 == 50) // 100 msec 

{

n_enter2 = 0;

if (direction> 0)

{

degree+= 5.f;

if (degree > MAX_ANGLE)

{

direction =  -1;

degree = MAX_ANGLE;

}

set_angle(0, degree);

}

else

{

degree-= 5.f;

if (degree < MIN_ANGLE)

{

direction = 1;

degree = MIN_ANGLE;

}

set_angle(0, degree);

}

RCServoSetOnWidth(on_width);

LcdMove(1,0); // HOME

sprintf(string,"%d        ", (int)degree);

LcdPuts(string);

}

}



int main()

{

char i;

degree = 0.f;


LcdInit(); // LCD 초기화

RCServoInit(20000); // 20ms PWM Period

LcdMove(0,0); // HOME

LcdPuts(lcdtitle); // 실습 제목을 쓴다.


LcdMove(1,0);

sprintf(string,"%d        ", (int)degree);

LcdPuts(string); // SRAM내의 문자열 출력


/////////////////////////// Switch ////////////////

SFIOR &= ~(1 << PUD); // PUD는 io.h에 정의되어 있음.

PORTD |= (1 << PD0) | (1 << PD1) | (1 << PD2); // Switch로 사용할 PD0와 PD1을 출력으로 설정.


EICRA = (1 << ISC21) | (1 << ISC11) | (1 << ISC01); // Interrupt 1과 0을 하강모서리 트리거 (교재 p110)


EIMSK |= (1 << INT0) | (1 << INT1) | (1 << INT2);


TCCR2 = (1 << WGM01) | (0<WGM00) | (1 << COM00) | (1 << CS02) | (0 << CS01) | (1 << CS00);

TCNT2 = 0x00;

OCR2 = 0x9C;

TIMSK |= (1 << OCIE2);



sei(); // 전역 인터럽트 허용.



while(1);

}


// 시간지연함수

//////////////////////////////////////////

void msec_delay(int n)

{

for(; n >0; n--)  // 1msec 시간지연을 n회 반복

_delay_ms(1); // 1msec 시간지연

}