정보공간_1

[2기 광주 박정태]Arduino 의 모든것#2 본문

IT 놀이터/Elite Member Tech & Talk

[2기 광주 박정태]Arduino 의 모든것#2

알 수 없는 사용자 2012. 10. 15. 19:32

이제 아두이노의 사용법에 대해 심도 있게 알아보겠습니다.

앞선 포스팅에서 아두이노 예제를 컴파일 해서 다운받아서 LED가 깜박이는 것을 확인해 보았습니다. 이번 포스팅 부터는 각각의 함수와 레지스터가 어떻게 ATmega에 적용이 되는지 자신이 원하는 것을 하고 싶을때 어떻게 하면 되는지 알아 보도록 하겠습니다.

일단 Blink예제를 열어 보겠습니다.

led라는 int형 변수를 선언하고 setup이라는 함수와 loop라는 함수가 있는 것을 확인 할 수 있습니다.

아두이노 홈페이지에 나와 있는 함수 레퍼런스를 보면 설명이 나와있습니다. 간단히 설명하자면 setup은 말그대로 전체 시스템이 시작하기전 초기화 부분에 관련된 것을 하는 부분입니다. loop는 말그대로 시스템이 계속 실행될 부분입니다. 무한루프죠.

아두이노 폴더에 cores에 arduino 폴더를 보면 기본 라이브러리 가 있습니다. 이중 main.cpp파일을 보면 setup함수와 loop 함수의 역할을 잘 알수 있습니다.

LED 를 깜빡이기 위해서는 핀 관련 레지스터를 셋팅한후 일정 시간마다 깜빡이도록 핀의 상태를 변경 시켜 주어야 합니다.

이 부분을 설명하기에 앞서 MCU의 기본적인 기능에 대해 간단히 이야기 하고 넘어 가도록 하겠습니다.

모든 입출력을 디지털화된 1,0의 신호로 처리하는 MCU는 각 핀이 기본적으로 GPIO기능을 합니다 General Input/Output 기능은 말그대로 핀의 상태를 1(High상태) 과 0(Low) 으로 출력하거나 1/0의 상태를 입력 받는 기능입니다. 간단히 LED의 한쪽다리를 GND에 연결하고 한쪽다리를 핀에 연결후 핀의 상태를 LOW로 하면 LED가 꺼지고 High상태로 하면 LED가 켜지는 일련의 행동을 할수 있도록 하는 기능입니다. 단순하지만 기 기본적인 기능과 이를 응용한 다양한 시퀀스를 통해 LED를 제어하고 모터를 제어하여 Hard ware를 컨트롤 하는 것 입니다.

그리고 MCU에서 이 GPIO를 응용한 기능인 External interrupt , Timer/Counter , ADC , 다수의 통신들의 기능을 각 핀마다 할수 있도록 지원합니다. 이러한 기능들중 사용자가 어떤 기능을 쓸지는 각 핀 레지스터 셋팅을 통해 합니다.

GPIO

LED를 깜빡이기 위해서는 기본 GPIO를 이용해서 할수 있습니다. 먼저 setup 함수에서 핀을 입력이 아닌 출력으로 사용하겠다는 설정을 해주고 Loop 함수내에서 일정 시간마다 핀의 출력상태를 1에서 0으로 0에서 1로 바꿔주면 LED가 깜박이게 되는 것 입니다. 이를 위해서는 핀을 OUTPUT으로 설정해주겠다는 셋팅이 우선 필요합니다. 이를 위한 함수가 pinMode()함수죠.

다음은 아두이노 레퍼런스에서 발췌한 함수에 관련된 내용입니다.

pinMode()

Description

Configures the specified pin to behave either as an input or an output. See the description of digital pins for details on the functionality of the pins.

As of Arduino 1.0.1, it is possible to enable the internal pullup resistors with the mode INPUT_PULLUP. Additionally, the INPUT mode explicitly disables the internal pullups.

Syntax

pinMode(pin, mode)

Parameters

pin: the number of the pin whose mode you wish to set

mode: INPUT, OUTPUT, or INPUT_PULLUP. (see the digital pins page for a more complete description of the functionality.)

Returns

None

pinMode함수는 디지털 핀의 input, output을 설정하는 함수로 파라미터는 핀의 번호와 input인지 output인지 상태를 알려주는 변수가 필요합니다.

mode는 라이브러리에 define이 되어 있는 INPUT OUTPUT INPUT_PULLUP 세가지를 쓸수 있습니다. input_pullup은 핀이 입력을 받을때 내부 풀업을 사용한다는말입니다. setup함수에서 핀의 용도의 레지스터를 셋팅하면 이제 핀의 상태를 바꿔주면 LED가 반응하게 됩니다. Loop함수에서 일정 시간마다 핀의 상태를 변경시켜주도록 하겠습니다.

우선 핀의 상태를 변경하는 함수를 보겠습니다.

digitalWrite()

Description

Write a HIGH or a LOW value to a digital pin.

If the pin has been configured as an OUTPUT with pinMode(), its voltage will be set to the corresponding value: 5V (or 3.3V on 3.3V boards) for HIGH, 0V (ground) for LOW.

If the pin is configured as an INPUT, writing a HIGH value with digitalWrite() will enable an internal 20K pullup resistor (see the tutorial on digital pins). Writing LOW will disable the pullup. The pullup resistor is enough to light an LED dimly, so if LEDs appear to work, but very dimly, this is a likely cause. The remedy is to set the pin to an output with the pinMode() function.

NOTE: Digital pin 13 is harder to use as a digital input than the other digital pins because it has an LED and resistor attached to it that's soldered to the board on most boards. If you enable its internal 20k pull-up resistor, it will hang at around 1.7 V instead of the expected 5V because the onboard LED and series resistor pull the voltage level down, meaning it always returns LOW. If you must use pin 13 as a digital input, use an external pull down resistor.

Syntax

digitalWrite(pin, value)

Parameters

pin: the pin number

value: HIGH or LOW

Returns

none

핀을 OUT으로 사용한다는 가정하에 이 함수는 작용한다. digitalWrite함수는 파라메터로 핀의 번호와 출력상태를 갖는다. 출력은 HIGH 와 LOW를 갖는다. 마찬가지로 라이브러리에 define이 되어있다.

GPIO에 관련된 함수로는 위의 함수외에 digitalRead() 가 있다. pinMode()함수를 통해 핀을 INPUT으로 설정하면 이 함수를 사용할수 있는데 파라메터로 핀의 번호를 넣고 digitalRead함수를 호출하면 핀의 상태를 1과0으로 리턴해준다.

Loop함수 내에 digitalWrite함수를 통해 미리 정해둔 13번 핀의 상태를 High와 Low를 반복하게 설정해준다. 무한반복 되는 매우 빠르기 떄문에 delay없이 High와 Low를 반복한다면 실제로 보이는건 매우 빨라서 계속 켜져 있는것 처럼 보이게 된다 그래서 중간중간에 delay함수를 추가해 눈에 보이게 한다.

아두이노 라이브러리에서 정해놓은 함수들은 라이브러리 폴더에 가면 함수의 원형을 볼수 있다. 이 함수들은 MCU 에서 각 함수관련 레지스터를 직접 제어하게 된다. 이부분은 하드웨어라면 쉽게 볼수 있을 것 이고 소프트웨어라면 구지 알지 않아도 사용하는데 크게 지장이 없을것이라 생각된다.

GPIO는 가장 기본이 되는 기능이지만 Digital 신호에선 모든것이라고 말할수 있습니다. High/Low로 모든 것을 표현하기 떄문입니다. 이 1과0의 조합으로 모터속도 제어를 하고 엄청난양의 데이터 통신도 하고 센서값도 받아오고...MCU에서 내부 적으로 구현한 IO를 응요한 다양한 기능을 이제부터 배워보도록 하겠습니다.

이번 포스팅부터 External Interrupt , Timer/Counter , ADC , serial통신 을 순서대로 배워보도로 하겠습니다. 이는 MCU를 배울때 가장 기본적으로 그리고 많이 사용되는 기능입니다.

External Interrupt

외부 인터럽트는 말그대로 외부에서 어떤 인터럽트가 발생 했을때 계속 반복되고 있는 loop문에서 잠시 다른 일을 처리할수 있도록 만든 기능입니다.

예를들어 1초에 한번씩 LED 가 점등되고 있는 상황인데 어떤 버튼을 누르면 좀더 빠르게 LED가 점등되고 또 다른버튼을 누르면 좀더 느리게 점등되게 하는 시스템이 있다고 해보겠습니다. 점등되는 속도를 컨트롤 하는 스위치 2개가 필요하고 각각의 스위치가 눌렸을때를 감지하고 눌린 버튼에 해당되는 인련의 행동을 하게 해주는 것이 외부 인터럽트 입니다.

외부 인터럽트가 걸리면 항상Loop를 돌고 있던 시스템이 잠시 인터럽트 서비스 루틴으로 점프해 인터럽트에서 정의한 행동을 한 후 다시 Loop로 되돌아 가게 되는 것 입니다.

이 외부 인터럽트는 핀의 상태를 읽어 인터럽트를 걸리게 하는 것 입니다. 하지만 일반 핀을 input으로 설정하여 읽는 것 과의 차이점은 input으로 설정해서 핀의 상태를 읽는건 루프 내에서 매 주기마다 계속 읽어와 상태의 변경을 파악하고 어떤 일련의 행동을 하지만 외부인터럽트는 사용자가 직접 핀의 상태를 읽지 않아도 MCU가 자체적으로 핀의 상태를 파악해 사용자가 설정한 변경값이 포착되면 높은 우선순위로 인터럽트 서비스 루틴으로 점프하게 해준다.

인터럽트 감지에 대한 모드는 총 4가지가 있다. 이것은 외부인터럽트 설정 함수 레퍼런스를 설명할때 좀더 자세히 설명하겠습니다. 외부 인터럽트는 주로 0번1번(pin2, pin3) 이렇게 2개가 있고 아두이노 메가의 경우는 4개(pin21, pin20, pin19, pin18)를 지원합니다.

attachInterrupt()

Description

Specifies a function to call when an external interrupt occurs. Replaces any previous function that was attached to the interrupt. Most Arduino boards have two external interrupts: numbers 0 (on digital pin 2) and 1 (on digital pin 3). The Arduino Mega has an additional four: numbers 2 (pin 21), 3 (pin 20), 4 (pin 19), and 5 (pin 18).

Syntax

attachInterrupt(interrupt, function, mode)

Parameters

interrupt: the number of the interrupt (int)

function: the function to call when the interrupt occurs; this function must take no parameters and return nothing. This function is sometimes referred to as an interrupt service routine.

mode defines when the interrupt should be triggered. Four contstants are predefined as valid values:

  • LOW to trigger the interrupt whenever the pin is low,
  • CHANGE to trigger the interrupt whenever the pin changes value
  • RISING to trigger when the pin goes from low to high,
  • FALLING for when the pin goes from high to low.

Returns

none

외부 인터럽트를 위한 함수의 레퍼런스 입니다. 파라미터는 외부인터럽트가 들어올 핀의 번호, 인터럽트서비스루틴 함수 이름, 인터럽트가 감지되는 모드 이렇게 3가지가 있습니다. 위에서 설명 했듯이 인터럽트는 보통 0,1 두개가 있고 메가 시리즈는 0,1,2,3 4개가 존재 합니다. 모드는 4가지 모드가 있습니다.

LOW : 핀의 입력이 LOW일때 인터럽트가 발생

CHANGE : 핀의 입력 이 변화 할때 즉 LOW->HIGH 혹은 HIGH->LOW의 경우 인터럽트 발생

RISING : 핀의 입력이 LOW->HIGH일때 인터럽트 발생

FALLING : 핀의 입력이 HIGH->LOW일때 인터럽트 발생

그리고 마지막으로 인터럽트 서비스 루틴 함수는 어떻게 사용하는지 예를 통해 설명하겠습니다.

int pin = 13;
volatile int state = LOW;

void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE);
}

void loop()
{
digitalWrite(pin, state);
}

void blink()
{
state = !state;
}

우선 인터럽트 서비스 루틴 함수를 하나 선언해 줍니다. 그 함수 내부엔 인터럽트가 발생 했을때 줄 변화에 대한 행동을 지정합니다. 그리고 attachinterrupt 함수를 호출시 2번째 파라메터로 함수의 이름을 넘겨줍니다. 그러면 3번째 파라메터의 모드에 의해 핀의 변화가 생길때 loop를 계속 돌던 MCU가 인터럽트 서비스 루틴 함수에 있는 행동을 처리하고 다시 loop로 돌아가게 되는 것 입니다.

흔히 기본적으로 외부 인터럽트를 공부할때 쓰는 하드웨어 예제를 함께 보도록 하겠습니다.

다음과 같은 회로가 있습니다.

PD0은 외부 인터럽트 핀이구요, 회로를 보면 핀은 스위치로 GND와 연결 되어 있고 10K옴의 저항으로 풀업상태에 있습니다. 스위치가 OFF된 상태에선 PD0핀은 상항 High상태 일 것입니다. 그리고 스위치가 눌리면 저항이 작은 GND와 연결되어 LOW상태가 될 것입니다. Mode에 따라 스위치를 눌렀을때, 뗄때, 누르고 있을때 눌렀다뗄때 의 타이밍에 맞춰 ISR의 내의 어떠한 행동을 할 것입니다.