Busan IT/모터제어2015. 7. 14. 13:58

================================ Outline ====================================

AX-10+ 모터제어

- 각도 값을 입력하면 작동하는 함수 만들기

** 자동문 만들기

- 모터 속도 조절

----------------------------------------------------------------------------

 

각도 값을 입력하면 작동하는 함수 만들기

 

각도 값을 입력하면 그만큼 회전하게 만드는 함수를 만들어 보자.

0도이면 0x000, 300도이면 0x3FF이다. 표로 만들어 보자.

 

각도

Hexa

10진수

0

0x000

0

100

0x155

341

200

0x2AA

682

300

0x3FF

1023


 

각도 값과 10진수 값의 관계를 알아보자.

 

10진수 = 3.41 * 각도

 

para1은 각도 값에서 하위 1byte의 값이고 para2는 각도 값에서 오른쪽으로 1byte를 밀어준 값이다.

 

하여 int 값으로 받은 ucAngle(0~300) 값을 10진수로 변경해 주고 상위바이트와 하위바이트를 나누어 para1, 2에 넣어주는 작업을 하면 된다.

unsigned char para1;

unsigned char para2;

ucAngle = 3.41 * ucAngle;
para1 = ucAngle & 0b11111111;
para2 = ucAngle >> 8;


그 후 전에 만들어놓았던 para값이 2개인 함수를 사용하여 para1, 2을 제외한 값들은 상수로 바꾸고 함수로 만들면 된다.

 

** 자동문 만들기

 

 

자동문을 원리를 생각해보고 전원이 인가되면 자동적으로 모터가 돌아가고 딜레이 후 모터가 원위치로 돌아가도록 만들어보자.

 

전원을 인가할 포트는 B port이다.

 

//A port를 사용하였다가 port가 고장난 것을 모르고 1시간을 날렸다.

 

모터 속도 조절

 

회전문이 초고속으로 닫히면 사용자가 다칠 위험이 있음으로 모터의 회전 속도를 줄여보자.

WRITE_DATA를 사용하기 때문에 instruction0x03이고 Moving Speed를 제어하기 위해 control table에서 0x20 parameter의 개수가 2개임으로 Length5가 된다.

parameter의 값이 0일 경우 현재 인가 전압상 최대 속도임으로 속도를 줄이기 위해서는 0x001부터 0x3FF사이에서 값을 설정해 주어야 한다.


이미 만들어진 parameter2개를 입력하는 함수를 사용하여 속도 조절을 해보자.


PacketTX_P2(0x0C, 0x05, 0x03, 0x20, 0x40, 0x00); //회전 속도 조절 -> 0x040

 

 

코드는 간단하다.

 

/*** 코드 ***/

 

#include <avr/io.h>
#include <util/delay.h>

void USART0_init()
{
  /* BAUD Rate Set */
  UBRR0 = 0x00;

  /* USART Set */
  UCSR0A = 0b00000000;    //일반모드 
  UCSR0B = 0b00001000;    //인터럽트 사용 안함
  UCSR0C = 0b00000110;
}

void USART0_disable()
{  
  /* USART Set */
  UCSR0A = 0;   
  UCSR0B = 0;    
  UCSR0C = 0;
}


void USART1_init()
{
  /* BAUD Rate Set */
  UBRR1 = 0x67;

  /* USART Set */
  UCSR1A = 0b00000000;    //일반모드 
  UCSR1B = 0b00001000;    //인터럽트 사용 안함
  UCSR1C = 0b00000110;

}

void Data_Tx0( unsigned char data )
{
  /* Wait for empty transmit buffer */
  while ( !( UCSR0A & (1<<UDRE0)) );
  
  /* Put data into buffer, sends the data */
  UDR0 = data;    
}

unsigned char Data_Rx0()
{
  // Wait for data to be received
  while ( 0==(UCSR0A & (1<<RXC0)) );  //datasheet p/184
  
  // Get and return received data from buffer 
  
  return UDR0;
}
void Data_Tx1( unsigned char data )
{
  /* Wait for empty transmit buffer */
  while ( !( UCSR1A & (1<<UDRE1)) );
  
  /* Put data into buffer, sends the data */
  UDR1 = data;    
}

unsigned char Data_Rx1()
{
  // Wait for data to be received
  while ( 0==(UCSR1A & (1<<RXC1)) );  //datasheet p/184
  
  // Get and return received data from buffer 
  
  return UDR1;
}

void PacketTX_P1(unsigned char ID, unsigned char Length, unsigned char Instruction, unsigned char cmd, unsigned char para1)
{
    Data_Tx0(0xFF);  //ini
    Data_Tx0(0xFF);  //ini
    Data_Tx0(ID);  //ID
    Data_Tx0(Length);  //LENGTH = 2+ # of parameter
    Data_Tx0(Instruction);  //Instruction 
    Data_Tx0(cmd);  //command in control table
    Data_Tx0(para1);  //goal position(rear byte)
  
    Data_Tx0((unsigned char)(~(ID + Length + Instruction + cmd + para1)));
    _delay_ms(865);
}

void PacketTX_P2(unsigned char ID, unsigned char Length, unsigned char Instruction, unsigned char cmd, unsigned char para1, unsigned char para2)
{
    Data_Tx0(0xFF);  //ini
    Data_Tx0(0xFF);  //ini
    Data_Tx0(ID);  //ID
    Data_Tx0(Length);  //LENGTH = 2+ # of parameter
    Data_Tx0(Instruction);  //Instruction 
    Data_Tx0(cmd);  //command in control table
    Data_Tx0(para1);  //goal position(rear byte)
    Data_Tx0(para2);  //goal position(head byte)
  
    Data_Tx0((unsigned char)(~(ID + Length + Instruction + cmd + para1 + para2)));
    _delay_ms(865);
}

void Motor_Rotate(unsigned char ID, unsigned int ucAngle)
{
    unsigned char para1;
    unsigned char para2;
    ucAngle = 3.41 * ucAngle;
    para1 = (unsigned char)(ucAngle & 0b11111111);
    para2 = (unsigned char)(ucAngle >> 8);

  
    Data_Tx0(0xFF);  //ini
    Data_Tx0(0xFF);  //ini
    Data_Tx0(ID);  //ID
    Data_Tx0(0x05);  //LENGTH = 2+ # of parameter
    Data_Tx0(0x03);  //WRITE_DATA 
    Data_Tx0(0x1E);  //Goal Position
    Data_Tx0(para1);//goal position(rear byte)
    Data_Tx0(para2);//goal position(head byte)
  
    Data_Tx0((unsigned char)(~(ID + 0x05 + 0x03 + 0x1E + para1 + para2)));    
}

void Baud9600()
{
  //AX-10_ Baud Rate 9600으로 변경 
  PacketTX_P1(0x0C, 0x040x030x040xCF);   
   
  //ATmega2560 Baud Rate 9600으로 변경    
  USART0_disable();
  UBRR0 = 0x67;
                /* USART Set */
  UCSR0A = 0b00000000;    //일반모드 
  UCSR0B = 0b00001000;    //인터럽트 사용 안함
  UCSR0C = 0b00000110;
  _delay_ms(1000);  
}


int main(void)
{
  DDRB = 0xFE;    //PORTB 0번 핀입력

  _delay_ms(1000);
  USART0_init();
  
  Baud9600();      //Baud Rate 9600으로 변경

  PacketTX_P2(0x0C, 0x050x030x200x400x00); //회전 속도 조절 -> 0x040


  while(1)
  {
    // 자동문, 문이 열리고 5초 대기 후 신호가 없으면 닫힌다.
    if(PINB == 0x01)
    {
      Motor_Rotate(0x0C,300);
      _delay_ms(5000);
    }
    else if((PINB & 0x01== 0x00)
    {
      Motor_Rotate(0x0C,0);
      _delay_ms(1000);
    }
  }

  return 0;
}


반응형
Posted by newind2000