회원가입 ID/PW 찾기
AA
atmega 128로 dc 모터제어를 꾸미고 있습니다.

그런데 제가 가변저항으로 %를 바꾸는 형식으로 모터 제어를 할려고 하는데

프로그래밍을 할때 가변저항을 따로 프로그래밍을 해야 한다고 하는데 어떻게 하는건지 모르겠네요..

adc1을 통해서 가변저항을 연결했습니다..

능력자 계시면 프로그래밍 소스 힌트나 좀 올려주시면 감사하겠습니다.

열심히 활동할께요..ㅠㅠ
댓글 3
  • No Profile
    <meta http-equiv="content-type" content="text/html; charset=euc-kr"> AVR 마이크로프로세서의 A/D converter활용 실습 <meta name="generator" content="Namo WebEditor v6.0">

     

    AVR 마이크로프로세서의 A/D converter활용 실습

     

    1.         실험 실습 내용 학습 목표

     

    l         AVR마이컴의 내장 A/D컨버터 활용법 이해

    l         LM 35 온도 센서의 활용법 실습

    l         LM385 voltage reference 이해와 응용법

    l         A/D 컨버터 관련 레지스터 사용법 이해

     

    2.         실험 실습 준비 항목

     

    l         실습회로 보드 (KEST-B1 보드)

    l         Atmega8535 CPU, 5V전원, 4MHz 혹은 8MHz Crystal 1,  22pF 콘덴서 2

    l         Reset버튼용 스위치 1, 10K 저항 1

    l         16x2 캐릭터 LCD 1 , 가변 저항 10K 1

    l         LM35 온도센서 1,  LM385-1.2 전압 레퍼런스 1, 포텐셜미터 5K 1

    l         WinAVR GCC 컴파일러

    l         Text Editor ( 각자 편리한 에티터를 사용하면됨 )

    l         PonyProg 프로그램 v.2.6 이상 ( v.2.6 이상에서만 ATmega8535 지원)

    l         ISP 모듈과 Serial Cable RS232C통신 포트를 갖춘 Window기반 PC 1

     

    3.         핵심 학습 내용

    이번 실험에서는 가장 유용하게 생활에 활용할 있는 온도센서의 AVR interface 방법에 대해 학습하고,실험해 볼것이다. LM35온도 센서와 LM385 전압레퍼런스 칩이 필요하며, 레퍼런스 전압을 조절하기 위하여, 정밀 가변저항인 포텐셜미터가 필요하다. 만일 온도를 0.5’C단위로 대략적으로 측정 한다면, LM385 전압레퍼런스는 사용하지 않아도 되겠지만, 이럴경우 시스템에 입력되는 전원 전압의 변동에 따라서 같은 온도 상태에서도 측정 온도 값이 변동될수 있으므로, 우리는 여기서 LM385 전압 레퍼런스를 함께 사용하여 이러한 온도 오차를 조금이나마 줄여 보도록 하겠다. LM385 입력 전원의 변동에 상관없이 언제나 1.2V혹은 LM385-2.5 경우엔 2.5V 기준 전압을 출력해 준다. 우리가 사용하는 칩은 LM385-1.2이다.

    LM35온도 센서는 온도의 변동에 따라 온도값에 해당하는 전압을 출력하여 온도 상태를 알려주는 온도 센서이다. 이것은 1’C 10mV 출력해 준다. 측정온도가 24.5’c 경우라면 245mV 출력되는 것이다. 우리가 이번 AVR CPU A/D내장 기능을 실험하기 위해 온도 센서를 사용하는 이유는 온도 값이 전압으로 출력 되므로, 출력된 전압을 AVR A/D컨버터를 사용하여, 디지털로 바꿔 주면 온도 값을 알수있기 때문이다. 그리고 이렇게 변환된 온도 값을 LCD 출력해 주면 일상 생활에서 편리하게 사용할 있는 디지털 온도계가 되는것이다.

    4.         LM35DZ 아날로그 온도센서 & LM385-1.2 전압레퍼런스

     

     

    LM35온도 센서는 위의 그림에서 보듯 다리가 3개인 트랜지스터 모양을 하고 있다.

    이것은 아래에서 그림이므로 정면에서 보았을 , 좌측핀이 Vcc전원이고, 가운데 온도 값에 해당하는 출력 전압이 나오는 핀이며, 우측 핀이 GND핀이다.

    LM35 ‘C 10mV 출력이 나오므로, 이렇게 출력된 전압을 1mV까지 정확히 읽을수만 있다면, 0.1’C 정밀도를 가진 디지털 온도계를 만들수 있는것이다.

    이런 아날로그 온도센서를 AVR에서 활용하는 방법은 바로 AVR 내장된 A/D컨버터를 사용하는 것이다. AVR 아주 우수한 10비트 정밀도를 가진 A/D컨버터를 가지고 있어 아날로그 값을 1024 단계까지 읽어 낼수 있다.

    AVR 아날로그 컨버터는 모두 8개의 채널을 가지고 있는데, PORTA 연결되어 있다. 우리는 PORTA PA0 온도센서를 연결하였으며, 좀더 정확한 온도 검출을 위해 레퍼런스 전압을 1V 맞추어 놓았다. 간단히 아날로그 입력을 연결하는 방법을 아래 그림에서 보여준다.

     

     

    또한 그림에서 기준 전압 용으로 LM385-1.2칩을 사용하는데 칩은 매우 정밀한 기준 전압을 출력해 준다.

     

     

     

    LM385 응용 회로는 위에서 보는것과 같다. 다만, 우리는 5V전원 전압을 사용하므로, 저항을 10K옴을 사용하였다.

     

    5.         AVR A/D컨버터 관련 레지스터들

     

    우선 AVR A/D컨버팅 계산은 다음과 같이 계산된다. 여기서 Vref 우리가 위에서 설정한 1V 전압값이 것이며, Vin 바로 LM35온도 센서에서 입력되어지는 아날로그 전압이 되는것이다.

     

     

    이렇게 변환된 디지털 값이 바로 ADCL ADCH 각각 저장되게 된다. AVR A/D컨버터는 10비트의 해상도를 가지고 있으므로 ADCL 8비트와 ADCH 2비트만이 유효한 값이 된다.

    AVR 8채널의 A/D 입력 라인을 가지고 있는데, 이것들 어느것으로 부터 아날로그 값을 받아 것인지는 ADMUX레지스터에서 설정해 주게 되며, 레퍼런스 전압을 어떤 종류를 사용할지도 레지스터에서 설정해 준다. 우리는 이번 실험에서는 AREF 외부 기준 전압을 사용한다.

     

     

     

    아래의 ADCSRA AD컨버터 전반에 대한 설정을 해주는데, A/D 활성화 시키고, 인터럽트를 설정해 주는 등의 역할을 한다.

     

     

    또한 SFIOR레지스터의 일부 비트들로 A/D컨버터와 관련이 있는데, ADTS2,1,0 설정에 따라 A/D컨버터에 영향을 주게된다. 우리는 여기서 FreeRunning모드라는 연속적인 A/D컨버팅 모드로 설정해서 온도를 검출 것이다.

     

     

     

    6.         실험 실습 회로 구성

     

    7.         실험 실습 프로그램 소스

    //**************************************************************************************

    //

    //

    //

    //             마이크로프로세서 실습 Atmega8535 KEST-B1 @ Kaywon University 2004

    //

    //                          by  Professor  S.J. Park

    //

    //               Atmega8535 LM35 Thermosensor interface test ver. 1.0

    //

    //**************************************************************************************

     

     

    #include <avr/io.h>

    #include <avr/pgmspace.h>

     

     

    #define TRUE            1           

    #define FALSE           0          

     

    typedef unsigned char   INT8U;

    typedef signed char     INT8S;

    typedef unsigned int    INT16U;

    typedef signed int      INT16S;

    typedef unsigned long   INT32U;

    typedef signed long     INT32S;

    typedef float           F32;

    typedef double          F64;

    typedef unsigned char   BOOL;

     

    unsigned char __attribute__ ((progmem)) msg1[]=" Kaywon Emb.Dept";

    unsigned char __attribute__ ((progmem)) msg2[]=" KEST-B1  rev.A ";

    unsigned char __attribute__ ((progmem)) Usermsg1[]=" Digital Thermo ";

    unsigned char __attribute__ ((progmem)) Usermsg2[]=" LM35DZ :       ";

    unsigned char __attribute__ ((progmem)) ASCII[]="0123456789ABCDEF"; // 16 ASCII 코드

    unsigned int result; 

    unsigned int CC,DD,EE;

    unsigned char Thigh,Tlow,bcdh,bcdl,T100,T10,T1,T01;

    unsigned char lo_val, hi_val;

    //-----------------------------------------------------------------

    //

    // LED Port 정의

    //

    #define LED_PORT              PORTB

    #define LED_DDR               DDRB

    #define LED0           PB0

    #define LED1           PB1

     

    void IO_Init(void)

    {

       outp(0xFE,DDRA);

       outp(0xe3,DDRB);

       outp(0xFF,DDRC);

       outp(0xF2,DDRD);

       UBRRL=25; // 9600bps, 4MHz

       UCSRB=0x18;

    }

     

     

    //Delay 함수

     

    void UTIL_DelayUS(INT16U wUS)

    {

        INT16U  wDelayLoops;

        register INT16U i;

       wDelayLoops = (wUS + 3) / 8;   

        for (i=0; i<wDelayLoops; i++);               

    }

     

    void UTIL_DelayMS(INT16U wMS)

    {

        register INT16U i;

     

        for (i=0; i<wMS; i++)

            UTIL_DelayUS(2000);        

    }

    //----------------------------------------------

     

    INT8U ReadRS232(void)

    {

       while(!(UCSRA & ( 1 << RXC)));

       return UDR;

    }

     

    void SendRS232(INT8U TXdata)

    {

       while(!(UCSRA & ( 1 << UDRE)));

       UDR=TXdata;

    }

     

    //----------------------------------------------

    #include "LCD4.h"

     

    //----------------------------------------------

     

    int main(void)

    {

      

       INT8U i=0,j=0,RxData;

       INT8U k=0;

     

     

      

       IO_Init();

       L_INIT();       // LCD 초기 설정

       DISPLAY();      // msg1, msg2 디스플레이

       UTIL_DelayMS(2000);       

       UserRamWrite1();

     

     

      

       PORTB=0x01;

       UTIL_DelayMS(1000);

       PORTB=0x02;

       UTIL_DelayMS(1000);

       PORTB=0x01;

       UTIL_DelayMS(1000);

       PORTB=0x02;

       UTIL_DelayMS(1000);

       PORTB=0x00;

     

     

      

       COMMAND(0x01); // LCD clear?

     

       COMMAND(0x02);        // 커서를 홈으로

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

             CHAR_O(PRG_RDB(&Usermsg1[i]));   // 데이터를 얻어서 LCD 데이터 출력

            }

         // 2라인 데이터 출력

            COMMAND(0xc0);        // 커서를 라인 2

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

             CHAR_O(PRG_RDB(&Usermsg2[i]));   // 데이터를 얻어서 LCD 데이터 출력

          }

      

     

       outp(0, ADMUX);

       outp((1<<ADEN)|(1<<ADSC)|(1<<ADATE)|0x04, ADCSRA);

      

      

       for(;;){

     

      

       PORTB=0x00;

     

       UTIL_DelayMS(1000);

     

       PORTB=0x02;

    //------------------- LM35 Test ------------------

       lo_val = inp(ADCL);

       hi_val = inp(ADCH);

       result = (unsigned int)(0x00ff & hi_val );

       result <<= 8;

       result |= (unsigned int)(0x00ff & lo_val );

     

     

        CC=result;         // Vref 1V 일때  , 0.1 단위의 정밀온도계

      

      

      

       DD=CC%1000;

       EE=CC/1000;

       T100=EE;

       CC=DD;

       DD=CC%100;

       EE=CC/100;

       T10=EE;

       CC=DD;

       DD=CC%10;

       EE=CC/10;

       T1=EE;

       T01=DD;

     

       Thigh=T10;

       Thigh=(Thigh<<4)|T1;

       Tlow=T01<<4;

     

        // 온도 디스플레이

       

        COMMAND(0xc9); // 커서 조정(LCD8.h 참조)

      

       if(T100==0){ CHAR_O(' '); } 

       else{    CHAR_O(T100 +0x30);  }

      

       if(T10==0){ CHAR_O(' '); } 

       else{    CHAR_O(T10 +0x30);  }

     

        CHAR_O(T1 +0x30);  

       CHAR_O('.');

        CHAR_O(T01 +0x30);

        CHAR_O(1);

        COMMAND(0xd0);               // 커서 조정

     

      

       }

      

      

     

     

      

      

       return TRUE;

      

    }

     

    소스에서 가장 핵심적인 코드는 다음의 줄이다. 줄의 코드가 AVR A/D컨버터 기능을 설정하고 동작 시키는 것이다.

     

              outp(0, ADMUX);       // Digital 변환할 Analog 입력핀을 PA0 선택하는 명령

             

              outp((1<<ADEN)|(1<<ADSC)|(1<<ADATE)|0x04, ADCSRA);

                                                 // A/D컨버터 제어 레지스터인 ADCSRA 설정하는 코드로

                                                 // ADEN 1 설정하여, A/D컨버터 기능을 활성화 시킨다.

                                                 // ADSC 1 설정하여, A/D컨버터의 컨버팅을 시작시킨다.

                                                 // ADATE 1 설정하여, 자동으로 계속적인 A/D변환을 하도록 한다.

     

    나머지 부분은 장에서 공부한 LCD디스플레이 코드와 거의 유사하다. 새로 추가된 부분 만을 설명 하자면

     

    unsigned char __attribute__ ((progmem)) Usermsg1[]=" Digital Thermo ";

     

    unsigned char __attribute__ ((progmem)) Usermsg2[]=" LM35DZ :       ";

     

     

    온도 값을 표시해 주는 메인 화면을 표시할 문자열을 개의 프로그램 메모리 영역에 저장 하였다.

    문자열은 main함수 내의 다음과 같은 코드로 LCD화면 위에 표시되게 된다.

     

              COMMAND(0x02);        // 커서를 홈으로 , 커서를 윗줄의 1번째 칸으로 가져간다.

     

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

     

                        CHAR_O(PRG_RDB(&Usermsg1[i]));   // Usermsg1 문자데이터를 얻어서 LCD 출력

     

                               }

     

         // 2번째 라인 데이터 출력

     

                          COMMAND(0xc0);        // 커서를 2번째 라인으로

     

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

     

                        CHAR_O(PRG_RDB(&Usermsg2[i]));   // Usermsg2 문자데이터를 얻어서 LCD 출력

     

          }

     

     

    이로서, 온도를 표시해 주기 위한 코드는 준비되었고, 실제로 온도를 가져와 계산해서 화면에 표시하는 실제 코드에 대해 설명하겠다. 코드는 main함수 안의 for() 내에 위치해 주기적으로 반복하며, A/D컨버터에서 변환된 디지털 값을 읽어와 LCD 표시할 있도록 값을 100,10,1자리의 숫자문자로 분해해 LCD 보내주는 코드 이다.

     

     

    //------------------- LM35 Test ------------------

     

              lo_val = inp(ADCL);                    

              hi_val = inp(ADCH);

              result = (unsigned int)(0x00ff & hi_val );

              result <<= 8;

              result |= (unsigned int)(0x00ff & lo_val );

     

    A/D변환된 디지털 온도값은 ADCL ADCH 저장되게 된다. 이때 ADCH 하위 2비트만이 유효하다, 이유는 앞에서도 설명하였듯 Atmega8535 A/D컨버터는 10비트 이므로 하위8비트와 상위 2비트로 나누어 레지스터에 저장되어 있는데, 상위 레지스터 8비트 값를 읽어와서 하위 2비트만을 사용하면 되는것이다.

    코드에서는 하위 값을 lo_val, 상위 값을 hi_val변수에 일단 저장한 16비트 변수인 result 상위 값을 넣고 좌로 8비트 쉬프트 시킨후 하위 값을 ‘OR’연산하면 16비트의 변수 값이 만들어 지게된다.

    변수 값이 바로 LM35 나타내는 온도 자체인것이다.

    그러나 온도 값은 16비트 이진수로 되어 있으므로 LCD 바로 보내면 이상한 깨어진 문자가 화면에서 표시될 뿐이다. 이것을  우리가 쉽게 읽기 위해서는 3자리 혹은 두자리의 숫자로 바꾸어 하나씩 LCD 전송해표시해 주어야 한다. 그렇게 하기위해 16비트 이진 값을 100단위,10단위,1단위의 3개의 숫자로 바꿔 주는 코드가 필요하다. 다음의 코드에서 그런 연산이 이루어 진다.

     

             CC=result;                   // result온도 값을 16비트 변수 CC 넣는다.

             

             

             

              DD=CC%1000;           // CC 1000으로 나누어 나머지를 임시로 DD변수에 저장한다.

     

              EE=CC/1000;              // CC 1000나누어 EE 저장한다.

     

              T100=EE;                   // EE값을 100자리 온도 문자변수 T100 저장한다.

     

              CC=DD;                      // 아까의 나머지 값인 DD CC 대치한다.

     

              DD=CC%100;             // CC 100으로 나누어 나머지를 임시로 DD변수에 저장한다

     

              EE=CC/100;                // CC 100나누어 EE 저장한다

     

              T10=EE;                     // EE값을 10자리 온도 문자변수 T10 저장한다

     

              CC=DD;                      // 아까의 나머지 값인 DD CC 대치한다

     

              DD=CC%10;               // CC 10으로 나누어 나머지를 임시로 DD변수에 저장한다

     

              EE=CC/10;                 // CC 10나누어 EE 저장한다

     

              T1=EE;                      // EE값을 1자리 온도 문자변수 T1 저장한다

     

              T01=DD;                    // 아까의 나머지 값인 DD 0.1단위 온도 문자변수 T01 저장한다

     

     

              코드에서 100단위의 온도 값을 100 아닌 1000으로 나눈이유는 온도값이 0.1 단위로 result 저장되어 있기 때문이다.

     

        // 온도 디스플레이

       

        COMMAND(0xc9);      // 커서 위치를 두번째 10번째 자리에 위치시킨다.

             

              if(T100==0){

    CHAR_O(' '); }  // 만일 100단위 온도 값이 0이면 공문자를 LCD 쓴다.

     

              else{   

    CHAR_O(T100 +0x30);  }           //  100단위 온도 값에 0x30 더하여 LCD 쓴다.

                                                            // 그이유는 T100에는 실제 100자리 온도 값에 해당하는 0~9

    // 까지의 숫자값이 들어 있는데 숫자값과 LCD 표시할 ASCII ‘0’~’9’ 값과는 0x30 , 48 차이가 있어 이값을 더해주면 숫자0 문자 ‘0’ 되는것이다.

             

              if(T10==0){

                               CHAR_O(' '); } 

              else{   

      CHAR_O(T10 +0x30);  }           //  10단위 온도 값에 0x30 더하여 LCD 쓴다.

                                                                         

     

          CHAR_O(T1 +0x30);                                  //  1단위 온도 값에 0x30 더하여 LCD 쓴다

     

              CHAR_O('.');                                                  // 컴마 ‘.’ 화면에 찍어 준다.

         

              CHAR_O(T01 +0x30);                                                   //  0.1단위 온도 값에 0x30 더하여 LCD 쓴다

       

    CHAR_O(1);                                                 // 사용자 정의 문자로 만들어 놓은 특수 문자인 ‘c 써준다.

       

              COMMAND(0xd0);                           // 커서를 화면 바깥으로 보내 깜박이는 것을 방지한다.

     

    #.주의 :  이 문서는 교수님이 쓰신책으로 저작권 있는 내용 허락없이 도배 하거나 상용화 하시면 법의 저촉을 받습니다.

     출처 : http://cafe.naver.com/allcyber/1272

  • No Profile
    글쓴이 이어달리기 10.06.20 22:40 댓글 좋아요 0 싫어요 0

    감사합니다...혹시 다른 질문 생기면 또 올리겠습니다. 감사합니다.^^

  • No Profile
    답변엑박.. ㅠㅠ

하드웨어 설계 및 개발에 대하여 개발자들이 자유롭게 토론하는 공간입니다.
- Q&A, 자유주재 토론, 관련 정보 공유
- 분야 : 마이크로프로세서 응용, 전기/전자(아날로그/디지털) 회로 설계, C/C++ 프로그래밍, 펌웨어,
         PCB Artwork, 트러블슈팅 등 하드웨어 설계에 관한 전반인 내용
※ 게시글에 맞는 분류를 선택하여 글을 작성해 주시면 쾌적한 사이트 운영에 많은 도움이 됩니다.
※ 하드웨어 인사이트는 회원들간의 거래정보를 게재할 뿐이지, 그 어떤 책임과 의무도 가지지 않습니다.

search
번호 분류 제목 글쓴이 조회 수 날짜
548 마이크로프로세서 HOTatmega8 어셈블리어 부탁 드릴게요 qusgmltjd 1549 2010.06.20
마이크로프로세서 HOT가변저항을 사용하는데 잘 모르겠네요...3 이어달리기 2171 2010.06.19
546 마이크로프로세서 HOT[도와주셔용] "ATmega16 + 16MHz 외부 클럭 + ISP" 인데, 동작이 안됨 !!4 쑤잉아 3797 2010.06.19
545 마이크로프로세서 HOTATmega를 공부하기 어렵죠?11 genid 1740 2010.06.19
544 마이크로프로세서 HOTDC 모터의 위치 제어2 에르피온 1913 2010.06.16
543 마이크로프로세서 HOT[FND] 4-digit 7 segments에 관련된 schematic 자료가.. 사랑니 2186 2010.06.15
542 마이크로프로세서 HOTAtmega128 과 모터 모듈(BA6208) 을 사용한 DC 모터제어1 왕쓰 3800 2010.06.15
541 마이크로프로세서 HOT8051 에 대하여 .. 개굴이잉 1008 2010.06.14
540 마이크로프로세서 HOT답답한 마음에 몇자 적어 봅니다.8 돌롭 1293 2010.06.14
539 마이크로프로세서 HOTpwm을 이용한 dc모터제어6 d2comet 2348 2010.06.12
538 마이크로프로세서 HOTavr을 이용해서 조도 제어와 색온도 제어 초보자가 가능할까요?2 AVR 초보자 1610 2010.06.11
537 마이크로프로세서 HOT8051 소스에 관해서요..3 Do 1275 2010.06.11
536 마이크로프로세서 HOT가입하자마자 질문 먼저 올려서 죄송해요 하지만 꼭 보고 수정 부탁드려요.!6 막멀티 1259 2010.06.10
535 마이크로프로세서 HOTCAN통신 관련 질문이요 jeon_goon 1124 2010.06.09
534 마이크로프로세서 HOT8051을 배우기 시작한 대학생입니다.2 진진진 1032 2010.06.09
533 마이크로프로세서 HOT8051 과 RFID 단말기 연동 질문 입니다~1 뒹굴뒹굴 1123 2010.06.09
532 마이크로프로세서 HOTATmega128로 기판을 짜봤는데요.2 d2comet 1247 2010.06.08
531 마이크로프로세서 HOT재미는 주제입니다.. 제발 답변을..ㅠㅠ1 절제하는늑대 1074 2010.06.07
530 마이크로프로세서 HOT가변 저항 연결에 대한 질문입니다.6 dlgodnjs 3176 2010.06.07
529 마이크로프로세서 HOTAT89S52하고 AT89S51에 대하여2 끈기 1464 2010.06.06
Prev 1 ... 18 19 20 21 22 23 24 25 26 27 ... 50 Next
  • 부모만큼 가장 자연스럽고 적합한 교육자는 없다.
    - 헤르바르트
  • * 납포인트 정보 *
  • 글 작성 : 3
  • 댓글 작성 : 1
  • 내 글이 추천받음 : 1
저작권법에 위배되는 콘텐츠는 등록 불가하며, 저작물에 대한 권리는 저작자에게 있습니다.
Copyright 2006-2021 © hardwareis.com, All rights reserved.