학습    1

학습주제    1

예습내용    1

실습방법    1

        1

AVR PC 통신 (DC모터제어)

학습목표

스텝모터 드라이버를 만든다.

학습용 보드로 만든 것을 사용하려고 보니 출력에 릴레이를 사용해 24V 제어했다. 실제 드라이버 제작에는 TR 사용하니 단원에서는 스텝모터의 원리를 이용하고 응용에서는 TR 이용하세요.

학습주제

실습에 사용하는 스텝모터는 200스텝이 1회전으로 되어있다. 스텝모터는 PC응용제어 스텝모터 참조하고 PC프로그램은 지난주의 프로그램을 그대로 사용한다.

그림은 PC에서 모터의 좌우회전을 제어하는 화면이다.

그림1 PC 제어 판넬

 

그림2 스텝모터 보드에 연결

통신 프로토콜

RS232 이용해 PC에서 문자 하나를 AVR 전송한다. 우회전(0x31), 좌회전(0x32), 정지(0x00) 보내면 마이크로프로세서는 이를 수신해서 모터의 회전을 제어한다. 실습에서는 1회전(200스텝) 시킨다. 각도 조절은 스템을 계산하여 만들 있을 것이다.

예습내용

아래 그림1 CT GND(-) 또는 Vcc(+) 연결하는 2가지 방법의 모터 기동 방법이 있다.

 

 

 

CT GND 연결

CT Vcc 연결

 

 

시계방향

B-A-[B]-[A]

0x04-0x01-0x08-0x02

A-B-[A]-[B]

0x01-0x04-0x02-0x08

 

 

반시계방향

[A]-[B]- A-B

0x02-0x08-0x01-0x04-

[B]-[A] -B-A

0x08-0x02-0x04-0x01

 

       1 스텝모터 제어 순서

실습방법

   

1. CT GND 연결한 스텝모터 제어

그림3 같이 스텝모터를 보드에 연결한다. 2 모터의 스텝별 동작을 나타낸 그림이다.

그림3에서 빨간색 4개의 릴레이모듈(컴파일사) PC0,PC1,PC2,PC3 연결하여 제어 한다.

그림2 도면과 Simulator 회로와 확인하면서 배선을 연결한다.

 

 

Step

PC0

PC1

PC2

PC3

포트출력

그림3 릴레이 모듈로 모터제어

0

 

 

ON

 

0x04

1

ON

 

 

 

0x01

2

 

 

 

ON

0x08

3

 

ON

 

 

0x02

0

 

 

ON

 

0x04

2 CT GND 연결한 스텝모터 시계방향 회전

2. CT Vcc 연결한 스텝모터 제어

그림4 같이 스텝모터를 보드에 연결한다. 3 모터의 스텝별 동작을 나타낸 그림이다.

그림4에서 검은색 4개의 TR모듈(컴파일사) PC0,PC1,PC2,PC3 연결하여 제어 한다.

그림2 도면과 Simulator 회로와 확인하면서 배선을 연결한다.

 

Step

PC0

PC1

PC2

PC3

포트출력

그림3 TR 모듈로 모터제어

0

ON

 

 

 

0x01

1

 

 

ON

 

0x04

2

 

ON

 

 

0x02

3

 

 

 

ON

0x08

0

ON

 

 

 

0x01

 

3 CT Vcc 연결한 스텝모터 시계방향 회전

 

 

3. AVR 프로그램 (CT GND 연결)

 

한문자를 전송해서 모터의 회전을 제어 한다. [AVR전체 프로그램 보기]

 

 

interrupt [USART0_RXC] void uart0_rx_isr(void)

{

    ……..(생략)

       if(data == 0x30){   // 좌회전

          for(i=0;i<10;i++) { 

                    PORTC = 0x02;

                   delay_ms(100);

                    PORTC = 0x08;

                    delay_ms(100);

                    PORTC = 0x01;

                    delay_ms(100);

                    PORTC = 0x04;

                    delay_ms(100);

              }

              PORTC = 0x00;

       } 

       else if(data == 0x31){   // 우회전

              for(i=0;i<10;i++) {

                    PORTC = 0x04;

                    delay_ms(100);

                    PORTC = 0x01;

                    delay_ms(100);

                    PORTC = 0x08;

                    delay_ms(100);

                    PORTC = 0x02;

                    delay_ms(100);

              }

              PORTC = 0x00;

       }

       else if(data == 0x32)    // 정지

              PORTC = 0x00;

}

 

 

4. AVR 프로그램 (CT Vcc 연결)

 

한문자를 전송해서 모터의 회전을 제어 한다.

 

 

interrupt [USART0_RXC] void uart0_rx_isr(void)

{

    ……..(생략)

       // C포트로 스템모터 드라이버를 제어한다.

       if(data == 0x30){   // 좌회전

          for(i=0;i<10;i++) { 

                    PORTC = 0x01;

                   delay_ms(100);

                    PORTC = 0x04;

                    delay_ms(100);

                    PORTC = 0x02;

                    delay_ms(100);

                    PORTC = 0x08;

                    delay_ms(100);

              }

              PORTC = 0x00;

       } 

       else if(data == 0x31){   // 우회전

              for(i=0;i<10;i++) {

                    PORTC = 0x08;

                    delay_ms(100);

                    PORTC = 0x02;

                    delay_ms(100);

                    PORTC = 0x04;

                    delay_ms(100);

                     PORTC = 0x01;

                    delay_ms(100);

              }

              PORTC = 0x00;

       }

       else if(data == 0x32)    // 정지

              PORTC = 0x00;

}

 

5. PC 프로그램

송신되는 문자의 01 비트가 0인지 아닌지를 검사하여 화면의 LED 표시한다.

[소스 프로그램 내려받기]

처음

   

아래 그림과 같이 스텝수를 입력하여 각도를 제어하고 속도를 제어하는 프로그램 하자.

CT Vcc 연결하고 TR모듈을 사용하는 프로그램을 기본으로 만든다.

PC 프로그램

 

통신은아래와 같이 5개의 문자로 이루어 진다.

[통신시작문자,0x02] [회전방향] [스텝수] [속도] [통신시작문자,0x03]

[PC 프로그램 내려받기]

 

 

void CRs232Dlg::OnPointerValueChangedCwknob1(long Pointer, VARIANT FAR* Value)

{

       // TODO: Add your control notification handler code here

       CString strTemp;

 

       if(m_nKnob.Value==0)

              strTemp.Format( "%c%c%c%c%c",0x02,0x30,(char)m_nStep.Value,(char)m_vel.Value,0x03); // 반시계방향

       else if(m_nKnob.Value==1)

              strTemp.Format( "%c%c%c%c",0x02,0x31,0x08,0x03); // 정지  

       else if(m_nKnob.Value==2)

              strTemp.Format( "%c%c%c%c%c",0x02,0x32,(char)m_nStep.Value,(char)m_vel.Value,0x03); // 시계방향

       m_ComuPort.WriteComm((unsigned char*)(LPCTSTR)strTemp,strTemp.GetLength());

}

 

 

AVR 프로그램

 

문자 0x02 전송되면 rx_buffer0[0] 부터 전송된 문자가 저장된다. 문자 0x03 전송되면 통신의 끝을 알리는 문자 이므로 receive 0에서 1 값을 바꾼다. 그리고 main 함수에서 이를 처리 한다.

[AVR 프로그램 내려받기]

 

 

interrupt [USART0_RXC] void uart0_rx_isr(void)

{

char status,data;

#asm

    push r26

    push r27

    push r30

    push r31

    in   r26,sreg

    push r26

#endasm

status=UCSR0A;

data=UDR0; 

 

if(data == 0x02)    // 통신시작

       rx_wr_index0 = 0;  

 

if(data == 0x03)           // 통신 완료 - 메세지 발생

       receive=1;        

if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)

   {

   rx_buffer0[rx_wr_index0]=data;

   if (++rx_wr_index0 == RX_BUFFER_SIZE0) rx_wr_index0=0;

   if (++rx_counter0 == RX_BUFFER_SIZE0)

      {

      rx_counter0=0;

      rx_buffer_overflow0=1;

      };

   };

#asm

    pop  r26

    out  sreg,r26

    pop  r31

    pop  r30

    pop  r27

    pop  r26

#endasm  

}

 

===================생략==========================

while (1)

      {

      // Place your code here

         if(receive==1) { 

                     if(rx_buffer0[1] == 0x30){     // 좌회전

                         for(i=0;i<rx_buffer0[2];i++) { 

                                         PORTC = 0x02;

                                       delay_ms(rx_buffer0[3]);

                                         PORTC = 0x08;

                                         delay_ms(rx_buffer0[3]);

                                         PORTC = 0x01;

                                        delay_ms(rx_buffer0[3]);

                                         PORTC = 0x04;

                                      delay_ms(rx_buffer0[3]);

                                 }

                                  PORTC = 0x00;

                          } 

                          else if(rx_buffer0[1] == 0x32){     // 우회전   

                                 for(i=0;i<rx_buffer0[2];i++) {

                                       PORTC = 0x04;

                                        delay_ms(rx_buffer0[3]);

                                        PORTC = 0x01;

                                        delay_ms(rx_buffer0[3]);

                                      PORTC = 0x08;

                                       delay_ms(rx_buffer0[3]);

                                       PORTC = 0x02;

                                        delay_ms(rx_buffer0[3]);

                                 }

                                 PORTC = 0x00;

                          }

                          else if(rx_buffer0[1] == 0x31)      // 정지

                                 PORTC = 0x00;

        

                         receive=0;

                }

 

      };