메뉴 건너뛰기

app

[h/w c] AVR 모터제어 예제 소스

박영식2008.04.11 14:10조회 수 5154댓글 0

    • 글자 크기

#include <mega128.h>
#include <stdio.h>
#asm //
인터럽트 enable 관련
.equ __lcd_port=0x12 ;PORTD
#endasm
#include <lcd.h> 
#include <delay.h>      
       
void Go_Ahead(int v, int p);
void Turn_Left(int v, int angle);
void Turn_Right(int v, int angle);
void Turn(int v,int angle);
void Stop(int delay);


void Key_Input(void);
void Run(void);
void Run_Test(void);
void Run_Run(void);


void Run_Servo_Motor(void);
void Run_DC_Motor(void);
void Test_Mode(void);
void Run_Mode(void);


int i, j, Velocity, Pulse, Angle; //속도, 펄스(펄스 속도), 앵글 변수 선언
int switch1, switch2,switch3;
int switch1_cht, switch2_cht, switch3_cht;


interrupt [TIM1_COMPA] void step_motor_1(void) //timer interupt 시간에 따라 호출
{                   
        i++; 
}  
                         
interrupt [TIM3_COMPA] void step_motor_2(void)
{          
        j++; //
외부 인터럽트로 j값을 증가시킴, j값의 초기화는 이루어 지나 제어문 등에는 사용되는 것이 보이지 않음.
}
interrupt [TIM1_COMPB] void servo_motor_1(void)
{            

interrupt [EXT_INT5] void external_int5(void)   //switch1 = 0 : Test Mode, switch1 = 1 : Run Mode,
{                                               //switch1 = 2 : Servo motor Mode, switch1 = 3 : DC motor Mode
        switch1_cht++;
        if (switch1_cht > 1)
        {
                switch1++;
                switch1_cht = 0;
                delay_ms(10);
        }
        if(switch1 == 4)
        {
                switch1 = 0;
        }       
}          
interrupt [EXT_INT6] void external_int6(void)
{      
        switch2_cht ++;
        if (switch2_cht > 1)
        {
                switch2++;
                switch2_cht = 0;
                delay_ms(10);
        }
        if(switch2 == 10)
        {
                switch2 = 0;
        }       
}


interrupt [EXT_INT7] void external_int7(void)
{
        switch3_cht ++;
        if (switch3_cht > 1)
        {
                switch3++;
                switch3_cht = 0;
                delay_ms(10);
        }
        if(switch3 == 2)
        {
                switch3 = 0;
        }              
}
       
void Go_Ahead(int v,int p)
{     
        OCR1A = v;//velocity
pulse
        OCR3AH = 0;
        OCR3AL = v;
               
        i=0;
        while(1)       
        {
                if(i>=p)  //
인터럽트 증가에 따라 i 증가, i 따라 pulse 만큼 유지
                {      
                        i = 0;
                        break;
                }
        }
}


void Turn_Left(int v,int angle)
{   
        PORTA = 0b00000000;
        OCR1A = v;
        OCR3AH = 0;
        OCR3AL = v;
               
        i=0;
        while(1)
        {
                if(i>=angle)
                {      
                        j = 0;
                        PORTA = 0b00000010;
                        break;
                }
        }
}
void Turn_Right(int v,int angle)
{      
        PORTA = 0b00000011;
        OCR1A = v;
        OCR3AH = 0;
        OCR3AL = v;
               
        i=0;
        while(1)
        {
                if(i>=angle+2)
                {      
                        j = 0;
                        PORTA = 0b00000010;
                        break;
                }
        }
}
void Turn(int v, int angle)
{  
        PORTA = 0b00000000;
        OCR1A = v;
        OCR3AH = 0;
        OCR3AL = v;
               
        i=0;
        while(1)
        {
                if(i >= angle * 2 + 4)
                {      
                        j = 0;
                        PORTA = 0b00000010;
                        break;
                }
        }
}
void Stop(int delay)
{
        delay_ms(delay);
}
void Init_Port(void)
{
        DDRA = 0b00000011;
        DDRB = 0b00100000;
        DDRE = 0b00001000;
        PORTA = 0b00000010;
        OCR1A = 0xFFFF;
        OCR3AH = 0xFF;
        OCR3AL = 0xFF;             
}



void Init_Timer(void)
{       
        TIMSK = 0x10;           //Timer/Counter1, Output Compare A Match Interrupt Enable
        ETIMSK = 0x10;          //Timer/Counter3, Output Compare A Match Interrupt Enable
        TCCR1A = 0x40;
        TCCR1B = 0x0d;       
        TCCR3A = 0x40;
        TCCR3B = 0x0d;
}


void Init_ext_int(void)
{
        EICRB = 0b10101000;      //INT5,INT6,INT7
falling edge 설정
        EIMSK = 0b11100000;      //INT5,INT6,INT7
인에이블 설정


}
void Init_System(void) //
초기화
{
        Init_Port();   
        Init_Timer();
        Init_ext_int();
        lcd_init(16);
        delay_ms(10);
       
        SREG = 0x80;            // Global int enable
}
void Key_Input(void)
{
        while(1)
        {      
                lcd_gotoxy(0,13);
                lcd_putchar(switch2 + 48);
                if(switch1 == 0)
                {
                        lcd_gotoxy(0,0);
                        lcd_putsf("Test Mode  "); //
값이 0이면, Test Mode  글자를 보여준다.
                }
                else if(switch1 == 1)
                {
                       lcd_gotoxy(0,0);
                       lcd_putsf("Run Mode   ");//
값이 1이면, Test Mode  글자를 보여준다.
                }
                else if(switch1 == 2)
                {
                      lcd_gotoxy(0,0);
                      lcd_putsf("Servo motor");//
값이 2이면, Test Mode  글자를 보여준다.
                }
                else if(switch1 == 3)
                {
                     lcd_gotoxy(0,0);
                     lcd_putsf("DC motor   ");//
값이 3이면, Test Mode  글자를 보여준다.
                }
                if(switch3 == 1)
                {
                        break;
                }
        }
}
void Run_Run(void)
{       
        Velocity = 50;
        Pulse = 4700 ;
        Go_Ahead(Velocity,Pulse);
        Turn_Left(Velocity,Angle);
        Go_Ahead(Velocity,Pulse);
        Turn_Left(Velocity,Angle);
        Go_Ahead(Velocity,Pulse);
        Turn_Left(Velocity,Angle);
        Go_Ahead(Velocity,Pulse);
        Turn(Velocity,Angle);
                              
        Go_Ahead(Velocity,Pulse);
        Turn_Right(Velocity,Angle);
        Go_Ahead(Velocity,Pulse);
        Turn_Right(Velocity,Angle);
        Go_Ahead(Velocity,Pulse);
        Turn_Right(Velocity,Angle);
        Go_Ahead(Velocity,Pulse+100);
        
        DDRB = 0b00000000;
        DDRE = 0b00000000;
      
}
void Run_Test(void)
{
        while(1)
        {
                Go_Ahead(Velocity,Pulse); //
속도와 펄스에 따라 실행
                Turn_Left(Velocity,Angle);       //
속도와 앵글에 따라 실행
        }
}
void Run_Mode(void) //switch2
값에 따라 앵글을 지정한다
{
        if (switch2 == 0)
        {
                Angle = 190;       
        }
        else if(switch2 == 1)
        {
                Angle = 192;
        }
        else if(switch2 == 2)
        {
                Angle = 194;
        }
        else if(switch2 == 3)
        {
                Angle = 195;
        }
        else if(switch2 == 4)
        {                  
                Angle = 196;
        }
        else if(switch2 == 5)
        {                  
                Angle = 197;
        }
        else if(switch2 == 6)
        {                  
                Angle = 199;
        }
        else if(switch2 == 7)
        {                  
                Angle = 201;
        }
        else if(switch2 == 8)
        {                  
                Angle = 203;
        }
        else if(switch2 == 9)
        {                  
                Angle = 205;
        }        
}
void Run_Servo_Motor(void)
{
        unsigned int sign = 0;    // 0 -> (-)  ,  1 -> (+)
        unsigned int dir = 0;     // 0 : increse  ,  1 : decrease //
모터의 방향에 관한 변수
        unsigned char sign_d = 0b00101101;    // initialization = -
        unsigned char ten_d = 0b00111001;   // initialization = 9
        unsigned char one_d = 0b00110000;   // initialization = 0
       
        DDRB = 0b01000000;       //PB6
        TIMSK = 0b00001000;      //Timer/Counter1, Output Compare B Match Interrupt Enable
        TCCR1A = 0b00100010;     //Clear OCnA/OCnB/OCnC on compare match, set OCnA/OCnB/OCnC at BOTTOM(non-inverting mode)
                                 //Fast PWM mode(Bit1,0)
        TCCR1B = 0b00011011;     //Fast PWM mode(Bit4,3)
                                 //clkI/O/64 (From prescaler)
                                 //16Mhz/64 = 250000 Hz
          
        ICR1 = 5000;             //Period(250000/5000 = 50 Hz)
        OCR1B = 174;             //initialization : Pulse Width(250000/175 = 1428.57 Hz = 0.7ms , -90degree)
       
        lcd_init(16);   // init 16*2 LCD
        delay_ms(50); 
        
        lcd_gotoxy(0,0); //
출력 좌표지정
        lcd_putsf("HOMEWORK");
        lcd_gotoxy(0,1);
        lcd_putsf("Degree is = ");
        lcd_gotoxy(12,1);  
        lcd_putchar(sign_d);
        lcd_gotoxy(13,1);  
        lcd_putchar(ten_d);
        lcd_gotoxy(14,1);  
        lcd_putchar(one_d);


       
        delay_ms(50);       
        while(1) //PWM
파형으로 SEOVO MOTOR 제어
        {
                if (dir == 0) OCR1B = OCR1B + 11;    //-90 to 90 , unit 5 degree increase
                else OCR1B = OCR1B - 22;    //90 to -90 , unit 5 degree decrease
                              
                if ( 370 >= OCR1B ) sign = 0;   // sign : (-)
                else sign = 1;    // sign : (+)
               
               
                if ( OCR1B <= 174 || OCR1B >= 570 ) ten_d = 0b00111001;   //9
                else if ( (OCR1B <= 196 && OCR1B >= 185) || (OCR1B <= 559 && OCR1B >= 548) ) ten_d = 0b00111000;  //8
                else if ( (OCR1B <= 218 && OCR1B >= 207) || (OCR1B <= 537 && OCR1B >= 526) ) ten_d = 0b00110111;  //7
                else if ( (OCR1B <= 240 && OCR1B >= 229) || (OCR1B <= 515 && OCR1B >= 504) ) ten_d = 0b00110110;  //6
                else if ( (OCR1B <= 262 && OCR1B >= 251) || (OCR1B <= 493 && OCR1B >= 482) ) ten_d = 0b00110101;  //5
                else if ( (OCR1B <= 284 && OCR1B >= 273) || (OCR1B <= 471 && OCR1B >= 460) ) ten_d = 0b00110100;  //4
                else if ( (OCR1B <= 306 && OCR1B >= 295) || (OCR1B <= 449 && OCR1B >= 438) ) ten_d = 0b00110011;  //3
                else if ( (OCR1B <= 328 && OCR1B >= 317) || (OCR1B <= 427 && OCR1B >= 416) ) ten_d = 0b00110010;  //2
                else if ( (OCR1B <= 350 && OCR1B >= 339) || (OCR1B <= 405 && OCR1B >= 394) ) ten_d = 0b00110001;  //1
                else  ten_d = 0b00100000;             
               
               
                if (dir==0)
                {
                        if (one_d == 0b00110000) one_d = 0b00110101;    //one digit : repeat 0 and 5
                        else one_d = 0b00110000;
                }
                else one_d = 0b00110000;
               
                if ( OCR1B >= 570 && dir == 0) dir = 1;
                if ( OCR1B <= 174 && dir == 1) dir = 0;
               
                if (sign == 0) sign_d = 0b00101101;   //sign = 0 -> LCD -
                else sign_d = 0b00100000;             //sign = 1 -> LCD
               
                lcd_gotoxy(0,0); //
출력 좌표지정
                lcd_putsf("HOMEWORK");
                lcd_gotoxy(0,1);
                lcd_putsf("Degree is = ");
                lcd_gotoxy(12,1);  
                lcd_putchar(sign_d);
                lcd_gotoxy(13,1);  
                lcd_putchar(ten_d);
                lcd_gotoxy(14,1);  
                lcd_putchar(one_d);
                              
                delay_ms(500);
               
       
        }
}
void Run_DC_Motor(void)
{
        int g;
        DDRB = 0b00100000;         
        TIMSK = 0b00010000;             //Timer/Counter1, Output Compare A Match Interrupt Enable
       
      
        TCCR1A = 0b10000010;     //Clear OCnA/OCnB/OCnC on compare match, set     OCnA/OCnB/OCnC at BOTTOM(non-inverting mode)
                                 //Fast PWM mode(Bit1,0)
        TCCR1B = 0b00011011;     //Fast PWM mode(Bit4,3)
                                 //clkI/O/64 (From prescaler)
                                 //16Mhz/64 = 250000 Hz
          
        ICR1 = 5000;             //Period(250000/5000 = 50 Hz)
        OCR1B = 174;             //initialization : Pulse Width(250000/175 = 1428.57 Hz = 0.7ms , -90degree)
       
                      
        #asm("sei")//
인터럽트 enable
         
        while(1)
        {
                delay_ms(500);
               
                for (g=0; g<50; g++) //
속도 증가
                {
                        OCR1A = OCR1A + 100;
                        delay_ms(100);
                }
               
                delay_ms(4000);
                for (g=0; g<50; g++) /
속도 감소
                {
                        OCR1A = OCR1A - 100;
                        delay_ms(100);
                }
               
                delay_ms(5000);
       
       
       
        }
 
}                         
void Run(void)  //
값에 따라 함수 실행
{
        while(1)
        {
                switch(switch1){
                case 0: Test_Mode();
                        Run_Test();
                        break;
                case 1: Run_Mode();
                        Run_Run();
                        break;
                case 2: Run_Servo_Motor();
                        break;
                case 3: Run_DC_Motor();
                        break;
                }
        }
}


void Test_Mode(void)
{
        Velocity = 50;  //
속도와 펄스 지정
        Pulse = 300 ;
        if (switch2 == 0) // switch2
값에 따른 각도 지정
        {
                Angle = 195;       
        }
        else if(switch2 == 1)
        {
                Angle = 196;
        }
        else if(switch2 == 2)
        {
                Angle = 197;
        }
        else if(switch2 == 3)
        {
                Angle = 198;
        }
        else if(switch2 == 4)
        {                  
                Angle = 199;
        }
        else if(switch2 == 5)
        {                  
                Angle = 200;
        }
        else if(switch2 == 6)
        {                  
                Angle = 201;
        }
        else if(switch2 == 7)
        {                  
                Angle = 202;
        }
        else if(switch2 == 8)
        {                  
                Angle = 203;
        }
        else if(switch2 == 9)
        {                  
                Angle = 204;
        }
}


void main(void)
{         
        Init_System();
        while(1)
        {
                Key_Input(); // key
값을 입력 받는다.
                Run();  // Run
함수 실행
        }
}








서보 모터로 돌아가는 각도 표시하고 


DC 모터로 순간 가속 시키고



스텝 모터로 2m 정사각형을 한번 돌고 다시 역순으로 돌아오는 프로그램이

박영식 (비회원)
    • 글자 크기
[flash] 무비클립 복제의 2가지 방법 (by 박영식) [HDL] 9 x 9 multiplier (by 박영식)

댓글 달기

박영식
2010.09.09 조회 4787
박영식
2010.05.25 조회 4090
박영식
2010.01.14 조회 4969
박영식
2009.09.21 조회 4146
박영식
2008.08.18 조회 6061
박영식
2008.08.17 조회 4192
박영식
2008.07.24 조회 4621
박영식
2008.07.23 조회 7998
박영식
2008.07.22 조회 3347
박영식
2008.04.11 조회 2198
박영식
2008.01.20 조회 2038
박영식
2007.12.23 조회 3222
첨부 (0)
위로