본문 바로가기

만들기 / making/sensing workshop

ATmega168 ADC 2

ATmega168 ADC 2

(아직 수정중입니다. 현재 Resolution 쪽은 거의 수정 완료입니다.)
 
ADC 에 있어서 가장 중요한 두가지
 
1. Resolution
2. Sampling Frequency

 
 
//비행기의 예
 
비행기 이륙 때는
여러 스위치
순서에 맞춰 작동
 
 
//기차의 예
 
파리->모스크바
선로가 파리에서부터 모스크바로
올바르게 순서대로 변경되가야할 것이다.
 

 

 
1. Resolution
 
Resolution은 해상도를 의미한다.
해상도가 풍부하다 함은 그만큼 표현력이 좋다는 의미이기도 하다.
 
//예
디지털 카메라, 디스플레이
 
ATmega는 10bit와 8bit의 Resolution을 지원한다.
 
그럼 Resolution이 10bit 라는 것은 무슨 뜻일까?
 
이는 ADC에 있어 아날로그 신호(전압)를 2^10(=1024) 단계의 디지털 신호로 변환한다는 뜻이다.
 
//예
5V의 전압을 10bit Resolution으로 ADC한 경우
디지털 신호 0 == 5/1024V
디지털 신호 1023 == 5V
반면, 5V 전압을 8bit Resolution으로 ADC한 경우
디지털 신호 0 == 5/256(=2^8)V
디지털 신호 255 == 5V


 
Resolution에 있어 또 다른 중요사항은 AREF이다.
AREF는 ADC에 있어 인식할 아날로그 값(전압)의 최대값을 의미한다.
즉, AREF가 5V로 설정되있으면 ADC에 5V를 초과하는 전압을 흘려도 5V로만 인식하는 것이다.
반면, AREF가 5V인 상태에서 최대 2.5V의 전압을 내보내는 센서를 사용한다면 어떻게될까?
 
Resolution을 10bit라 가정하면
본래 사용자가 의도한 ADC 결과는 2.5V의 전압이 1024단계의 디지털 신호로 변환되는 것이다.
디지털 신호 0 == 2.5/1024V
디지털 신호 1024 == 2.5V
그러나 결과는 512단계로 변환된 디지털신호다.
디지털 신호 0 == 2.5/512V
디지털 신호 512 == 2.5V
 
왜냐하면 AREF(최대값)로 지정된 5V에 비해 들어오는 센서의 최대값이 절반인 2.5V 에 불과하기에 결과적으로 원하던 Resolution에 절반밖에 못 미치는 Resolution 결과를 받게 되는 것이다.
따라서 센서가 보내는 전압의 최대값에 맞춰 AREF를 수정해줘야 할 것이다.
 
ATmega의 기본 AREF값은 1.1V이다.
 

 
여기서 잠깐 상식!!
입력 전압의 최대값은 마이크로 컨트롤러에 들어오는 전압을 넘어선 안된다.
V =< VCC

 

Resolution에 관련한 또다른 이야기들

Sound와 Resolution
8bit 과거 버블버블, 초창기 핸드폰
10bit
24bit 최신 장비 및 고가의 디지털 레코더 등등

Graphic과 Resolution
디지털 카메라의의 한 픽셀은 4개의 화소를 가지고 있다.
따라서 한 픽셀에는 RGB의 삼원색 화소중 한 색깔의 화소가 많고 이러한 사실이 각 디지털 카메라 브랜드마다의 색감차이를 만들어낸다.

//예
RGBB
RGGB
RRGB

한 화소당 8bit Resolution이라면,
한 픽셀은 8*4bit의 데이터.
10M Resolution의 디지털 카메라라면 하나의 이미지의 데이터량은 8*4*10Mbit
(여기서 화소의 Resolution은 색에 대한 해상도를, 10M Resolution은 한 화상이 얼마나 많은 픽셀로 표현되는가를 의미한다.)

어마어마한 데이터량이다.
그래서 디지털 카메라는 포착한 화상을 저장하느라 연사가 느리다.
이러한 문제의 해결을 위해 연사력을 높인 디지털 카메라는 CF 카드와 더불어 RAM을 사용.(연사이미지의 저장에 일시적으로 RAM을 사용하는 것이다.)

 

 

2. Sampling Rate

Sampling Rate는 단어 그대로
얼마나 자주 Sampling, 즉, ADC를 수행하는가를 의미한다.

ATmega는
8bit res 에서 최대 76.9kSPS
10bit res 에서 최대 15kSPS 의 Sampling Rate를 가진다.
(kSPS == 10^3 Sampling per Second, 즉, 76.9kSPS란 초당 76900번 ADC를 수행한다는 이야기다.)

 

사인파의 예

 

그렇다면 최적의 Sampling Rate는?

Nyquist Theory

만약 1kHz를 샘플링한다면

최소 두배가 되어야 원활

두배에 해당하는 주파수를

Nyquist rate

보통은 2배 이상의 샘플링

over sampling


 

GPS5

뇌파4

카메라프레임이야기 놓치는 컷

조명

디스플레이

6개의 ADC 채널

왜? 6개가 아니라 6채널인가?

ADC가 6개인게 아니라 ADC는 1개, 채널이 6개

 

따라서 실질적으로는

76900/6(8bit res)~15000/6(10bit res) 샘플링

 

 

더군다나

ADC만하는게 아니라

ADCread->save->compare->communication

 

그래서 꼼수가 필요하다

한 채널의 1회 리딩만 끝내고 다음채널로 넘어갈 것인지

한 채널의 리딩에서 커뮤니케이션까지 다 끝내고 다음채널로 넘어갈 것인지

등 등

 

실로 가장 중요한 것은 Resolution 보단 Sampling Rate다.

 

ADC 가 여력이 안된다면 각 센서당 프로세서를 할당한다.

그럼 또 문제가 통신 속도

통신도 최적화해야한다.

1을 보낼 것인가

1 connected를 보낼것인가.

 

 

자체적으로 1.1v 의 AREF

 

free running 은 계속적 ADC

single conversion 은 단 한번 ADC

 

인터럽트 ADC가 끝나면 인터럽트로 넘어가도록

 

ADMUX 스위치 묶음

 

Register는 8칸의 저장공간

MUX(Multiplexer) 는 선택의 의미

ADMUX 에 모여있다.

 

ADMUX 의 레퍼런스

7번비트는 전압관련

6번비트도 전압관련

5번 비트는

4번 비트는 reserve

3번 비트에서 0번 비트까지는 조합으로

채널 선택
 
 
 
 
▼ 아래 프로그램 설명해주실 분 있으신가요? Arduino 로에서는 serial 로 값이 잘 뜨는데, AVR Studio 에서 오른쪽 프로그램을 구운 다음에 하이퍼터미널로 보면 아무 것도 안 찍히네요 ㅜㅜ
 
 AVRStudio 에서 프로그램 구울때 project 메뉴에 configure 옵션에서 16000000 주파수를 써주셨어요?
다시한번 체크해보시고 하이퍼터미널을 열때도 9600 보드레이드 세팅이랑도 다시한번 체크해보세요~
 
답변 감사합니다.
문제는 하이퍼 터미널의 COM port 설정이었네요.
arduino port 와 isp port 가 다른 걸 몰랐습니다.
저 같이 삽질하신 분이 없으시길요 ㅎㅎ;;

//Arduino code
//ADC + Serial Communication

int reading;                // the readings from the analog input
int inputPin = 0;

void setup()
{
  Serial.begin(9600);                     // initialize serial communication with computer
 
}

void loop()
{
  
  reading = analogRead(inputPin); // read from the sensor
  Serial.println(reading);                // send it to the computer (as ASCII digits)
}
//AVR-GCC code
//ADC + Serial Commnication
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>

#define FOSC 16000000
#define BAUD 9600
#define UBRR FOSC/16/BAUD-1

// Initialize USART0
void init_USART0(unsigned int baud)
{
UBRR0 = baud; // Set Baudrate
UCSR0C = (3<<UCSZ00); // Character Size 8 bit
UCSR0B |= _BV(RXEN0) | _BV(TXEN0); // Receiver and Transmitter Enable
}

// Set Receive Interrupt Enable
void setRXCIE_USART0()
{
UCSR0B |= _BV(RXCIE0);
}

// Receive 1 byte Data
unsigned char receive_1byte_USART0(void)
{
loop_until_bit_is_set(UCSR0A, RXC0);
return UDR0;
}

// Transmit 1 byte Data
void transmit_1byte_USART0(unsigned char data)
{
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = data;
}

// Transmit String Data
void transmit_str_USART0(char *str)
{
while (*str != 0) 
{
transmit_1byte_USART0(*str);
*str++;
}
}

// Transmit Four-Digit Integer
void transmit_4digit_USART0(int num)
{
unsigned char temp;
int digit = 1000;

while (digit != 0) 
{
temp = num / digit;
transmit_1byte_USART0('0'+temp);
num -= (digit*temp);
digit /= 10;
}
}

// Transmit Digit Integer
void transmit_digit_USART0(int num)
{
char temp[4];
itoa(num, temp, 10);
transmit_str_USART0(temp);
}

int main()
{
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Set ADC prescalar to 128 - 125KHz sample rate @ 16MHz 
ADMUX |= (1 << REFS0); // Set ADC reference to AVCC 
//ADMUX |= (1 << ADLAR); // Left adjust ADC result to allow easy 8 bit reading 
ADMUX &= ~(1 << ADLAR); // right adjust ADC result to allow easy 10 bit reading 

// No MUX values needed to be changed to use ADC0 

ADCSRA |= (1 << ADATE); // Set ADC to Free-Running Mode
ADCSRA |= (1 << ADEN); // Enable ADC
ADCSRA |= (1 << ADSC); // Start A2D Conversions 

 
init_USART0(UBRR); // initialize USART0


while (1) 
{
transmit_digit_USART0(ADCW);
transmit_1byte_USART0('\r');
transmit_1byte_USART0('\n');
_delay_ms(20);
}

return 0;
}

'만들기 / making > sensing workshop' 카테고리의 다른 글

Day 4: InfraRed Sensor  (0) 2009.08.31
ATmega168 ADC 3  (0) 2009.08.31
ATmega168 ADC  (0) 2009.08.31
bit 연산  (0) 2009.08.31
2진법 / 16진법 / ASCII  (0) 2009.08.31