================================ 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를 사용하기 때문에 instruction은 0x03이고 Moving Speed를 제어하기 위해 control table에서 0x20 parameter의 개수가 2개임으로 Length는 5가 된다.

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, 0x04, 0x03, 0x04, 0xCF); //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, 0x05, 0x03, 0x20, 0x40, 0x00); //회전 속도 조절 -> 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; }
|