만져보는 임베디드 시스템/아두이노 소프트웨어

아두이노 소프트웨어-x. 함수 -디지털, 아날로그 입출력, 기타 입출력 함수

hanjinee 2020. 12. 31. 00:41

[이 포스트는 -'아두이노 상상을 스케치하다' 허경용 저-에서 많은 정보를 얻었으며, 추가 정보는 여러 책에서 종합해서 공부한 것입니다. ]

안녕하세요 제타지니입니다. 오늘은 아두이노의 고유 함수인 디지털, 아날로그 입출력과 기타 입출력 함수에 대해서 다루어 보겠습니다. 

 

아두이노에서는 '아두이노 만의' 고유한 함수가 있는데, 지금부터 그것을 살펴보도록 합시다!

가장 기본이 되는 것은 아두이노 보드를 다룰 수 있게끔 만들어주는, '입출력 함수'입니다. 

 

시작하시기 전에 아두이노의 핀 번호 부터 먼저 보신다면 꿀이득입니다. 

(핀 번호를 아셔야 코딩을 하실 수 있겠죠?)

핀 번호를 보기 위해서는 이 사이트가 좋습니다!!

http://www.pighixxx.com/

 

pighixxx.com - pighixxx 자료와 정보

 

ww1.pighixxx.com

안된다면, 구글에 uno pinout을 쳐보시면 바로 나올겁니다!

 

한번 uno를 예시로 들고 왔습니다. 

출처: www.pighixxx.com

 

[디지털 입출력 함수]

 

디지털 입출력 함수에는 3가지가  있습니다.

pinMode

digitalWrite

digitalRead

 

하나 하나 설명을 해보자면, 

****pinMode

void pinMode(pin_nunmber, Mode)

pinMode ==pin핀의 Mode상태를 설정합니다.

즉, pinMode함수는 지정한 핀이 출력 or 입력으로 동작하도록 설정합니다. 

사용 방법은 다음과 같습니다. 

pin_number: 설정하고자 하는 핀번호

Mode : INPUT, OUTPUT, INPUT_PULLUP

void로 설정되어 있는 함수죠? 그렇습니다. 일단 '반환값'이 존재하지 않습니다. 

여기에 대해서는 별로 설명을 드릴 게 없습니다만 그래도 설명을 드리자면 mode를 설정하는 것은 지정한 핀에 대해서 입력(INPUT, INPUT_PULLUP)으로 할 것인지 출력(OUPUT)으로 할 것인지 정하는 것입니다. 

 

mode를 INPUT_PULLUP으로 하게 되면 내부 풀업 저항을 사용하도록 설정됩니다. (INPUT으로 설정하면 내부 풀업 저항이 사용되지 않습니다.) 외부 풀업 저항을 사용하지 않을 때 사용하시면 될 것입니다. 

 

위의 그림에서 보시다 시피 TX와 RX를 제외한 digital 핀은 4번 ~ 13번입니다. 

예시는 digitalWrite를 설명하고 보여드리도록 하겠습니다.

 

 

****digitalWrite

void digitalWrite(pin_number, value)

'디지털 핀 출력'의 대표적인 함수입니다. pin_number에 출력으로 지정한 디지털 핀을 넣고, HIGH 값 혹은 LOW값을 출력합니다. 

pin_number : pinMode에서 출력으로 설정한 뒤에 핀 번호를 넣습니다.

value: HIGH 또는 LOW를 넣습니다. 대문자로 넣으시면 됩니다.

역시나 digitalWrite도 void로 선언된 함수로, 반환값이 존재하지 않습니다. OUTPUT으로 설정된 경우 HIGH값을 출력하면 5[V](3.3[V] 보드의 경우 3.3[V])를 출력하고, LOW의 경우 0[V](ground, 접지)를 출력합니다. 

만약 pinMode에서 지정한 digital pin이 INPUT(입력)으로 설정되었다면, digitalWrite를 설정한 핀에 쓰시게 될 경우 uno의 경우 HIGH값을 출력하면 20kΩ 내부 풀업 저항이 연결되며, LOW값을 출력했을 경우, 풀업 저항이 해제됩니다. 또한 아두이노의 각각의 핀들은 각각의 pullup resistor를 지니고 있으므로, 너무 많은 핀 연결이 pull up 저항에 부담을 줄 것이라고는 생각하실 필요 없습니다. pull up 저항이 손상을 입게될 경우는 '과전압' 혹은 '방전'일 경우라고 하네요!

 

코딩의 경우 이런식으로 하시면 됩니다. pinMode의 경우 처음에 한번만 설정하면 되니 굳이 loop에 넣지 않아도 되겠죠? 또한 아두이노 기기 내부에는 led가 포함되어 있는데, 이 led의 경우 13번 핀과 연결이 되어 있으므로, 13번 핀을 출력으로 설정하시면 led 역시 켜지는 것을 확인하실 수 있을 것입니다. 

 

다만 주의하실 점이 있다면, LED와 LED 보호를 위한 저항이 13번 핀에 연결되어 있으니, 만약 13번 핀에 대해 내부 pull up 저항(20kΩ)을 사용하도록 설정하면 LED 보호 저항도 함께 사용되어, HIGH 상태에서도 전압이 1.7[V]로 낮아지게 되어 항상 LOW상태가 됩니다. 따라서, 13번 핀에 대해서 입력으로 사용할 때는 내부 pull up 저항을 사용하는 것이 아닌 외부 pull up 저항을 사용하셔야 합니다. 

 

 

****digitalRead

int digitalRead(pin_number)

반환값이 정수형입니다. 지정한 핀(pin_number)이 입력으로 설정되어 있을 때, 지정한 핀으로 부터 값을 읽어들여 HIGH값 또는 LOW 디지털 값을 읽어서 반환합니다. 만약 PIN에 외부 회로가 연결되어 있지 않다면, digitalRead 함수의 경우 LOW나 HIGH값 중 임의의 값을 반환할 수 있으므로, 풀업 저항이나 풀다운 저항을 사용할 것을 권장한다고 하네요. 

 

 

[아날로그 입출력 함수]

 

analogReference

analogRead

analogWrite

 

하나하나 설명을 드리자면, analogReference 함수는 다음과 같습니다.

****analogReference

void analogReference (type)

반환값이 없는 함수입니다. 기준전압(reference voltage)이 어떻게 되는 지 설정하는 함수입니다.

선정해야 하는 변수 type은 다음과 같습니다. 

type: DEFAULT, INTERNAL, INTERNAL1V1, INTERNAL2V56, EXTERNAL 중 한가지를 넣으시면 됩니다. 하나하나 설명드리자면

DEFAULT: 아두이노 보드의 동작전압 5[V]로 기준전압을 설정합니다. 3.3[V]의ㅣ 보드의 경우 3.3[V]로 설정 됩니다.

INTERNAL: 내부 기준 전압으로 설정합니다. ATmega168이나 ATmega328의 경우 1.1[V], ATmega8의 경우 2.56[V]으로 설정됩니다. 아두이도 메가의 경우 사용할 수 없습니다.

INTERNAL1V1: 내부 1.1[V]를 기준 전압으로 설정합니다. 아두이노 메가에서만 사용 가능합니다. 

INTERNAL2V56: 내부 2.56[V]를 기준 전압으로 설정합니다. 아두이노 메가에서만 사용 가능합니다. 

EXTERNAL: AREF핀에 인가된 0~5[V] 사이의 전압을 기준 전압으로 설정합니다. 

 

이제부터는 주의하실 점에 대해서 이야기를 나누어 보겠습니다.

준 전압을 변경하고 anlalogRead 함수로 처음 읽어 들이는 몇 개의 아날로그 전압은 부정확할 수 있습니다. 

외부 기준 전압을 사용하는 경우 AREF핀에는 0[V]미만이나 5[V]를 초과하는 전압을 인가해서는 안됩니다.

AREF 핀에 인가되는 전압을 기준 전압으로 사용할 경우 analogRead함수 호출 이전에 기준 전압을 EXTERNAL로 설정해야 합니다. 

-그렇지 않으면, 내부 기준전압과 AREF핀에 인가된 외부 전압이 동시에 인가되어 보드가 손상될 수 있습니다.  

AREF핀에는 32KΩ 내부 저항이 연결되어 있습니다..

-만약 10KΩ 외부 저항을 연결하고 5[V]의 전압을 인가하게 된다면

(10 * 32) / (10 + 32) = 7.62[V] 의 전압이 AREF 핀에 인가됩니다. 

센서를 사용하여 센서 출력을 하신다면, 거의 아날로그 기준 전압의 사용이 필수적인데, 이유는 센서의 출력을 ADC(Analog Digital Converter, Analog 신호를 Digital 신호로 변환)하게 된다면, ADC 자체가 기준 전압의 영향을 크게 받기 때문입니다. 기준전압을 사용하지 않을 시에 부정확한 값을 얻을 수 있습니다. 

AREF핀에 연결된 전압을 필시 확인하세요. 전압의 값이 정확한지 꼭 확인하시기를 바랍니다.

 

****analogRead

int analogRead(pin_number)

반환되는 값 0에서 1023 사이의 정수값입니다. 

pin_number에는 먼저 pinMode에서 analog pin을 입력으로 설정합니다. 

지정한 아날로그 입력 핀으로 부터 '아날로그 값을 읽어서 ADC(Analog Digital Converter, 아날로그-디지털 변환기)를 통해서 디지털 값으로 변환하여 반환합니다. 

우노에는 6개의 채널의 10비트 아날로그-디지털 변환기가 포함되어 있으므로, 가해진 입력 전압은 0에서 1023(2^10 - 1) 사이의 디지털 값으로 변환되어 읽힙니다.

(ex 5[V]의 경우 5 / 1024 = 4.9[mV]이므로 4.9[mV] 차이를 인식할 수 있습니다.)

아날로그 입력을 읽는 데 걸리는 시간은 약 0.0001초 (100us, microsecond)입니다.

 

****analogWrite

void analogWrite(pin_number, value)

pin_number: 아날로그 핀 번호

value: 0에서 255 사이의 값.

analogWrite 함수를 사용할 시에는 출력으로 PWM(Pulse Width Modulation, 펄스 폭 변조)방식의 신호를 디지털 핀으로 출력합니다. 

PWM에는 duty cycle이라는 녀석이 있는데, 말로서 설명을 드리자면..... LOW인 상태와 HIGH인 상태를 %로 표시한 것이죠. 수식은 (HIGH값 출력 시간 / 전체 출력 시간)으로 설명 드릴 수 있겠습니다. 그림으로 표현하자면 다음과 같습니다. 한번 보시죠

 

 

0을 출력하면 duty cycle은 0%이며, 255을 출력하면 duty cycle이 100%인 PWM이 출력됩니다.

Atmega168과 ATmega328을 포함한 대부분의 아두이노 보드는 디지털 핀 3, 5, 6, 9 10, 11로 PWM 신호를 출력할 수 있습니다. 

아두이노 메가의 경우 2번에서 13번 핀까지 PWM 신호 출력을 지원합니다. 

아두이노 두에의 경우 2번에서 13번 핀까지 PWM 신호 출력을 지원함과 동시에 DAC0과 DAC1으로 아날로그 신호 출력 역시 가능합니다. (DAC = Digital- Analog Converter, 디지털-아날로그 변환기, PWM 신호와는 다르게 실제 아날로그 신호)

analogWrite함수로 PWM 신호를 출력하기 전에는 pinMode 함수를 이용하여 핀을 출력으로 설정하지 않아도 됩니다!

 

[기타 입출력 함수]

tone

void tone(pin_number, unsigned int frequency, unsigned long duration = 0)

pin_number: 핀번호

frequency: 출력 주파수

duration: 출력 지속 시간, milli-seconds 단위

 

50%의 duty cycle 지정된 주파수(frequency)를 지닌 구형파(square wave)를 출력합니다. 

'피에조 스피커'와 같이 '단음'을 재생하기 위해 사용합니다.

지속시간(duration)을 설정할 수 있으며, 지속시간이 지정되지 않을 시에 noTone함수가 호출될 때 까지 출력이 계속됩니다.

 

tone함수는 신호 출력을 위해 타이머를 사용합니다. PWM 신호를 출력하는 디지털 핀 중 3번과 11번 핀이 동일한 타이머를 사용하기 때문에, tone 함수를 사용할 경우에는 3번과 11번 디지털 핀으로 PWM 신호를 출력할 수 없습니다.

 

noTone

void noTone(pin number)

pin: 핀 번호(uint8_t)

tone 함수에 의한 구형파 출력을 멈춥니다. 

여러 핀으로 다른 높이의 음을 재생하기 위해서는 반드시 현재 재생중인 핀에 대하여 noTone함수를 먼저 호출하 뒤 tone함수를 호출해야 합니다. 

 

여기부터는 조금 더 심화된 내용 같아서 몇 가지 유용한 사이트도 같이 첨부 합니다! 

 

shiftOut

void shiftOut(dataPin, clockPin, bitOrder, value)

dataPin: 비트 출력이 일어날 핀, ds 핀넘버(uint8_t)

clockPin: 한 비트 출력 후에 데이터 출력을 알려주기 위해 펄스가 출력되는 핀, Clock 핀넘버(uint8_t)

bitOrder: 비트 출력 순서, MSBFRIST 또는 LSBFIRST(uint8_t)

-MSBFIRST = Most Significant Bit FIRST 1 byte의 데이터 中 가장 왼쪽의 데이터 부터 전송

-LSBFIRST = Least Significant Bit FIRST 1 byte의 데이터 中 가장 오른쪽의 데이터 부터 전송

value: 출력될 데이터, 8개의 비트를 담은 1 byte의 데이터(byte, uint8_t)

이 함수는 데이터를 shift register에 보내기 위해 특별히 고안되었습니다. 

그렇다면, Shift Register라는 녀석에 대해서 먼저 설명해야 겠지요?

Shift Register라는 녀석은 Serial to Parallel Converter라고도 불리웁니다. 직렬(Serial)로 입력되는 데이터를 병렬(Parallel)로 바꾸어 주는 것이지요. 사용해야 할 출력의 수가 디지털 핀 수 보다 많을 때 일반적으로 사용됩니다. 

Shift Register에는 SIPO(Serial In Parallel Out) 방식과 PISO(Parallel In Serial Out) 방식 두가지가 있는데요,

SIPO방식 다수의 출력을 가질 때, PISO방식 다수의 입력을 가질 때 사용합니다. 

 

여하튼, shiftOut에 대해서 설명드리자면 

지정한 데이터 값을 비트 단위로 지정한 핀으로 출력하는 함수 입니다. 

shiftOut함수는 소프트웨어를 통한 통신 함수의 구현이며, 하드웨어를 통한 구현은 SPI(Serail Peripheral Interface) 라이브러리를 통해 제공된다. SPI 라이브러리는 속도면에서 빠르기는 하지만, SPI를 위한 전용 핀 (우노 - 11, 12, 13 디지털 핀)을 사용해야만 한다 단점이 있습니다.

 

shiftIn

void shiftIn(dataPin, clockPin, bitOrder, value) 

shiftOut 함수와 같습니다. shiftOut 함수와 마찬가지로 소프트웨어를 통해 구현된 통신함수입니다.

다만 shiiftOut 함수와의 차이점은 데이터를 입력받는 것이지요. 

 

 

pulseIn

unsigned long pulseIn (uint8_t pin, uint8_t value, unsigned long timeout = 1000000L)

pin: 펄스를 읽어 들일 핀 번호

value: 읽어 들일 펄스의 종류, HIGH 또는 LOW

timeout: 펄스의 시작을 기다리는 시간, micro-seconds 단위. 디폴트 값은 1초

지정한 핀으로 부터 HIGH 또는 LOW 펄스를 읽어들인다. value HIGH로 지정하면 지정한 핀이 HIGH 상태로 바뀐 뒤 다시 LOW 상태로 바뀔 때 까지의 시간을 마이크로-초 단위로 반환합니다. 타임아웃 이전에 pulse가 시작되지 않으면 0을 반환합니다. 

 

*pulseIn 함수로 측정된 시간은 경험적으로 계산된 값입니다. 긴 펄스의 경우 오차가 생길 수 있으니, pulseIn 함수는 10마이크로-초에서 3분 정도의 길이의 펄스를 측정하기 위해 사용될 수 있습니다. 

 

 

728x90