메뉴 건너뛰기

app

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

박영식2008.04.11 14:10조회 수 4952댓글 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 박영식)

댓글 달기

이전 1 ... 5 6 7 8 9 10 11 12 13 14다음
첨부 (0)
위로