아두이노 기초 강좌는 아두이노를 처음 접하시는 전자분야 비 전공자를 위한 강좌입니다. 이해를 위해서는 간단한 프로그래밍 지식이 필요할 수 있습니다. 프로그래밍이 처음이라면 [아두이노 프로그래밍 기초] 강좌를 먼저 읽으시길 권해 드립니다.

=============================================================
.

지난 시간에 digitalRead, digitalWrite 함수 사용 방법을 알아봤습니다. 주로 on/off 동작을 제어하는 경우에 해당하는 작업이었습니다. 이번에는 0~5v까지 세분화된 값을 입력받거나 출력할 때 어떻게 하는지를 예제를 통해 알아보겠습니다.

1. AnalogRead 예제 – 포텐셔미터

먼저 살펴볼 예제는 아두이노 공식 홈페이지에 소개된 포텐셔미터 입력(AnalogReadSerial) 예제입니다.

http://arduino.cc/en/Tutorial/AnalogReadSerial

간단하죠. 5V, GND를 포텐셔미터에 연결하고 포텐셔미터의 가운데 핀을 아날로그 0번 핀으로 연결합니다. 포텐셔미터(Potentiometer)는 동그란 손잡이를 시계, 반시계 방향으로 돌릴 때 마다 내부의 저항이 바뀌는 장치입니다. 그래서 가운데 핀(아날로그 0번 핀)으로 들어가는 전압이 바뀝니다. 즉, 아날로그 0번 핀으로 입력받는 전압이 0V ~ 5V 사이에서 변화하는데 이 값을 읽어서 입력 장치처럼 사용하는 것입니다.

지난 시간에는 버튼의 on/off 를 읽었기 때문에 digitalRead() 함수를 사용했죠. 이제는 0V~5V 사이에서 변화하는 값을 읽어야 하기 때문에 analogRead() 함수를 사용할 것입니다. 이름처럼 analogRead() 함수는 입력된 전압에 따라 0~1023 까지의 값을 반환해주는 함수입니다.

즉, 아두이노는 0V에서 동작전압 5V 까지를 1024등분해서 값을 알려준다는 얘기입니다. 이렇게 Analog 값(전압 입력 값)을 digital 값(0~1023)으로 변환해주는 모듈을 ADC(Analog to Digital Converter)라고 부르고 아두이노가 자체적으로 가지고 있습니다. 아두이노는 ADC 가 1024 단계(2^10)로 구분할 수 있기 때문에 10비트의 분해성능을 가지고 있다고 합니다.

analogRead() 함수로 읽은 값은 USB serial 로 출력합니다.(즉 PC로 전송해서 PC에서 확인할 수 있도록 해줌) 아두이노 개발환경이 제공하는 Serial Monitor로 확인하면 0부터 1023 사이의 값이 주르륵 나오고 포텐셔미터를 돌릴 때마다 그 값이 변화해서 나올겁니다.

이제 코드를 확인해 보겠습니다.

/*
  AnalogReadSerial
  Reads an analog input on pin 0, prints the result to the serial monitor.
  Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.
 
 This example code is in the public domain.
 */

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  // print out the value you read:
  Serial.println(sensorValue);
  delay(1);        // delay in between reads for stability
}

소스코드는 매우 간단합니다. Serial monitor를 통해 포텐셔미터의 값을 출력하는 부분을  제외하면 실질적으로 아래 라인이 전부입니다.

  int sensorValue = analogRead(A0);

A0(아날로그 0번) 핀에서 0~1023 으로 구분된 값을 읽는 것이죠. 여기서 한가지 생각하셔야 할 점은 digitalRead 함수를 쓸 때 처럼 pinMode 함수로 read/write 모드를 설정해 주지 않았다는 점입니다. 이것은 analogRead를 사용할 수 있는 핀이 아날로그 입력핀인 A0~A5(또는 A7) 로 고정되어 있고 여기에는 Read 작업만 할 수 있어서 모드를 설정할 필요가 없기 때문입니다. 그래서 포텐셔미터를 아날로그 핀에 연결해서 analogRead를 사용한 것입니다.

다음 예제에서 보겠지만 analogWrite 는 PWM 이라고 부르며 아날로그 핀이 아니라 지정된 digital 핀(PWM 핀)에 사용합니다.

2. analogWrite(=PWM) 예제

아두이노에서 제공하는 기본 예제 중 하나인 Fade 예제를 보겠습니다. 

http://arduino.cc/en/Tutorial/Fade

이 예제는 LED 를 아두이노의 PWM 핀에 연결해서 밝기를 원하는대로 조절하는 예제입니다. LED의 밝기를 조절하려면 어떻게 해야 하죠? 아두이노 핀으로 출력되는 5V 전압을 적당히 낮춰주면 됩니다. 그런데 아두이노는 핀으로 출력되는 전압 자체를 조절하는 능력은 없습니다. 대신에 PWM 이란 방법을 사용합니다.

PWM(Pulse Width Modulation, 펄스 폭 변조) 이란?  PWM은 5V출력을 on/off 상태로 유지하는 것으로 출력하는게 아니라 빠르게 on/off 를 반복하는 것입니다. 아래 그림처럼요. 

pwm1

이걸 매우 빠르게 반복하는 겁니다. 그러면 위 예시처럼 on/off 간격(Pulse Width)에 따라 평균전압이 낮아지는 효과가 납니다. 평균전압이 낮아져서 LED를 어둡게 만들 수 있는거죠. 아두이노에서는 500Hz 주파수, 2ms 간격으로 이런 작업을 수행합니다. 그리고 아두이노는 이 단계를 256 단계로 구분할 수 있습니다. 우리가 0V(0) ~ 5V (255)를 256 단계로 구분해서 입력할 수 있다는 뜻입니다. on/off 출력이 아니라 단계적인 출력이 가능하므로 아날로그 출력이라고도 합니다.

아두이노가 가진 Digital 핀 중 PWM 기능을 가진 핀들이 이미 정의되어 있습니다. 아두이노 보드에 있는 각각의 핀 아래에는 핀 번호가 적혀있는데 PWM 기능을 가진 핀은 앞에 (~) 물결 마크가 붙어 있습니다. 아래 그림에서 보듯3, 5, 6, 9, 10, 11번 핀이 PWM 핀이죠. (UNO 보드 기준이며, 보드 종류에 따라 PWM 핀이 틀려집니다)

ArduinoUno_r2_front450px

정리를 하면… analogRead() 함수를 사용해서 단계적인 값을 읽을 때는 아날로그 핀들을 사용하면 됩니다. 하지만 아날로그 핀을 통해 단계적인 0V~5V 사이의 값을 출력할 수는 없습니다. 이런 작업은 PWM 핀으로 지정된 digital 핀을 통해서 가능합니다. 이 때 analogWrite() 함수를 사용할 수 있습니다.

그리고 추가로 하나 더. analogRead는 0~1023 까지의 값을 읽을 수 있고, analogWrite는 0~255 사이의 값을 사용할 수 있습니다. 따라서 analogRead()를 통해 입력받은 값을 1/4 하면 analogWrite() 의 출력 단계값으로 사용할 수 있습니다.

 

그럼 예제를 한번 보겠습니다.

챕터 1에서 사용된 analogRead 예제를 변형해서 이용합니다. 포텐셔미터로 입력된 값을 이용해서 LED의 불빛을 조절하는 예제입니다. 챕터 1에서 사용한 회로에 LED 를 추가로 연결해서 쓰시면 됩니다. 아래 강좌에 사용된 회로를 참고해서 LED를 추가로 연결하세요.

https://www.hardcopyworld.com/?p=936

9번핀 -> 220 ohm 저항 -> LED 긴 다리 -> LED 짧은 다리 -> GND 순서로 연결하면 됩니다.

int ledPin = 9;

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);   // sets the pin as output
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);

  // print out the value you read:
  Serial.println(sensorValue);

  analogWrite(ledPin, sensorValue / 4);  // analogRead values go from 0 to 1023, analogWrite values from 0 to 255

  delay(1);        // delay in between reads for stability
}

기존에 있던 코드에서 LED 불빛을 제어하기 위한 코드만 추가되었습니다. 따라서 포텐셔미터로 입력받은 값에 따라 LED 불빛이 변화합니다.

변경된 코드를 한 줄씩 보겠습니다.

int ledPin = 9;

디지털 9번핀(PWM 핀) 에 저항을 거쳐 LED 가 연결되어 있습니다. 그래서 9번핀을 미리 기억해 둡니다.

  pinMode(ledPin, OUTPUT);   // sets the pin as output

9번핀은 digital 핀이므로 INPUT/OUTPUT 모드를 설정해야 합니다. LED로 전원을 넣어줘야 하니까 OUTPUT 모드로 설정.

  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);

  // print out the value you read:
  Serial.println(sensorValue);

  analogWrite(ledPin, sensorValue / 4);  // analogRead values go from 0 to 1023, analogWrite values from 0 to 255

이 부분이 가장 중요한, 포텐셔미터의 값을 읽어서 LED 출력을 조절하는 부분입니다. A0 아날로그 핀에서 값을 읽어서(0~1023) PC로 값을 전송하고, analogWrite 함수를 사용해서 LED 핀으로 PWM 출력을(0~255) 합니다. 아날로그 입력값의 범위가 PWM 출력 범위보다 4배 넓기 때문에 sensorValue에 저장한 아날로그 입력값을 4로 나누어서 사용했습니다.

이제 직접 아날로그 출력(PWM 출력)으로 불빛 조절이 가능한지 확인해보세요.

# 강좌의 내용이 명확하지 않거나 이해가 힘든 부분이 있으시면 댓글로 말씀해 주세요. 해당 부분을 지속적으로 업데이트 하겠습니다.

=============================================================

이 문서는 작성자의 동의없이 개인적인 목적 외의 상업적인 목적으로 활용되어서는 안됩니다.

이 문서의 일부 혹은 전체를 수정, 삭제, 재배포 하여서는 안됩니다.

작성자 : GodsTale (godstale@hotmail.com)