AVR 타이머/카운터 인터럽트 응용 소프트웨어 PWM DC모터 속도 제어하기 - AVR 연습

2013.02.28 14:23




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


모터 정역제어를 해보았으니 다음은 모터의 속도를 조절해 봅니다.

DC모터는 전압에 따라 속도가 변하는데 AVR은 전압의 조절은 불가하고 입력이나 출력만 가능합니다. 따라서 그냥 모터의 속도를 조절 할 수는 없는데요. 

이 것을 소프트웨어 적으로 PWM(Pulse Width Modulation) 펄스 폭 변조를 해주어서 일정 주기 내에 On/Off 횟수를 조절해 주면 평균전압이 떨어지게 되어서 모터의 속도를 제어 할 수 있습니다.


 꾸준히 포스팅하는 것도 힘드네요..ㅎ 개학하면 어찌해야 할지...


PWM (Pulse Width Modulation) 이란 무엇일까요??


위 이미지의 타이밍도 처럼 일정한 동작시간(전체주기) 동안 ON과 OFF의 비율을 조정해서 평균 전압을 떨어뜨리는 방법을 말합니다.

예를 들어서 5V를 공급받아 출력하는 AVR에서 전체 동작 시간을 1초로 모터를 동작시키고자 했을때 PWM을 이용해서 저속으로 동작시키고 싶었다면 펄스 한주기 100%의 최대출력을 자신이 원하는 %만큼 ON/OFF 비율을 조정해 줄수 있도록 (제 경우에는 PWM이라는 변수를 만들어 최대 값은 10으로 10%씩 조정이 가능하도록 나누었습니다.) 변수를 만들어서 50%는 ON, 50% OFF 해서 동작시간동안 계속해서 반복 전체 평균전압을 3V로 떨어뜨리는 방법 입니다.


 AVR에서는 PWM기능을 따로 제공하는데요. 이 기능을 이용해서 PWM 출력을 할 경우에는 OC0A, OC0B, OC1A, OC1B 등 해당 기능을 가진 핀 들에서 밖에 PWM출력이 되지 않기 때문에 타이머/카운터를 이용하면 좀더 범용적으로 기능이 없는 다른 입출력 핀들에서도 PWM 출력이 가능해 진답니다.



모터 PWM 제어 연습 회로도




회로는 기존의 모터 정/역 제어를 했던 것과 동일하고, BA6208 모터컨트롤러 IC를 사용하고, AVR 모듈의 B포트 0번핀과 1번핀으로 제어 하는 회로입니다. 


CodeVision AVR 용 소스코드


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

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


int pwm, count, sec;    // 정수형 전역변수 pwm, count, sec를 생성합니다.


interrupt [TIM0_OVF] void timer0_ovf_isr(void)    // 타이머 인터럽트0번 인터럽트 발생시 점프

{

    if(pwm>10)    // 만약 pwm 변수 값이 10보다 크면

        pwm=0;    // pwm 변수 0으로 초기화

    else    // 아니라면

        pwm++;    // pwm 변수 1증가

    

    if(count==627)    // 만약 count 변수 값이 627과 같다면

    {

        if(sec==100)    // 만약 sec 변수 값이 100과 같다면

            sec=0;    // sec 변수 0으로 초기화

        else    // 아니라면

            sec++;    // sec 변수 1증가

        

        count=0;    // count 변수 0으로 초기화

    }        

    else    // 아니라면

        count++;    // count 변수 1증가

                

    TCNT0=0x00;    // 카운팅 레지스터 TCNT0을 0으로 초기화

}


void motor_pwm(char control)    // motor_pwm 함수를 생성합니다.

{

    pwm=0;    // pwm변수를 0으로 만듭니다.

    while(pwm<=control){}    // pwm 변수가 입력 된 control 변수보다 크거나 같을 때 까지 아무 것도 하지 않습니다.

}


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

{

PORTB=0x00;    // 포트B의 초기값은 8비트 전체 논리0 (0V) 출력

DDRB=0xFF;    // 포트B의  입출력 상태는 8비트 전체 논리1 (5V) 출력으로 설정


TCCR0A=0x00;    // 타이머, 카운터0번 컨트롤 레지스터A Normal (OverFlow)모드로 설정

TCCR0B=0x01;    // 타이머, 카운터0번 컨트롤 레지스터B 입력클럭 그대로 사용 분주비 없음

TCNT0=0x00;    // 타이머, 카운터0번 카운팅 레지스터 0으로 초기화


TIMSK=0x02;    // 타이머,카운터 마스터 컨트롤 레지스터, 타이머, 카운터 인터럽트0 허용


#asm ("sei")    // 전체 인터럽트 허용


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

      {

        sec=0;    // sec변수를 0으로 만듭니다.

         

        while(sec<50)    // sec 변수가 50보다 클때까지

        {

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

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

        motor_pwm(10);    // pwm변수가 10일 때 까지 지연합니다.

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

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

        motor_pwm(0);    // pwm 변수가 0일 때 까지 지연합니다.

        }


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

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

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

        

        sec=0;    // sec변수를 0으로 만듭니다.

        

        while(sec<50)    // sec 변수가 50보다 클때까지

        {

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

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

        motor_pwm(5);    // pwm변수가 5일 때 까지 지연합니다.

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

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

        motor_pwm(5);    // pwm변수가 5일 때 까지 지연합니다.

        }


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

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

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

      }

}


AVR Studio 용 소스코드


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

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

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

#include <avr/interrupt.h>    // 인터럽트 관련 헤더파일을 포함합니다.


volatile int pwm, count, sec;    // 정수형 전역변수 pwm, count, sec를 생성합니다.


ISR(TIMER0_OVF_vect)    // 타이머 인터럽트0번 인터럽트 발생시 점프

{

    if(pwm>10)    // 만약 pwm 변수 값이 10보다 크면

        pwm=0;    // pwm 변수 0으로 초기화

    else    // 아니라면

        pwm++;    // pwm 변수 1증가

    

    if(count==627)    // 만약 count 변수 값이 627과 같다면

    {

        if(sec==100)    // 만약 sec 변수 값이 100과 같다면

            sec=0;    // sec 변수 0으로 초기화

        else    // 아니라면

            sec++;    // sec 변수 1증가

        

        count=0;    // count 변수 0으로 초기화

    }        

    else    // 아니라면

        count++;    // count 변수 1증가

                

    TCNT0=0x00;    // 카운팅 레지스터 TCNT0을 0으로 초기화

}


void motor_pwm(char control)    // motor_pwm 함수를 생성합니다.

{

    pwm=0;    // pwm변수를 0으로 만듭니다.

    while(pwm<=control){}    // pwm 변수가 입력 된 control 변수보다 크거나 같을 때 까지 아무 것도 하지 않습니다.

}


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

{

PORTB=0x00;    // 포트B의 초기값은 8비트 전체 논리0 (0V) 출력

DDRB=0xFF;    // 포트B의  입출력 상태는 8비트 전체 논리1 (5V) 출력으로 설정


TCCR0A=0x00;    // 타이머, 카운터0번 컨트롤 레지스터A Normal (OverFlow)모드로 설정

TCCR0B=0x01;    // 타이머, 카운터0번 컨트롤 레지스터B 입력클럭 그대로 사용 분주비 없음

TCNT0=0x00;    // 타이머, 카운터0번 카운팅 레지스터 0으로 초기화


TIMSK=0x02;    // 타이머,카운터 마스터 컨트롤 레지스터, 타이머, 카운터 인터럽트0 허용


sei();    // 전체 인터럽트 허용


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

      {

        sec=0;    // sec변수를 0으로 만듭니다.

         

        while(sec<50)    // sec 변수가 50보다 클때까지

        {

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

        motor_pwm(10);    // pwm변수가 10일 때 까지 지연합니다.

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

        motor_pwm(0);    // pwm변수가 0일 때 까지 지연합니다.

        }


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

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

        

        sec=0;

        

        while(sec<50)

        {

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

        motor_pwm(5);    // pwm변수가 5일 때 까지 지연합니다.

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

        motor_pwm(5);    // pwm변수가 5일 때 까지 지연합니다.

        }


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

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

      }


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

}


프로그램 동작 설명


STEP 1 타이머/카운터0의 기본설정은 CK로 분주비를 사용하지 않고, Normal(OverFlow)모드로 동작합니다.


STEP 2 count변수와, sec변수는 while반복문으로 일정시간동안 지연시키면서 계속해서 pwm구문을 동작시키기 위해서 사용되고, count변수가 627이 되면 0.000031875초 동안 지연되고, 이 때 sec 변수가 1 증가되는데 sec 변수가 50이 되면 약 1초 동안 지연이 가능 해 집니다.


STEP 3 이를 이용해서 while(1) 반복구문에서 while(sec<50) sec변수가 50보다 클 때까지, 모터의 정회전을 100%동작 시키고, 모터의 정지를 0% 출력시키면 PWM출력은 100%로 1초동안 DC모터가 정회전 동작하고, 아래 두번째 반복구문 에서 while(sec<50) 에서는 모터의 정회전을 50%동작시키고 50%는 정지를 시켰기 때문에 PWM출력은 50%로 약 3V정도 출력되어 저속으로 정회전 동작하게 됩니다.



DC모터 PWM 구동영상



총 동작은 PWM 100%로 모터 정회전 1초 > 4초동안 정지 

> PWM 50%로 모터 정회전 1초 > 4초동안 정지 입니다.


PWM 제어 끝 다음은 무엇을 할까요??


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

  1. Blog Icon
    왕초보

    보다가 궁금한게 있어서 질문을 올립니다.
    위에서 두번째 if문에서 count==627이라고 해놨는데 왜 그런지 이유를 알고 싶습니다. 그리고 PWM변수가 뭘 뜻하는지 잘 모르겠습니다.

  2. 일반적인 AVR의 지정된 핀에서 나오는 PWM을 사용하면.
    일정 동작시간동안 ON/OFF가 제어되지만...타이머/카운터0 오버플로우를 이용해서 PWM을 출력하려면, 일정한 동작시간을 카운터로 반복 동작 구현시켜주어야합니다.
    따라서 8Mhz기준 0.000000125초 마다 TCNT0값이 1올라가는데요.
    TCNT0값이 125uS마다 세어서 256이 되면 오버플로우가 발생하는데 이 때 count값이 627이 안되었으니 1증가합니다.
    이렇게 반복하다보면 어느새 count 변수는 627에 다다르겠죠.
    이 때가 0.000000125초 x 256 x 627 되었을 때 시간입니다.
    이 시간은 0.020064초로 약 20mS가 발생되는데요.
    이것을 또 count값이 627일 때 마다 sec변수를 올려주게되어서
    sec변수가 약 50일 때 동작을 시키게 되면 약 1초 동안 모터를 구동시킬수 있는 시간이 생성됩니다.
    이것을 이용해서 while(1)무한 반복구문에서 반복문인 while문으로 sec변수 50동안 10등분되어있는 pwm변수 8이 될때까지 ON pwm변수가 2가 될때까지 OFF를 sec변수가 50이 될때까지 반복하므로 pwm출력값은 80%를 가지게 되는 것입니다.
    pwm변수는 sec변수로 생성된 1초 동안 계속 반복해서 원하는 시간만큼 ON 또 나머지 시간동안 OFF를 반복하는 역할을 합니다.^

    도움이 되셨을지 모르겠네요. ㅎ 감사드립니다.^

  3. Blog Icon
    이도희

    당근이의 AVR 갖고 놀기 까페에 올려진 작품 보고 지역이 울산이라고 하여
    연락 드립니다.

    저는 울산에서 학교 졸업하고 개인 사업을 하고있습니다.
    현재는 산업용 제어기 개발을 주로 하고 있습니다.

    시간이 혹 된다면 만나서 이야기를 좀 해보고 싶은데요
    도움을 드릴수 있는 부분도 있을것 같아서..

    좀 더 깊이 공부 해보고 싶다면 연락 부탁해요..


    010 - 6264 - 7863
    이도희

  4. 안녕하세요^
    당근이 카페를 보고 직접 찾아 들어오셨다니 기쁩니다^, 앞으로 더 배울 생각이구요.
    현재는 조금 바빠서 일 처리가 모두 끝났다음에 연락드려도 받으실수 있을까요?!
    방문해 주셔서 정말 감사드립니다^

  5. Blog Icon
    입문자

    저도 카페를 보고 찾아왔습니다.

    저는 Atmega128 을가지고 모터를 제어하고있는데요

    만약 계속 같은 속도로 할 순 없는건가요?

  6. 안녕하세요.^ 질문주셔서 감사드립니다^
    먼저 구동하고자 하는 모터가 2개 이하 인 경우에는 AVR에 기본적으로 있는 PWM 출력기능을 이용하면 계속해서 연속제어 할수있고, 현재 블로그어 있는 소스로 모터를 제어하고자 한다면 연속제어 시에는 pwm변수를 while문이 아닌 if문으로 비교해야 할것 같습니다.
    if(pwm<6)
    PORTB=0x02;
    else
    PORTB=0x00; 이런식으로 말이죠!!
    도움이 되셨기를 바랍니다^^

  7. Blog Icon
    입문자

    그럼 저기 6은 회전수 가 되는건가요?

    pwm이 6보다 작을땐 회전하고

    아닐땐 정지 인거 같은대 맞나요? 제가 잘못이해하고 있는건 아닌지요..


    음 제가 원하는 속도는 바로 PWM 50%속도 인 즉 두번째 while문의 동작하는 곳의 속도인데요.

    코디비전을쓰고 있는데요 두번쨰 while()문을 전에 반드시 첫번째 while()문부분을 거쳐야만 두번째때 PWM50%가 먹는건가요???

  8. Blog Icon
    입문자

    계속 질문해서 죄송합니다. 진짜 잘몰라서 그럴수도 있는데요 ㅠㅠ

    연속제어 시에는 pwm변수를 while문이 아닌 if문으로 비교해야한다고 하셨는데요

    앞서 설명하신 부분은 이해가 되었는데요

    저 if문을 어디에서 비교를 해야한다는거죠?

    제가 이리저리 다건들려 봤는데 연속적으로 나오지않아;; 제가 잘못 알고 있나 싶어서요 ..

    혹시 motor_pwm 메소드 부분에 있는 while 말씀하시는거 아닌가요?

  9. Blog Icon
    입문자

    코디비전의 메인문에 첫번째 while()문에서 조건은 맞지만 출력을 안하고

    PORTB.0=0;
    PORTB.1=0;
    두번째 while()에서 출력을하니 50%으로 감소된 형태의 속도가 출력이 되네요 ..?

    잘못된건가요;?

  10. pwm변수가 6보다 작을때 동작 6보다 클때는 정지로 한주기가 생성되게 됩니다.
    이 것을 if문으로 구현했을때는 동작처리를 하는 동안 계속해서 pwm변수 5까지 동작 pwm변수 10까지 정지로 듀티비가 50%가 나오게 되고, while문으로 비교했을때는 while일정시간동안 pwm함수로 5동안 모터구동 5동안 모터정지로 구현하면 듀티비가 50%로 출력되게 됩니다^
    설명이 어렵게 된것 같네요^, 부족한 부분있다면 질문남겨주세요^ 감사드립니다

  11. 혹시 만드시는 것이 어떤 입력일 때 PWM 출력을 원하시는 것이라면 위에 While문으로 동작시키는 것은 불가능합니다.
    while문을 사용한 예제는 어떤 원하는 동작시간을 제한해둘 때 유용하게 사용할 수 있구요. 계속해서 연속동작 할때는 if문으로 구성해야 하는데요.^
    while(1)에 있는 프로그램을 모두 제거하시고, 위에서 구성해 드린 if문을 입력하시면 pwm출력이 나온답니다.^^

    코드비전으로 사용하시는 것이라면, 이렇게 구성해야 할것 같네요.^
    while(1)
    {
    pwm=0;
    if(pwm<=5)
    {
    PORTB.0=1;
    PORTB.1=0;
    }
    else
    {
    PORTB.0=0;
    PORTB.1=0;
    }
    }

    이렇게 구성하시면 모터가 정방향으로 PWM 50% 출력으로 연속으로 동작하게 됩니다.^

    그리고 while(1)의 구문에서 두번째 while문이 PWM 50% 출력되는 부분이 맞습니다.^ 그런데 출력시간이 1초로 제한되어 있습니다.^^ 궁금하신점 계속 문의해 주셔도 된답니다.^ 그리고 다시 방문해 주셔서 감사드려요 ㅎㅎ

  12. Blog Icon
    입문자

    그런데 제가 궁금한게 있는데요

    만약에 어느정도 갔다가 멈추는 현상을 한번 구현보았는데요

    avrstudio version

    volatile int cnt = 0;
    void main(void)
    {
    PORTC= 0x00;
    DDRC= 0xff;

    while(1)
    {

    while(cnt<5)
    {
    PORTC=(1<<PC0) | (0<<PC1) | (1<<PC4);
    cnt++;


    }

    if(cnt == 5)
    {
    break;

    }
    }
    PORTC=0x00;
    }

    cnt가 5면 break; 로인해 while문 전체를 빠져나올텐데

    디버깅때문 잘되는데요;; 왜 프로그램 심으면 계속돌아가는 이유는 뭐죠;; 왜 안걸리죠;;? if문이;; 5정도면 티가 안나서 그런가요?

    타이머 인터럽트 안쓰면 답이 업는건가요?

  13. 안녕하세요^ 입문자님 답변드립니다.^
    이렇게 구성하시게 되면 문제점이 많아 집니다.^

    첫번째로 의도 하시는 것은 cnt 값이 5일 때 까지 모터를 구동하다가, cnt변수가 5가 되었을 때 무한루프 while(1)을 빠져나오도록 구성하려고 하시는 것 같은데 그렇게 되면 MCU가 아예 동작을 정지하게 되어버립니다. 즉 프로그램 종료 이지요. 따라서 무한루프 while(1)에서 break;가 되지 않도록 프로그래밍 해야 합니다.^

    두번째로는 타이머/카운터 인터럽트를 사용하지 않으시면 MCU가 구문을 처리하는 속도에 의존해야 하는데 이런 경우에 오차도 심해지고, 변수를 여러번 비교해서 처리해야합니다. 결국 타이머/카운터를 쓰는 것 만 못하게 됩니다. 그래서 타이머/카운터를 이용해서 if문으로 비교 하는 것이 좋을듯 합니다.^

    ps. 저도 한번 구성해서 입력해주신 소스코드로 실험해 보았는데요 cnt 변수가 5 이상 되면 break 덕분에 빠져나오고 바로 동작을 정지하고 이후 어떤 동작도 하지 않습니다. 또 cnt변수가 5까지 상승 후에 변수를 초기화 하는 부분이 없는 것도 문제입니다. 따라서 타이머/카운터0번을 이용해서 PWM을 구현하시는 것을 권장합니다.^
    소프트웨어 자체를 문의할 때는 이메일로 보내주시면 감사하겠습니다.^, 댓글로 입력하는데는 한계가 있네요.^

  14. Blog Icon
    초보자

    메일 확인좀 부탁드립니다^^ ㅎ

  15. 어떤 분이 신가요?? 메일이 조금 여러개 와서요.!

  16. Blog Icon
    초보자

    stragedy@naver.com 입니다^^

  17. 이메일 확인해 보았는데 해당 메일주소로 어떠한 메일도 날아오지 않았습니다. 보내는 이메일 주소를 잘못 보내신것은 아닌지요?

  18. Blog Icon
    김승호

    이게 안된다면 atmega128을 이용한 온도센서에 반응하여 모터 속도변화를 하고싶습니다. 일단 답변 기다리겠습니다. 감사합니다.

  19. 장문의 코드 전문을 댓글로 달아주시지 마시기 바랍니다.^
    블로그 접속시 지연을 유발할수 있어요.
    그리고 메일로 따로 연락드렸습니다.^

  20. Blog Icon
    이승호

    소중한 정보를 올려주셔서 감사합니다.

    DC모터 드라이브는 개인적으로 제작하신건가요 아니면 구입하신건가요 구입하신가면 제품명좀 알려주시면 감사하겠습니다.

  21. 계속해서 도움될 수 있는 정보로 블로그 업데이트 해 나가겠습니다.^
    DC모터 드라이브는 간단한 회로로 사용전류량 800mA급의 모터를 제어 할 수있는 IC인 BA6208을 사용해서 브레드 보드에 간단하게 구성후 테스트 했습니다. 구매 할 수 있는 사이트는 www.eleparts.co.kr 또는 www.devicemart.co.kr이 있고, 다른 여러 사이트가 있으니 참고하셔서 구매하시는데 도움 되시기를 바랍니다.^

  22. Blog Icon
    ky.y

    일반적으로 이런식의 pwm을 이용 하나요? 아님 bingoon님께서 응용 하신건가요? 기발한 발상 같아요!!
    그리고 감사합니다...

  23. 안녕하세요^ 일반적으로는 AVR에서 타이머카운터로 제공하는 하드웨어 PWM을 주로 사용하는데요. 하드웨어 PWM의 단점이 AVR입출력 핀중에 해당 기능을 가진 핀밖에 출력을 하지 못한다는 단점이 있습니다. 그래서 많은 수의 모터나 서보모터를 제어할때는 해당 코드와 유사한 방식으로 여러핀에 출력을 낼수 있는 소프트웨어 PWM을 사용한답니다.^ 부족한 지식 도움 되셨기를 바랍니다 ㅎ

  24. 안녕하세요. 좋은 정보 감사합니다.
    휴대폰 같은데 들어가는 소형 모터제어에 있어서
    키트 크기의 문제에 대해서 어떻게 생각하시는지 궁금합니다.

  25. 안녕하세요.
    휴대폰에 무슨 용도로 사용하시려는지는 모르겠지만, 배터리에 회로가 직결연결되는 것인가요?? 단순히 모터만 제어하는 회로로 MCU + 모터 컨트롤러를 SMD타입으로 PCB 제작한다면 작게 제작은 가능할 것 같습니다. 하지만 SMD타입으로 작게 만드실려면 양면 PCB를 뜨거나 조금 크더라도 단면으로 제작해야 하는데 어느정도 크기 선까지 가능한지 모르겠습니다.

  26. Blog Icon
    기계과전자초보

    안녕하세요. 님의 블로그가 무지한 기계과 학생에게 많은 도움이 되네요 ㅠㅠ
    저두 ATmega128로 DC 모터를 제어 하려고 하는데 전공이 아닌지라 어려움이 이만저만이 아닙니다.
    다름이 아니고 뭔가 여쭈어 볼려구요. 위에 써주신 소스를 AVR Studio로 컴파일 해보닌까 빌드 하는 과정에서 다음 부분에서 'TCCR0A' uncleared(first use in this function) 이라고 뜹니다
    TCCR0B 에서도 마찬가지구요 ㅠㅠ

    TCCR0A = 0x00; // 타이머, 카운터0번 컨트롤 레지스터A Normal (OverFlow)모드로 설정
    TCCR0B = 0x01; // 타이머, 카운터0번 컨트롤 레지스터B 입력클럭 그대로 사용 분주비 없음

    어째서 빌드가 안되는 걸까요 ㅠㅠ

    그리고 따로 예제를 통해 컴파일한게 있는대 빌드와 connect 까지 깔끔하게 진행 되었는대
    모터가 전혀 반응이 없습니다 ㅠㅠ 이게 왜 그런지 전혀 모르겠네요 ㅠ
    제가 작성한 소스도 보여드리고 여쭙고 싶지만 블로그에 쓰는건 예의가 아닌거 같아서리 ㅠ
    일단 답변 기다릴게요 ㅠ 도와주세요 ㅠㅠ

  27. 죄송합니다. 제가 교육받는 일정 탓에 1월 24일 까지 블로그 활동을 할수가 없네요.
    ATMEGA128의 경우 ATTINY2313과 다르게 TCCR0A와 TCCR0B가 TCCR0하나로 합쳐져있기때문에 데이터시트에서 포스팅에 제공된 TCCR0A와 TCCR0B와 동일하게 바꿔주시면 되겠습니다.
    도움되셨기를 바라고 2월 중으로 새포스팅 올리도록 하겠습니다.

  28. Blog Icon

    비밀댓글입니다

  29. 안녕하세요.^
    댓글을 한번에 너무 많이 달아주셔서 단편적으로 답글 달아두도록 하겠습니다. 먼저 위 회로의 경우 PB0번과 PB1번 핀에 BA6208 모터컨트롤러의 입력핀이 연결되어있습니다. BA6208에는 별도의 VCC와 GND를 통해 전원이 공급되고 있는데요. 이 때 PB0번 핀에 HIGH (5V)를 주고, PB1번 핀에 LOW(0V)를 주었을 때 Bin에 5V(논리1), Ain에 0V(논리0) 으로 Bout, Aout에 각각 5V, 0V가 출력되어 모터 입장에서는 5V가 VCC, 0V가 GND가 되므로 모터가 정회전 하게 됩니다. DC모터에서 정회전은 구분이 없으므로, 어느 쪽 방향으로 회전하는 것을 정회전으로 생각하여 주셔야 합니다.^

    역회전으로 회전 하실 때는 PB0, PB1에 연결되어있는 Bin, Ain에 반대로 0V(논리0), 5V(논리1) 순으로 입력하여 주시면 Bout, Aout에 정회전과는 반대로 출력되어 역회전 동작하게 됩니다.^
    설명이 조금 복잡하게 되었네요.^
    참고로 (논리1 = 5V = HIGH = 1), (논리0 = 0V = LOW = 0) 같은 의미입니다. 또한 전압은 높은 곳에서 낮은 곳으로 흐르므로, +에 5V를 연결하고 -단자에 0V를 연결했다면 모터에 걸리는 전압은 5V가 되게 됩니다. 도움 되셨기를 바랍니다.^

  30. Blog Icon
    기계과 전기회로 초보

    모터드라이브를 L298N으로 해서 회로는 다꼽았습니다. ㅠㅠ 그런데 소스를 어떻게 봐꿔야할지를 잘몰라서 문의드립니다.ㅠㅠ

  31. L298 IC는 입력제어, 출력제어 핀은 동일하나 동작 Enable핀에 동작신호를 넣어주어야 IC가 제대로 동작합니다. 이 것을 참고하고 동작 ON/OFF 제어가 필요하다면 AVR의 남는 신호선에 연결하여 제어하고, 필요없다면 IC의 동작조건에 따라 해당 핀은 GND에 연결하거나 VCC핀에 연결하여 줍니다.^

  32. Blog Icon
    기계과 전기회로 초보

    그리고 AVR코드비젼 처음에 설정하실때 10MHZ로 해주고 다른 설정 어떻게하셨는지좀 알려주시면 감사하겠습니다.

  33. 혹시 해당 Attiny2313모듈에 외부 크리스탈 (X-tal)을 연결하시지 않고, 내부에 클럭을 발생시키는 회로를 이용하시는 것인가요? 코드비전을 설정하실 때 주파수는 Attiny2313에서 입력받고 있는 클럭 주파수를 설정하셔 주셔야 합니다. 그리고 코드비전 설정은 http://binworld.kr/4 포스팅에서 코드 위자드 사용부터 참고해 주시면 되겠습니다.^^

  34. Blog Icon
    곽희찬

    포트는 임시로 지정하신건가요?
    모터 두개를 구동하려면 따로 포트가 필요한가요?

  35. 안녕하세요.
    답변이 4일 지체 되어서 죄송합니다. DC 모터를 구동하는 핀은 1개의 모터를 제어하는 IC의 경우 2개의 제어선이 필요하고, 2개를 제어하는 IC의 경우 4개의 제어선이 필요합니다. 그 핀은 AVR에서 IO핀 즉 포트A, 포트B, 포트D에서 특정 포트하나 포트B를 선택했다면 포트B에서 두핀 예를들어 PB0과 PB1을 사용했다면 이 두핀에 IC의 제어선을 연결하고 PORTB = (1<<PB0) | (0<<PB1); 이런식으로 00, 01, 10, 11에 따라서 각각 정역회전이 달라지게 되는 원리입니다.

  36. Blog Icon
    전자과

    ATmega128 PWM을 이용해서 듀티비로 모터의 속도? 세기?를 정하려고 합니다.
    모터제어를 하기위해서 기본으로 한주기를 몇초로 잡는게 적당할까요?
    너무 빨라도 안되고 느려도 안될거같아서요. 실험을 하면서 하자니 개인적으로 가진 기반이 없어서

  37. 안녕하세요.^^
    먼저 주말단위로 끊어서 답변달고 있기에 답변이 늦을수 있는점 양해 부탁드립니다. PWM 듀티비는 한 주기(ON+OFF)에서 ON된 비율로 오실로스코프로 찍어 보시면 평균적으로 산출되는 전압이 변동되면서 모터의 세기가 달라지게 되는 방식인데요, 모터 속도는 이 PWM비율을 잘 조절하시면 속도를 변동 시키실수 있습니다.

    그리고 한주기의 시간은 특수한 목적이 아닐경우에 크게 중요치는 않지만, 가청주파수 대역에 들어가도록 주기를 잡으시면 모터 동작시 마다, 모터 내부의 코일에서 삐~~하는 소리가 들릴 수 있으므로, 가청주파수 대역을 벗어나도록 어느정도 높은 주파수로 설정하시길 바랍니다.^ 가청 주파수 대역은 16Hz ~ 20kHz이니 1/20kHz 하시면 주기가 계산됩니다.

    그럼 부족하지만 작품만드시는데 도움되시길 바랍니다.^^

  38. Blog Icon
    공대초보

    안녕하세요.
    모터 제어하는 법 막막했는데 어느 정도 실마리가 보이는 것 같네요. 감사합니다.
    그럼 온도를 감지해서 특정 온도 구간마다 모터의 속도를 다르게 제어하고 싶은데 어떤 식으로 해야하나요.

    qkdthd12@hanmail.net
    제 메일입니다. 답변 기다리겠습니다. 정말정말 감사합니다 ㅠㅠ

  39. Blog Icon
    이종욱

    안녕하세요. BLDC 모터 제어하는 코드비젼 코드 작성중입니다.
    토크센서를 이용하여 atmega로 ADC하여 ADC구간에따라 모터 속도제어를 하려고합니다.

    1. 센서의 신호에서 1.5~2.1V이고 10kgF~40kgF 사이의 사인값의 피크치가 1.65V, 1.8V, 1.95V, 2.1V 입니다.
    이것을 ADC값으로 바꾸게되면 338 , 368, 400, 430 입니다.

    2. 모터컨트롤러에서의 pwm이 1.8V(pwm0)~4V(pwm100)입니다. 총 5구간으로 나누게 되어
    ADC<338 일때 Vout = 1.8V (Vout 은 모터로 가는 출력전압입니다.)
    338=<ADC<386 일때 Vout = 2.24V
    386=<ADC<400 일때 Vout = 2.68V
    400=<ADC<430 일때 Vout = 3.12V
    430=<ADC<1023 일때 Vout = 3.56V
    이렇게 가능 할까요?

티스토리 툴바