아두이노 강좌 #12 아날로그 입력 analogRead() 와 map() 함수
Lucy Archive
Lucy 2023
2020. 7. 11. 02:03

아두이노 ADC 사용 방법 : analogRead()

  지난 디지털 입출력 관련 포스트에서 digitalPin(D0~D13) 으로 스위치가 On/Off 를 판정하는 코드를 작성할 수 있었습니다. 아두이노에서는 이렇게 HIGH(5V), LOW(0V) 상태 뿐만 아니라, 아날로그 전압을 입력 받을 수 있는 기능을 제공합니다. 아날로그 전압은 5V, 0V 의 이분화 된 전압이 아니라 0 ~ 5V 사이에 있는 중간 중간의 전압을 말합니다. 본 포스트에서는 아두이노에서

아날로그 전압 입력 방법과 예제

에 대해 작성하였습니다.

디지털 vs 아날로그

  디지털이란 말은 1과 0과 같이 이산적 수치를 말하고, 아날로그는 연속적인 값을 말합니다. 일상 생활에서 쉬운 예는 아래와 같이 디지털은 OFF, ON 의 기능만 되는 전구 스위치와 같고, 아날로그 타입은 밝기가 여러가지 중간 값을 가지는 가지는 형태로 이해 할 수 있습니다. 사실 이런 아날로그라고 하는 것도 대부분 디지털로 처리를 하지만, 이해를 돕기 위한 예시로 이해해주세요.

아날로그와 디지털 차이아날로그와 디지털 차이

  디지털 신호와 아날로그의 전기적인 신호는 아래의 그림과 같은 형태입니다. 실제로 디지털 값의 입력이 5V, 0V 로 이렇게 정확하게 나누어 지는 것은 아니고, 중간의 애매한 전압이 없이 HIGH(5V), LOW(0V) 로 구분 또는 인식합니다. 아날로그 전압은 아래와 같이 0 ~ 5V 사이의 중간 전압 값을 가지고 있습니다. 

(좌) 디지털, (우) 아날로그(좌) 디지털, (우) 아날로그

ADC와 분해능

  ADC는 Analog to Digital Convert 용어의 약자로 아날로그 신호를 디지털 신호로 변환하는 의미입니다. 아날로그 전압은 무한한 실수(소수)의 연속적인 값으로 구성됩니다. 마이크로프로세서는 유한한 메모리를 가지고 있어, 아날로그 신호의 무한한 중간 연속적인 값들은 이산적인 정수로 저장을 합니다.

  분해능은 아날로그 전압을 디지털 전압으로 변경 할 때 얼마나 정밀한 단위로 나눌지 결정하는 척도입니다. 분해능 스펙은 프로세서 마다 다양하지만, Arduino Uno 보드는 10 bit ADC를 장착하고 있습니다. 10 bit 는 2^10 으로 1024개의 수를 말하고, 0 ~ 5V 를 약 0.0049[V]단위로 나누어 저장한다는 뜻입니다. ( 5V / 1024 = 0.0048828125

  • 아날로그 전압 to 디지털 상수
    • 0 V : 0
    • 1.3 V : 265
    • 3.647 V : 746
    • 5 V : 1023

※ 알아두면 좋을 수도 있는 지식

디지털 신호가 1과 0만 존재 한다는 것은, 5V 전압이 선로에서 0.4V의 손실이 있어 4.6V 로 전압 강하가 발생해도 입력 받는 쪽에서 HIGH (5V)로 판단 할 수 있다는 의미 입니다. 이 이유로 노이즈에 강하고, 노이즈에 강하기 떄문에 멀리 보낼 수 있고, 고속으로 통신 할 수 있습니다. 

  • 아두이노 우노 디지털 입력
    • HIGH(로 인식) : 입력 전압 3V 이상
    • LOW(로 인식) : 입력 전압 1.5V 이하

아두이노 아날로그 입력

  아두이노 우노보드에서 디지털핀은 입력으로 사용하는 경우 5V와 0V 입력을 받아 HIGH 인지 LOW 인지 판별 가능한 핀이고, 아날로그핀핀은 일반적으로 0 ~ 5V 범위의 전압 값을 입력 받을 수 있는 핀입니다. 디지털 핀과 아날로그 핀으로 할 수 있는 일들은 아래와 같습니다.

  • 디지털핀
    • 입력 : 스위치 입력, 데이터 HIGH/LOW 판별, 디지털 데이터 수신 등
    • 출력 : LED ON/OFF, 디지털 데이터 송신 등
  • 아날로그핀
    • 입력 : 여러가지 아날로그 센서 연결, 아날로그 전압 입력 등
    • 출력 : LED 의 밝기 조절, 모터 속도 제어 등 다수

아두이노 우노 보드 아날로그 입력은 아래 그림 좌측 하단의 A0 ~ A5 핀으로 사용 가능 합니다.

아두이노 우노 아날로그 입력핀아두이노 우노 아날로그 입력핀


analogRead()

[각주:1]아두이노에서는 아날로그 입력을 처리할 수 있는 analogRead() 함수가 지원됩니다. 

Syntax

  • analogRead(pin)

Parameters

  • pin : 아날로그 핀 번호 (Arduino Uno의 경우 A0 ~ A5)

Returns : 입력된 전압을 10 비트 분해능 단위로 반환 된 숫자 (Datatype : int)

Example

  • val = analogRead(A1) : A1 핀 전압 10 비트 분해능 단위의 숫자를 val 에 저장


예제1 : A0 입력 전압 출력

아래 예제는 A0에 입력되는 아날로그 전압을 100ms 간격으로 출력하는 예제입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const int analogPin = A0;
int value;
/* sensor 값을 저장할 변수를 선언
    5V : 1023
    0V : 0     */
 
void setup(){
    // buadrate 9600 으로 시리얼 포트를 초기화하고
    // 시리얼 포트가 연결 될 때 까지 기다립니다.
    Serial.begin(9600);
    while(!Serial){
        ;
    }
    delay(1000);
    Serial.println("Initialize Finished...");
    delay(1000);
}
 
void loop(){
    // analogPin 의 값을 value 에 저장 후 시리얼포트로 출력합니다.
    value = analogRead(analogPin);
    Serial.println(value);
    delay(100);
}
cs

아래는 사용한 회로도와 실행 결과입니다.

가변저항 연결 회로도가변저항 연결 회로도

프로그램 실행 결과프로그램 실행 결과



map() : 범위 맵핑

  위의 예제에서 입력 전압을 10bit 로 디지털화된 숫자로 출력을 했는데, 실제로 필요한 것은 전압 또는 가변저항의 현재 저항 값이 필요한 경우가 있습니다. 또는 온도 센서를 사용하는 경우 온도가 실제로 출력이 필요한 데이터가 될 수 있습니다. 아두이노에서 지원되는 연산자 (+,-,*,/)로 디지털화되 숫자를 전압 또는 저항으로 계산 할 수 있지만, 아두이노는 입력 값의 범위를 출력값의 범위에 맞추어 계산해주는 [각주:2]map() 함수를 지원합니다.

Syntax

  • map(value, fromLow, fromHigh, toLow, toHigh)

Parameters

  • val : 변경 할 값 (Datatype : int)
  • fromLow : value 의 최소값 범위 (DataType : int)
  • fromHigh : value 의 최대값 범위 (DataType : int)
  • toLow : 변경될 범위의 최소값 (DataType : int)
  • toHigh : 변경될 범위의 최대값 (DataType : int)

Returns : 변경될 범위로 매핑된 값 (데이터타입 : int)

Example

  • val = map(120, 0, 1023, 0, 5) : 0 ~ 1023 범위의 값 120이 0 ~ 5범위로 매핑된 값을 val 에 저장
  • val = map(10, 0, 50, 0, -50) : 0 ~ 50 범위의 값 10을 0 ~ -50 범위로 매핑된 값을 val 에 저장

map() 함수는 일반적으로 int 형으로 처리를 하는데, 다른 데이터 형으로 처리하고 싶은 경우 아래와 같이 함수를 재정의 하고 사용이 가능합니다. 아래는 float 형을 사용하여 소수점으로 매핑하기 위해 map() 함수를 재정의 한 코드 입니다.

1
2
3
4
float map(float x, float in_min, float in_max, float out_min, float out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
cs

예제2 : 가변저항의 전압과 저항 출력

  예제1은 입력전압은 디지털 화 된 2진수를 출력하였고, 본 예제는 map() 함수를 함께 사용하여 입력된 전압과 현재 저항을 표시하는 예제입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
const int analogPin = A0;
int value;
float lVoltage; // 현재 전압 값 저장
float lResistance; // 현재 저항 값 저장
 
void setup(){
    // buadrate 9600 으로 시리얼 포트를 초기화하고
    // 시리얼 포트가 연결 될 때 까지 기다립니다.
    Serial.begin(9600);
    while(!Serial){
        ;
    }
    delay(1000);
    Serial.println("Initialize Finished...");
    delay(1000);
}
 
void loop(){
    value = analogRead(analogPin);
 
    lVoltage = map(float(value), 0102305);
    lResistance = map(float(value), 01024010000);
 
    Serial.print("Present Voltage : ");
    Serial.print(lVoltage, 2);
    Serial.println(" V");
    Serial.print("Present lResistance : ");
    Serial.print(lResistance, 2);
    Serial.println(" Ω");
    delay(1000);
}
 
float map(float x, float in_min, float in_max, float out_min, float out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
cs

예제2 코드 실행 결과예제2 코드 실행 결과


마무리

  본 포스트에서는 디지털과 아날로그에 대한 차이를 알아보고, 아두이노에서 지원되는 아날로그 핀과, 아날로그 입력 함수 analogRead() 함수 사용법에 대해 작성하였습니다. 이후 포스트에서는 아날로그 출력 방법과 활용에 대해 작성할 예정입니다.

  끝까지 읽어주셔서 감사합니다.^^

관련포스트

👉 아두이노 아날로그 입출력 관련글 목록 보기

👉 아두이노 전체 포스트 목록 보기 


  1. analogRead 더 많은 정보 : https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/ [본문으로]
  2. map() 함수의 더 많은 정보 : https://www.arduino.cc/reference/en/language/functions/math/map/ [본문으로]