[교통정리로봇] 프로젝트 문서 4. 구현(세번째)
(2) AVR 구현
project.c (AVR) |
#include <mega128.h> #include <delay.h>
void motor_mode1(); // 모터 제어 첫번째 모드(좌우) void motor_mode2(); // 모터 제어 두 번째 모드(앞뒤) void motor_autocontrol(); // 모터 자동 제어 모드 void motor_reset(); // 처음 상태로 변환
char ch[30] = {0}; int ch_num = 0; int ex = 0; typedef unsigned char byte; unsigned int tim0_cnt, mot_pos, change; unsigned int rc_time[2] = {130,180}; /* 0도 = 60; 90도 = 150; 180도 = 240; */
void motor_mode1() // 모터 제어 첫번째 모드(좌우) { motor_reset(); // 원래 자리로 이동
PORTA = 0x00; DDRA = 0x37; // PA0, PA1, PA2 사용 // PA4, PA5 사용 /* PA0 = 왼팔 팔꿈치(0X01) PA1 = 왼팔 팔 옆으로 벌리기(0X02) PA2 = 왼팔 팔 앞으로 벌리기(0X04) PA4 = 오른팔 팔꿈치(0X10) PA5 = 오른팔 옆으로 벌리기(0X20) */
tim0_cnt = 0; // 타이머/카운터0 오버플로우 횟수 리셋 mot_pos = 0; // 모터 위치 0도 change = 0; // 각도 변화 주기 리셋
// 타이머/카운터 0 ㅇ인터럽트 주기 // 이론치 (256-241) * 8분주 * 1/16us = 7us 약 10us TIMSK = 0x01; // TIOIE0= 1; TCCR0 = 0x02; // 일반 모드 , 프리스케일 = CK/8 TCNT0 = 238; // 타이머/카운터0 레지스터 초기값 SREG = 0x80; // 전역 인터럽트 인에이블 비트 I 셋
PORTA = 0xFF; // 모터 HIGH 출력
|
project.c (AVR) |
tim0_cnt = 0; ex = 0; while(ex < 100) { if(tim0_cnt >= 2000) // 10us * 2000 = 20ms 주기 체크 { tim0_cnt = 0; PORTA = 0x32; // 팔꿈치 이동, 양 팔 옆으로 change++;
// 20ms * 20 = 0.4sec 각도 변화 주기 체크 if(change == 20) { mot_pos = (mot_pos + 1) % 2; change = 0; ex++; if(UCSR0A & 0x80) { ch[ch_num] = UDR0; ch_num++; } } } if(mot_pos == 0 && tim0_cnt >= rc_time[mot_pos]) // 모터 Low 출력 { if(tim0_cnt >= 150) { PORTA = 0x00; } else { PORTA = 0x22; } } if(mot_pos == 1 && tim0_cnt >= 150) // 모터 Low 출력 { if(tim0_cnt >= rc_time[mot_pos]) { PORTA = 0x00; } else { PORTA = 0x10; } }
}
} |
project.c (AVR) |
void motor_mode2() // 모터 제어 두 번째 모드(앞뒤) { motor_reset();
PORTA = 0x00; DDRA = 0x37; // PA0, PA1, PA2 사용 // PA4, PA5 사용 /* PA0 = 왼팔 팔꿈치(0X01) PA1 = 왼팔 팔 옆으로 벌리기(0X02) PA2 = 왼팔 팔 앞으로 벌리기(0X04) PA4 = 오른팔 팔꿈치(0X10) PA5 = 오른팔 옆으로 벌리기(0X20) */ tim0_cnt = 0; // 타이머/카운터0 오버플로우 횟수 리셋 mot_pos = 0; // 모터 위치 0도 change = 0; // 각도 변화 주기 리셋
// 타이머/카운터 0 ㅇ인터럽트 주기 // 이론치 (256-241) * 8분주 * 1/16us = 7us 약 10us TIMSK = 0x01; // TIOIE0= 1; TCCR0 = 0x02; // 일반 모드 , 프리스케일 = CK/8 TCNT0 = 238; // 타이머/카운터0 레지스터 초기값 SREG = 0x80; // 전역 인터럽트 인에이블 비트 I 셋
tim0_cnt = 0; PORTA = 0xFF; // 모터 HIGH 출력 ex = 0; while(ex < 3) { if(tim0_cnt >= 2000) // 10us * 2000 = 20ms 주기 체크 { tim0_cnt = 0; PORTA = 0x04; // 왼팔 앞으로 change++;
// 20ms * 20 = 0.4sec 각도 변화 주기 체크 if(change == 20) { change = 0; ex++; if(UCSR0A & 0x80) { ch[ch_num] = UDR0; ch_num++; } } } if(tim0_cnt >= 170) // 모터 Low 출력 { PORTA = 0x00; } } |
project.c (AVR) |
tim0_cnt = 0; ex = 0; while(ex < 100) { if(tim0_cnt >= 2000) // 10us * 2000 = 20ms 주기 체크 { tim0_cnt = 0; PORTA = 0x23; // 팔꿈치 이동, 양팔 옆으로 change++;
// 20ms * 20 = 0.4sec 각도 변화 주기 체크 if(change == 20) { mot_pos = (mot_pos + 1) % 2; change = 0; ex++; if(UCSR0A & 0x80) { ch[ch_num] = UDR0; ch_num++; } } } if(mot_pos == 0 && tim0_cnt >= rc_time[mot_pos]) // 모터 Low 출력 { if(tim0_cnt >= 150) { PORTA = 0x00; } else { PORTA = 0x22; } } if(mot_pos == 1 && tim0_cnt >= 150) // 모터 Low 출력 { if(tim0_cnt >= rc_time[mot_pos]) { PORTA = 0x00; } else { PORTA = 0x01; } } }
} |
project.c (AVR) |
void motor_reset() // 처음 상태로 변환 {
PORTA = 0x00; DDRA = 0x37; // PA0, PA1, PA2 사용 // PA4, PA5 사용 /* PA0 = 왼팔 팔꿈치(0X01) PA1 = 왼팔 팔 옆으로 벌리기(0X02) PA2 = 왼팔 팔 앞으로 벌리기(0X04) PA4 = 오른팔 팔꿈치(0X10) PA5 = 오른팔 옆으로 벌리기(0X20) */
tim0_cnt = 0; // 타이머/카운터0 오버플로우 횟수 리셋 mot_pos = 0; // 모터 위치 0도 change = 0; // 각도 변화 주기 리셋
// 타이머/카운터 0 ㅇ인터럽트 주기 // 이론치 (256-241) * 8분주 * 1/16us = 7us 약 10us TIMSK = 0x01; // TIOIE0= 1; TCCR0 = 0x02; // 일반 모드 , 프리스케일 = CK/8 TCNT0 = 238; // 타이머/카운터0 레지스터 초기값 SREG = 0x80; // 전역 인터럽트 인에이블 비트 I 셋
tim0_cnt = 0; PORTA = 0xFF; // 모터 HIGH 출력 ex = 0; while(ex < 2) { if(tim0_cnt >= 2000) // 10us * 2000 = 20ms 주기 체크 { tim0_cnt = 0; PORTA = 0x03; // 왼팔 팔꿈치, 왼팔 옆으로 change++;
// 20ms * 20 = 0.4sec 각도 변화 주기 체크 if(change == 20) { change = 0; ex++; if(UCSR0A & 0x80) { ch[ch_num] = UDR0; ch_num++; } } } if(tim0_cnt >= 60) // 모터 Low 출력 { PORTA = 0x00; } } |
project.c (AVR) |
ex = 0; tim0_cnt = 0; while(ex < 2) { if(tim0_cnt >= 2000) // 10us * 2000 = 20ms 주기 체크 { tim0_cnt = 0; PORTA = 0x34; // 왼팔 앞으로, 오른팔 옆으로, 오른팔 팔꿈치 change++;
// 20ms * 20 = 0.4sec 각도 변화 주기 체크 if(change == 20) { change = 0; ex++; if(UCSR0A & 0x80) { ch[ch_num] = UDR0; ch_num++; } } } if(tim0_cnt >= 250) // 모터 Low 출력 { PORTA = 0x00; } } }
void motor_autocontrol() // 모터 자동 제어 모드 { int i; int exit = 1; while(exit) { motor_mode1(); motor_reset(); for(i = 0; i < ch_num; i++) { if(ch[i] == 'x' || ch[i] == 'X') { exit = 0; } } if(exit == 1) { motor_mode2(); motor_reset(); } for(i = 0; i < ch_num; i++) { if(ch[i] == 'x' || ch[i] == 'X') { exit = 0; } } } for(i = 0; i < ch_num; i++) { ch[i] = 0; } ch_num = 0; } |
project.c (AVR) |
interrupt [TIM0_OVF] void timer_int0(void) { tim0_cnt++; TCNT0 = 238; }
void main() {
int i;
DDRA = 0x00; // PORT A를 모터 제어 포트로 사용 PORTA = 0x00;
SREG |= 0x80; // 인터럽트 사용
UCSR0A = 0x00; UCSR0B = 0b00010000; // 수신기 인에이블이 되어 수신 가능 상태가 됨 UCSR0C = 0b10000110; // bit 2, bit 1은 전송 데이터 비트 수로 8비트로 설정 UBRR0H = 0; UBRR0L = 103; // X-TAL = 16MHz 일 때 BAUD = 9600
/* a = mode 1 s = mode 2 z = auto start x = auto end */
while(1) { if(UCSR0A & 0x80) { ch[ch_num] = UDR0; ch_num++; } if(ch_num > 0 && (ch[0] == 'a' || ch[0] == 'A')) { for(i = 0; i < ch_num; i++) { ch[i] = ch[i+1]; } ch[ch_num-1] = '\0'; ch_num--;
motor_mode1(); // 모터 제어 첫번째 모드(좌우)
} else if(ch_num > 0 && (ch[0] == 's' || ch[0] == 'S')) { for(i = 0; i < ch_num; i++) { ch[i] = ch[i+1]; } ch[ch_num-1] = '\0'; ch_num--;
motor_mode2(); // 모터 제어 두 번째 모드(앞뒤) } else if(ch_num > 0 && (ch[0] == 'd' || ch[0] == 'D')) { for(i = 0; i < ch_num; i++) { ch[i] = ch[i+1]; } ch[ch_num-1] = '\0'; ch_num--;
motor_autocontrol(); // 모터 자동 제어 모드 }
} }
|