본문 바로가기
아두이노

6 인터럽트& 타이머

by Beijing_KingGod 2019. 12. 18.

인터럽트란 일정 조건 충족 시 실행 중인 프로그램을 일시 중지하고 다른 프로그램을 우선순위로 먼저 실행시키는 것이다. 인터럽트 요인이 되는 조건이 충족되었을 때 실행중인 프로그램은 일단 중지 후 강제로 우선순위의 프로그램을 먼저 실행 후 중지된 프로그램을 다시 돌아가 다시 함수를 실행한다.

 

메인함수 실행 중 인터럽트 처리 과정

 

 

인터럽트는 기본적으로 하드웨어적인 신호를 이용하기 때문에 프로그램 실행 과정에 있어서 event를 실행시킬 때, 소프트웨어적 방식인 if 함수를 사용하는 것보다 event를 더 안정적이고 빠르게 처리할 수 있다. 인터럽트발생 요인과 프로그램은 모두 사용자가 직접 만들 수 있다.

 

인터럽트의 사용 조건에서는 PULL-UP PULL-DOWN의 이론이 필수적으로 필요하다. 이 내용을 모른다면 앞 장의 디지털 입출력 편으로 돌아가  PULL-UP PULL-DOWN의 이론을 확실하게 익히고 오도록 하자.

 

예제를 실험해 보기 앞서 가장 기본적인 3가지만 공부한 후 시작하도록 하자.

 

1. 아두이노 사용가능 핀번호

  아두이노 우노에서는 디지털핀 2번과 3번에서만 인터럽트 기능이 지원된다.

  (아두이노 모델마다 인터럽트 가능 핀의 수와 번호는 각각 다르다.)

 

2. 인터럽트 등록 함수

  void attachInterrupt(interrupt, ISR, mode)

 

interrupt : 인터럽트 함수 번호(핀번호가 아니다 우노에서는 2개의 인터럽트를 사용 할 수 있으므로 인터럽트 번호 0 1만 사용하면 된다.)

ISR    :  인터럽트가 발생할 때 수행할 서브함수 이름

mode  :  인터럽트가 수행될 조건

 

3. 인터럽트의 수행 조건의 종류(인터럽트 mode)

  우리는 디지털 입출력 단원에서 택트스위치를 이용하여 HIGH LOW 2가지 상태를 제어했지만 인터럽트 단원에서는 HIGH에서 LOW로 떨어지는 FALLING LOW에서 HIGH로 올라가는 RISING 신호를 더 이용할 수 있다. 인터럽트의 수행 조건의 종류는 4가지이며 아래의 4가지 중 원하는 상황에만 인터럽트가 발생하도록 지정하여 사용할 수 있다

 

LOW - 신호가 LOW일 때 항상 인터럽트 발생

 

RISING - 신호가 LOW에서 HIGH로 바뀔 때만 인터럽트 발생

 

FALLING - 신호가 HIGH에서 LOW로 바뀔 때만 인터럽트 발생

 

CHANGE - 신호가 RISING 또는 FALLING 일 때 발생

 

인터럽트와 일반 IF문의 가장 큰 차이점은 FALLING RISING이다. 기존에는 HIGH혹은 LOW의 신호만을 이용했지만 인터럽트를 사용하면 더 정밀한 부분인 FALLING 신호와 RISING 신호까지 사용할 수 있게 된다. FALLING RISING신호를 이용할 때 주의해야 할 점은 HIGH, LOW 신호와는 달리 각각의 신호가 지속되지 않고 한번만 일어난다는 것이다. 예를 들어 입력의 상태가 HIGH를 유지하가 LOW로 떨어졌을 때 단 한번 신호를 받는다는 것이다. 다시 FALLING 신호를 받기 위해서는 LOW에서 HIGH RISING을 한 후 HIGH상태에서 다시 LOW로 떨어져야 비로소 다시 신호를 받게 된다. 항상 HIGH LOW신호는 지속될 수 있지만 FALLING RISING신호는 지속될 수 없다는 점을 유의하도록 하자.

 

첫번째 예제로 익히 사용했었던 PULL-DOWN 회로를 이용하여 인터럽트 스위치를 구성하여 본다.

 

[인터럽트 예제 배선도]
[인터럽트 예제 회로도]

 

[예제 코드]

volatile int형이 사용되었다. 인터럽트 함수에 사용할 전역변수는 안정성의 이유로 반드시 volatile 함수로 선언해 주어야 한다.

 

다음과 같이 회로구성 후 아두이노보드에 프로그램을 정상적으로 업로드 하였다면 스위치를 한 번 누를 때마다 LED의 상태가 반전될 것이다.

 

 

Q1) Interrupt MODE FALLING CHANGE로 바꾸어보고 RISING으로 했을 때와 무엇이 다른지 생각해 본 후 HIGH LOW의 그래프를 그려 인터럽트 발생 과정을 설명하여라.

 

A1) PULL-DOWN저항을 이용하였을 때 스위치를 누르지 않은 상태가 LOW, 누르고 있는 상태가 HIGH 가 된다. 한 번 눌렀을 때 FALLING 이 한 번 일어나며 그것을 떼었을 때 RISING이 한 번 일어난다. (스위치를 떼고있을 때 처음상태 LOW -> 스위치를 눌렀을 때 RISING신호 한번 받음 -> 누른 스위치를 떼지 않고 있을 때 HIGH신호 유지 -> 누르고 있던 스위치를 뗐을 때 FALLING신호 한번 받음 - 다시 누르지 않는다면 LOW신호 유지)

 

INPUT_PULLUP

현재까지 우리는 편의상의 이유로 PULL-DOWN저항을 이용하여 스위치를 눌렀을 때 HIGH가 되도록 하는 회로를 많이 구성하였다. 하지만 실제로 회로를 설계할 경우 PULL-DOWN보다 PULL-UP저항을 더 많이 사용한다. 이유는 PULL-UP 저항이 noise나 충격에 더 강하기 때문이다.

 아두이노 각각의 디지털출력포트에는 내부 PULL-UP저항이 달려있기 때문에 회로에 직접 설계하지 않아도 함수문 하나만으로 PULL-UP저항을 사용할 수 있다.

그 함수가 바로 pinMode(pin, INPUT_PULLUP) 이다.

아두이노에는 이처럼 PULLUP저항을 간단하게 사용할 수 있다. 여태까지 연습한 PULL-DOWN저항이 아깝긴 하지만 실력이 향상될수록 PULLUP저항을 더 많이 사용하게 될 것이니 다음의 예제를 풀어보며 PULLUP저항을 이용한 인터럽트발생에 익숙해지도록 하자.

 

 

[풀업저항 회로구성]

다음 회로는 일반적인 풀업저항을 연결한 회로도이다. 빨간색 네모로 표시한 부분이 아두이노 디지털 포트 내부에 설계되어 있다고 생각하면 될 것이다.

 

그렇다면 아두이노 내부 풀업저항을 사용한다면 회로에 풀업저항을 따로 설계하지 않아도 될 것이다. 다음 예제를 실습하며 그 사용법을 익혀보도록 하자.

 

                  다음과 같이 회로를 구성하고 프로그래밍하여 보자.

 

 

[회로구성]
[회로사진]
[예제코드]

다음과 같이 회로구성 후 아두이노보드에 프로그램을 정상적으로 업로드 하였다면 외부에 풀업저항을 구성하지 않아도 플로팅현상이 일어나지 않고 스위치를 누를 때마다 LED의 상태가 반전될 것이다.

 

타이머

 

/타이머란/

/타이머의 원리/

/타이머 사용 가능 핀/

/타이머 등록 함수/

타이머 라이브러리 사용하면 등록 함수는 아주 간단하다. 타이머 라이브러리는 아두이노 홈페이지(http://playground.arduino.cc/Main/MsTimer2) 에서 다운받을 수 있다.

 

MsTimer2::set(ms,  ISR)  /타이머주기와 타이머 서브함수를 설정한다.

MsTimer2::start()         /타이머를 활성화한다.

MsTimer2::stop()            /타이머를 해제한다.

 

/타이머가 필요한 이유/

우리는 앞서 시간 관련된 부분을 모두 delay()함수를 이용하여 처리하였다. 물론 delay()함수 역시 아두이노 내부에서는 타이머를 이용하여 처리하지만 우리가 굳이 타이머를 따로 이용해야 할 이유가 있을까? 다음 문제는 타이머의 필요성을 실험을 통해 배울 수 있다.

 

Q) LED1 2초를 간격으로 ON, OFF를 반복하고 LED2는 스위치를 누를 때만 ON되도록 한다.

[회로구성]
[예제 코드]

다음과 비슷하게 설계하였다면 현재까지 배운 과정으로 살펴보았을 때 아주 잘한 것이다.

하지만 막상 실행시켜보면 정상적으로 작동하지 않을 것이다. 그 이유는 바로 delay() 함수 때문이다.

우리는 그동안 어떠한 입력에 지연시간을 주기 위하여 delay()함수를 이용하였다. 하지만 이 delay()함수에는 치명적인 약점이 있다. 바로 입력한 지연시간 동안에는 아두이노는 아무런 입력을 받지 못한다는 것. 우리는 스위치를 이용하여 원하는 순간에 LED2번을 점등시키려 하였지만 loop()문의 함수 발생 과정을 살펴보면 LED1번이 HIGH LOW를 출력하는 4초 동안은 if(sw_state == HIGH)부분을 실행하지 못하는 것이다. 이러한 delay()함수의 치명적인 약점을 아두이노 내부 TIMER를 이용하여 보완할 수 있다.

 

 

다음과 같이 소스를 변경하여 업로드 해보도록 하자.

 

[예제 코드]

loop()문 안에 delay()함수가 사라진 것을 볼 수 있다.

 

 

[회로사진]

다음과 같이 회로구성 후 아두이노 보드에 프로그램을 정상적으로 업로드 하였다면 LED1번이 HIGH LOW을 출력 할 때에도 스위치의 입력이 정상적으로 작동하는 것을 볼 수 있을 것이다.

'아두이노' 카테고리의 다른 글

8. 스마트 카 원격제어  (0) 2019.12.18
7. 블루투스 통신  (0) 2019.12.18
5.2 서보모터 제어하기  (0) 2019.12.18
5.1 DC모터 제어하기  (0) 2019.12.18
4.3 아두이노 아날로그 출력  (0) 2019.12.18

댓글