ATtiny26L의 AD 변환과 PWM 출력제어

AVR Project 조회 수 30321 추천 수 136 2005.07.12 10:27:18




http://www.geocities.jp/kuman2600/k2adc.html출처 : www.ipstack.co.kr

손잡이를 돌리면 모타의 회전이 바뀐다.
커다란 가변권선 저항을 직렬로 넣어 콘트롤하는 일이 있습니다.
Tiny26L은 AD변환과 PWM기능이 있으므로,
가변저항으로 변화된 전압을 지지털 신호로 바꾸어
이 수치로 PWM 제어를 하면 VR의 제어각에 대응하는 전력을 얻을 수 있다고 생각했습니다.
로터리 엔코더를 쓰면 직접 PWM 제어를 할 수 있으나
그 공부는 나중에 하겠습니다.

1단계로 출력은 LED의 광량변화로 모니터링합니다.
또한, PWM에 쓰는 디지털 숫치는 0~255로 하고,
그 상위 4비트를 4개의 LED로 2진 표시를 하였습니다.
255이상의 상위 1~16까지를 표시하고 있으나,
4비트라면 상당히 감각적으로 수치를 알 수 있으므로
간단한 표시에는 쓸 수 있다고 느낍니다.
    
AD변환도 PWM도 잘 몰라서 데이터 시트를 몇번인가 읽었고,
또한 선배의 홈페이지에 고생해서 프로그램도 써 보았습니다.
결과적으로 초기의 목적을 달성하기 위해서는
자신이 쓴 프로그램이 있어도 무었가를 알 수 없었습니다.
시간을 두고 공부한 뒤에, "이제야 이해가 쉽게 되었습니다"라고
했을 때까지는 배웠다고 할 수 없습니다.

출력 단자를 오실로 스코프로 보면, 주기는 2ms 정도이고
VR의 회전에 따라서 Duty 비율이 변화하는 것을 알 수 있습니다.
다음은 회로도와 프로그램입니다.
공부가 되는 데로 코멘드를 넣을 것 입니다.


회로도의 아래(9볼트를 전원으로 사용하는 전원안정화 회로)부분을 나중에 추가하였습니다.

/********************************************************************************** 
AD변환과 LED를 4행표시 그리고 PWM제어
2004.06.05  08.14
20050214판 대응 05.02.27

100KΩ의 VR전압을 VCC에서 0V까지 변화하고 그 전압을 AD변환하여
0-255의 디지털 데이터를 수치로 구한다 이 수치를 기준으로 PWM제어를 한다.

VR의 회전각도에 따라서 Duty를 변화한다
VR 단자의 접속을 변경하여 Duty를 반전할 수 있다.

AD변환 후의 수치(8비트)를 보기 위해서 상위 4비트를 PA의 LED4개에 출력한다.
2진 데이터를 4행으로 16~255를 안다.

PWM 출력은 2번핀(PB1)이다.
ADC의 아날로그 입력은 1번 핀이다(PA7 혹은 ADC6)

MCU는 ATtiny26L
출력단자에 드라이버를 붙히면, VR로 모터제어가 가능하다.
*********************************************************************************** */
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

volatile char int_flag=0;      //변수선언 및 초기화

SIGNAL (SIG_OVERFLOW1)    //ADC 인터럽트 초기화를 signal.h에 숨겨 놓음)
{
  int_flag=1;            // ADC 인터럽트 플랙을 처음 1로 셋트함  
}

void wait(void);

/*  메인 루틴 */
int main (void)
{
  int data;               //data는 정수(부호있는16비트 변수)  

  DDRA=0x7F;           // PORTA는 출력모드 PA7은 입력모드
  DDRB=0x7f;           // PortB 0--6=output
  TIMSK=(1<<TOIE1);   // 타이머0 인터럽트를 허가

  OCR1A=0;            // 기준레벨
  OCR1C=255;          // PWM의 최대치
  TCCR1A=130;         // PWM 허가(작동시작)可
  TCCR1B = 0x04;      // PWM 입력클럭의 분주비 =1/64

  // ADC
  ADMUX = (_BV(ADLAR)|6);                        
  // ADC0는 AVCC를 기준으로 데이터는 좌로 9개
  ADCSR = _BV(ADEN) | _BV(ADFR) | _BV(ADSC);    
  // AD변환허가, 연속변환, AD변환시작

  sei(); /* 인터럽트 허가 */  
  //여기까지는 MCU가 리셋되면 1회만 실행된다

  for( ; ; )                //무한 반복의 시작
                           // for(;;)와 while(1)은 완전히 같은 명령임.
  {
    if(int_flag==1)      //인터럽트 플랙이 1이면 다음 { }안의 루틴을 실행
    {
      data = ADCH ;     //data 변수에 AD변환기의 결과값을 읽어 넣는다
      int_flag=0;         //인터럽트 플랙을 리셋트한다  
      cli();                 //인터럽트 금지

      OCR1A=data;
    }                       //조건 분기의 끝 다음 명령은 무조건 실행됨

   PORTA=(data>>1);   // PB6-3에 출력하기 위해 1비트 시프트
   sei();                   // 표시를 출력하고 인터럽트를 허가(재 시작)
  }                         //무한 반복문의 끝
}                           /*   메인루틴 끝 */

void wait(void) // 시간지연 루틴 (서브루틴 =메인이 아님 =추가루틴)
{
  uint16_t j;            // j는 부호없는 16비트 정수
  for(j=0;j<30000;j++)    //j를 0에서 30000까지 1씩 반복하여 증가(여기서는 지연목적)
  {         // 3002로 하면 불안정해짐 <--원인불명(컴파일러의 int 변수값 제한?) 原因不明
    j = j;                       // dummy
  }
}

List of Articles
번호 제목 글쓴이 날짜 조회 수