AVR과 BA6208 모터드라이버로 DC모터 정회전, 역회전 제어하기 - AVR 연습

2013.02.14 20:13




현재 군 복무중인 상태입니다.


드디어 LED에서 벗어나서 새로운 DC모터를 제어해 봅니다. ㅎ

역시 제가 만든 Attiny2313 모듈을 가지고 DC모터를 제어 해 봤습니다.

그럼 간단하게 DC모터 제어의 이론 부터 살피고 직접 구동시켜보도록 하지요.^


딴길로...(?!) ㅎ DSLR이 갖고 싶다고 느낄 정도의 사진이 나와버렸습니다. 사진을 보정해서 저정도로 나왔는데 파란색이 있으니까 색농도가 너무 높아져서 백열등 켜놓은줄...


DC모터 제어의 이론


기본적으로 DC모터는 + - 만 정상적으로 연결 시켜주면 회전을 합니다.

그런데 DC모터 구동시에는 거의 200mA ~ 1A정도가 흐르기 때문에 AVR 핀출력으로 나오는 전류로만은 제어에 무리가 있는데요.

그래서 트랜지스터를 이용합니다.


한쪽 방향으로만 모터를 회전 시킬 때에는 다음처럼 손쉽게 NPN트랜지스터 활용 컬렉터 드라이브로 동작시킬수 있습니다.

그리고 D1은 모터 회전후 정지시에는 내부 코일에 의해 원래 전류 흐름의 반대 방향으로 기전력(전기생성) 이 되는데 이로 인해서 트랜지스터가 파손될수 있으므로 1000V정도 견딜수 있는 Fast Recovery Diode (고속 회복 다이오드) 를 사용하도록 합니다.








그런데 로봇같은 것을 만들 때에는 로봇이 앞으로 가기도 하고 뒤로 가기도 하고 하는데 이렇게 설계해서는 전류가 VCC에서 GND로 모터의 1번 핀에서 2번핀으로 한방향으로 밖에 전류가 흐를 수 없기 때문에 정방향/역방향 제어가 되지 않습니다.

그 때는 H 브릿지라는 회로를 이용 4개의 트랜지스터를 활용해서 정역제어를 하는데요.

기본적인 설계 구조는 아래와 같습니다.


다음 처럼 상단은 

PNP트랜지스터 2개

하단은 NPN트랜지스터 

2개로 구성하고 

역시 역방향 기전력 

차단용으로 다이오드를 

붙여줍니다.












- R1, R2, R3, R4의 저항 값은 모터의 용량에 따라 변경되어야 합니다.

상단에 PNP 트랜지스터를 이용하는 이유는 NPN 트랜지스터와 같이 컬렉터에 부하를 걸어야

트랜지스터가 포화상태가 되어서 트랜지스터에서 손실되는 전류/전력이 줄어들기 때문입니다.


동작방법은 PNP 트랜지스터는 베이스가 논리 0 이 되면 동작하므로

T1과 T4를 동작시키면 모터는 정회전을 하고, T2와 T3을 동작시키면 역회전을 하게됩니다.

이 회로를 작게 칩하나로 만들어 둔것이 BA6208 같은 모터 드라이버 IC입니다.

그럼 IC를 이용해서 실제로 구성 동작시켜보겠습니다.


DC모터 제어 연습 회로도




BA6208로 구성된 간단한 모터제어 회로입니다.

BIN과 AIN에 각각 논리 1, 논리 0을 주면 BOUT과 AOUT에 정회전 논리1, 논리 0이 출력되고

BIN과 AIN에 각각 논리 0, 논리 1을 주면 역회전 논리 0, 논리 1 로 동작시킬수 있습니다.


 DC모터는 정회전, 역회전이 정확이 정해져있지 않아서 본인 기준입니다.^

본인이 논리1, 논리0 을 보냈을때를 정회전이라고 정해두면 반대는 역회전인 것이죠.!


그리고 C3 콘덴서는 모터 초기 구동시에는 많은 전류를 끌어다 쓰기 때문에 전압 안정용으로 100uF정도 달아주거나 혹은 노이즈 제거용으로 0.1uF정도 달면 됩니다.

이외에 역기전력 차단 다이오드 트랜지스터는 모두 저 IC안에 내장되어 있습니다.

회로설명도 끝났으니 코드비전 용 소스코드 부터 살펴보면서 실제로 MCU로 제어해 보겠습니다.



CodeVisionAVR 용 소스코드


#include <tiny2313.h>    // Tiny2313 입출력 관련 헤더 파일을 포함합니다.

#include <delay.h>    // 지연함수 관련 헤더파일을 포함합니다.


void main(void)    // main함수를 호출합니다.

{


PORTB=0x00;    // 포트B의 초기상태는 모두 꺼짐 논리0 (0V)입니다.

DDRB=0xFF;    // 포트B의 8비트 전체를 출력으로 설정합니다.


while (1)    // 아래 구문을 무한반복합니다.

      {

        PORTB.0=1;    // 포트B의 0번 핀에 5V (논리1)출력

        PORTB.1=0;    // 포트B의 1번 핀에 0V (논리0)출력

        delay_ms(1000);    // 위 상태를 1초 동안 유지합니다.

        PORTB.0=0;    // 포트B의 0번 핀에 0V (논리0)출력

        PORTB.1=0;    // 포트B의 1번 핀에 0V (논리0)출력

        delay_ms(4000);    // 위 상태를 4초 동안 유지합니다.

        PORTB.0=0;    // 포트B의 0번 핀에 0V (논리0)출력

        PORTB.1=1;    // 포트B의 1번 핀에 5V (논리1)출력

        delay_ms(1000);    // 위 상태를 1초 동안 유지합니다.

        PORTB.0=0;    // 포트B의 0번 핀에 0V (논리0)출력

        PORTB.1=0;    // 포트B의 1번 핀에 5V (논리1)출력

        delay_ms(4000);    // 위 상태를 4초 동안 유지합니다.


      }

}


프로그램이 LED 비트제어 했던 것과 유사합니다. 회로가 약간 복잡해졌지만 소프트웨어는 어렵지 않지요.

프로그램을 설명하자면 1초 동안 DC모터를 정회전 후에 4초 동안 회전하지 않습니다.

그리고 1초 동안 DC모터를 역회전 후에 4초 동안 회전하지 않습니다. 이 것을 무한 반복합니다.


 실제로는 관성 때문에 조금 오래 돌아가서 4초 동안 지연시켰습니다.



AVR Studio 용 소스코드


#include <avr/io.h>    // AVR 입출력 관련 헤더파일을 포함합니다.

#define F_CPU 8000000UL    // 사용하는 크리스탈 주파수 값을 상수로 설정합니다.

#include <util/delay.h>    // 지연함수 관련 헤더파일을 포함합니다.


int main(void)    // main함수를 호출합니다.

{

PORTB=0x00;    // 포트B의 초기상태는 모두 꺼짐 논리0 (0V)입니다.

DDRB=0xFF;    // 포트B의 8비트 전체를 출력으로 설정합니다.


while (1)    // 아래 구문을 무한 반복합니다.

      {

PORTB = (1<<PB0) | (0<<PB1);    // 포트B의 0,1번 핀에 각각 5V, 0V출력

_delay_ms(1000);    // 위 상태를 1초 동안 유지합니다.

PORTB = (0<<PB0) | (0<<PB1);    // 포트B의 0,1번 핀에 각각 0V, 0V출력

_delay_ms(4000);    // 위 상태를 4초 동안 유지합니다.

PORTB = (0<<PB0) | (1<<PB1);    // 포트B의 0,1번 핀에 각각 5V, 0V출력

_delay_ms(1000);    // 위 상태를 1초 동안 유지합니다.

PORTB = (0<<PB0) | (0<<PB1);    // 포트B의 0,1번 핀에 각각 0V, 0V출력

_delay_ms(4000);    // 위 상태를 4초 동안 유지합니다.

      }


return 0;    // main함수에 0을 리턴합니다.

}


AVR Studio의 새로운 쉬운 비트제어 방법을 알았습니다.

시프트 연산자로 포트B의 5번 포트에 5V를 출력하고 싶다면 PORTB = (1<<PB5)라고

표현하면 쉽게 동작되는 것을 확인했습니다.

논리연산으로 비트 제어를 해도 되지만, 이 방법을 사용해도 됩니다.


DC 모터 동작영상


 

정역제어 끝... 다음 포스팅에서는 PWM으로 속도를 늘렸다 줄였다 해보겠습니다.

휴~~ 이번 포스팅은 조금 힘들었네요.^

BinGoon AVR/AVR 연습, Tutorial , , , , , , , ,

  1. Blog Icon
    김성훈

    안녕하세요 포스트 잘 봤습니다.
    한가지 궁금한 점이 있어서 이렇게 염치불구하고 댓글을 답니다.
    이번에 산업용 연마기를 구입하여 사업을 시작하게 되었는데 기계의 개조를 하고싶어서
    여러가지 설계는 이미 마쳤으나, 역시 전공분야가 아닌 자동제어 부분에서는 조언을 구할만한
    곳이 없더군요

    기계의 선반을 X축으로 좌우로 정,역방향 구동과 Y축으로의 미세구동을 개조하고싶은데
    모터제어에 대한 기본적인 지식조차 없으니, 모터선별부분에서 막혀버리고 말았네요
    모터에 대하여 자세히 알수있는 서적같은거 추천해주실수 있으신가 싶어서 이렇게 두서없이 글을 올립니다.

  2. 선반을 제어하시는 것이라면 어느정도 정밀성이 필요하지 않을까요?!
    DC모터는 정밀도가 떨어져서 사용하시면 안될 것 같습니다.
    CNC 가공기를 자작하시는 분들도 스테핑모터나 서보모터를 사용하시는데요. 스테핑 모터는 입력신호에 대응해서 일정각도를 회전하구요. 서보모터는 아날로그 서보의 경우 PWM의 듀티비에 대응해서 회전 각도가 결정된답니다.
    하지만 서보모터의 경우 180도 정도 회전각도가 제한되어서 일정 각도 내에서만 사용가능할것 같습니다. 따라서 스테핑모터의 구동방법및 자료들을 찾아야 할 것 같습니다.
    도움이 되셨을지 모르겠네요^;
    혹시 구동방법을 질문하신다면 도움이 못되어드릴것 같네요;; 스테핑 모터는 비싸서 사용을 못해봤답니다... 그리고 모터에 대해서 나온 서적은 제가 아는 것이 없습니다. 죄송합니다^
    좀 더 알도록 노력하겠습니다.!!

  3. Blog Icon
    김성주

    혹시 BIN, AIN에 입력으로 1,1을 넣어주면 어떻게 되나요???
    다른곳에서는 정지라고 했는데 0,0이랑 1,1랑 다른점은 무엇인가요??
    그리고 모터를 12v로 돌리고 싶은데 이경우는 어떻게 해야 되나요??
    단순하게 BA6208의 vcc에 12v걸수 있었으면 좋겠는데 안되겠죠?? ㅋㅋ

  4. 안녕하세요.^^ 오늘 새벽에 댓글 달아주셨네요. ㅎㅎ
    먼저 Bin과 Ain에 0,0을 넣어주시면 그냥 모터에 전원이 공급되지 않아 정지됩니다, 두번째로 1,1을 넣어 주시면 AVR의 명령어 처리 속도차이 때문에 매우 짧은 시간동안 1,0과 0,1이 번갈아 나타나면서 모터가 정지상태로 약간의 힘이 가해지게 됩니다. 따라서 부드러운 정지를 원할 경우에는 0,0의 신호를 급 정지를 원하신다면 1,1을 입력하도록 하시면 된답니다.^ 그리고 Vcc는 BA6208의 데이터 시트를 보면 18V까지 걸수 있다고 되어있네요 ㅎㅎ, 가능할 것 같습니다. 이로서 답변 마칩니다.^ 앞으로도 자주 찾아주세요. ㅎㅎ

  5. Blog Icon
    김성주

    11로 넣어주면 정지상태로 약간의 힘이 가해지신다고 하셨는데 정확하게 어떤 의미인가요??

  6. 조금 바쁜관계로 답변이 조금 늦었네요.^
    1,1로 신호를 넣어주게되면 모터의 입력이 AVR의 1클럭당 명령어를 1개 처리하므로 처음 5V,0V 출력에 다음 클럭에 0V,5V가 매우 빠르게 교대로 나타나게 될 것입니다. 이 때문에 모터는 약간에 힘이 들어간 상태로 중간에 멈춰있는 형태로 나타나게 될 것으로 예상됩니다.^

  7. Blog Icon
    [Adios]

    DC모터는 한번에 비트제어를 해서 모터를 구동하는건가보네요! 호옹이
    지금 스테핑모터에 대해 배우는 중인데 그건 모터의 구동을 위해 순차적으로 줘야하는 신호가 따로 존재한다...고 하더라고요. 또르르...

  8. DC모터는 제어하는데 별로 어려움이 없어요.^
    스테핑 모터나, 다른 것도 제어해 보고 싶지만... 학생이다 보니.. 너무 비싸서 시도조차 해보지 못했습니다...하...

  9. Blog Icon
    avr

    while문에서요

    PORTB=(1<<PB0)|(0<<PB1);
    여기서 잘 이해가 안가네요ㅠㅠ
    PB0가 0x01이니깐 1을 0x1만큼 쉬프트 해서 0000 0001 그래서 PB0 5V출력
    PB1이 0x2이니깐 0을 0x02만큼 쉬프트 해서 0000 0000 그래서 PB1
    0V출력
    이렇게 생각하면 맞나요?

    개념이 안잡혀서 어렵네요 ㅠㅠ
    좋은 하루 되세요

  10. 코드를 위에서 아래로 순서대로 보시면 도움이 되실듯 합니다.^^
    먼저 int main(void) 바로 아래 PORTB=0x00; 에 의해서 포트 B의 초기값은 0b00000000 입니다. 그리고 이 때 while(1)문에서 PORTB =(1<<PB0)|(0<<PB1);을 주었는데 PB0은 io.h에 포트B의 0번 비트로 정의 되고, PB1은 포트B의 1번 비트로 정의 되어 있습니다. 이렇게 되었을 때 8비트 프로세서 이므로, (1<<PB0)은 0b00000001로 해석 될수 있고, (0<<PB1)은 초기값이 0이라 입력하지 않아도 되지만, 0b00000000로 해석될 수 있습니다. 그리고 이 값을 OR 연산 하면 0b00000001 | 0b00000000 = 0b00000001 로 결과 값이 나오기 때문에 포트B의 0번 핀에서는 5V가 출력되고, 포트B의 1번 핀에는 0V가 출력되게 되는것입니다.^ 그리고 구동은 전압은 높은곳에서 낮은곳으로 흐르기 때문에 직관적으로 보면 PB0 ---- 모터 ---- PB1로 흐르게 되어서 회전하게 됩니다^ (실제로는 IC에 의해서 증폭되어서 모터에 입력된답니다..

  11. 검색하다가 들렀어요.염치 불구 하고 하나 여쭘겠습니다.
    제가 핸드폰에 소형 모터를 넣을 생각입니다.
    개략적인 구동은 스위치를 on하면 모터가 역회전과 정회전을 한후 멈추는 것입니다.
    이후 스위치를 off하고 난뒤에 다시 on 하면 다시 동작을 하는 식입니다.
    위에 포스팅을 보고 구동원리는 이해했습니다.
    제가 궁금한것은 avr키트가 폰에 들어가야하는데 소형화가 가능한지입니다.

  12. 다른 글에도 댓글 달아주셨는데요^
    먼저 배터리에 직결 연결로 구동하는가? 에 대한것이랑 크기가 어느정도 여야 하는지가 궁금합니다. 일단 SMD 부품을 쓰면 작게는 제작가능한데 수제작은 힘듭니다. (QFN 타입의 IC를 사용하게 되면 아주 작게 가능하고 SOIC나 TQFP패키지의 IC를 사용시 QFN타입에 비해 조금 커질수 있습니다.)

  13. Blog Icon
    대단해요

    인문계 나온 학생이고 지금 컴퓨터공학과 재학중인 학생입니다. 일년동안 마음먹고 한게 많지 않았는데. 적잖은 충격을 받고 열심히 공부 해야겠다는 생각이 드네요. 열심히 공부하시고 꿈을 이루시기 바래요 파이팅.

  14. 부족한 포스팅에서 대단하다고 해주셔서 감사드립니다.^
    또 블로그에 방문해 주셔서 감사드리구요, 계속해서 열심히 공부하도록 노력하겠습니다.

  15. Blog Icon
    굳굳

    안녕하세요 완전 공대생 초보입니다 . 2가지 질문좀하겠습니다.
    1.저가 모터드라이버로 L298N을사용하고 있는데 L298N에서 Logic supply voltage vss에서 12v인가 해주고 VCC에서는 5V가 나온는 건가요? 그쪽 VCC에 대해서 설명좀 해주세요^^

    2.12V 에서 다이오드를 거쳐 GND로 빠지는데 AVR쪽으로 가는 GND는 5V로 가는건가요?

  16. 안녕하세요.

    위 회로를 참고해서 회로를 구성하였는데요. TEST할 때 문제가 생긴 것을 공유하고자 합니다.
    제가 사용한 MOTOR는 12V 동작인데요. 제가 사용한 MOTOR를 위 회로처럼 구성면 모터로 인해서 TR에 부하가 많이 걸립니다..

    FET을 사용하면 금방 될 수 있겠죠.

    근데, 왜 이런 문제가 발생했는지는 알아야하기 때문에 말씀드리자면,
    제가 알기론 TR은 보통 최대 Ic가 600mA까지 가능할텐데.. 200mA이상의 전류가 흐르면 발열이 굉장히 심하기 때문에, 열패드 붙어있는 TR을 사용을 하셔야 할 것 같네요.

    그래서 열패드가 없는 BC547이나 KSP2222A같은 작고 spec이 낮은 TR을 사용하려면 Relay와 함께 사용해야 합니다.

    FET이 없으면 Relay와 함께 사용하면 된다는 점. 참고해주세요~

티스토리 툴바