My Project/교통정리로봇

[교통정리로봇] 프로젝트 문서 4. 구현(세번째)

행복하면 2009. 4. 29. 22:34
 

(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(); // 모터 자동 제어 모드

                }

   

        }      

}