본문 바로가기
코딩/아두이노

[아두이노 강좌] 예제로 배우는 아두이노 #8 timer interrupt() 사용법, delay 없이 LED 제어하기

by DIYver 2020. 3. 30.

<목표>

 

 

- delay() 함수를 사용하지 않고, LED를 원하는 시간만큼 점등시키고 소등시킬 수 있다.

 


<준비물>

 

 

- 아두이노(나노, 우노, 메가), 시리얼 통신 케이블, 브레드보드, led(백색)

아두이노 우노 / 시리얼 통신 케이블(USB-B타입) /  브레드보드 / LED 


<회로도>

 

이전 강의부터 계속 언급하지만, 원래는 1 led당 1저항이 원칙이다. 하지만 백색 led의 경우 타지않고 버틸 수 있기 때문에 편의성을 위해서 저항을 사용하지 않는다.

그리고 led가 없더라도 13번핀은 내부 led와 연결되어 있으므로 외부 led가 없어도 이번 강의를 이해하는데 문제 없다.


<코드>

 

const int ledPin =  LED_BUILTIN;// the number of the LED pin

int ledState = LOW;             // ledState used to set the LED

unsigned long previousMillis = 0;        // will store last time LED was updated

const long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    digitalWrite(ledPin, ledState);
  }
}

코드는 아두이노 - 파일 - 예제 - 02.Digital - BlinkWithoutDelay 의 예제 파일과 동일 합니다.

예제파일을 쓰셔도 되고, 위의 코드를 복사하여 붙여넣으셔도 됩니다.

 


<실행 결과>

 

 

 

설정한 시간마다 반복적으로 LED가 점등되고 소등되는 것을 볼 수 있다.

 

delay( time )으로 제어하면 더 간단하게 동일한 결과를 낼 수 있는데 왜 이렇게 힘들게 구현하냐고 물을 수 있다.

가장 큰 차이는 아두이노 코드가 멈추느냐, 계속 실행되느냐의 차이이다.

delay() 함수를 사용하는 경우에는, 아두이노가 실행되다가 delay() 함수 부분에서 일시 정지하게 된다.

말 그대로 그 멈춘 순간에는 어떠한 동작도 할 수 없다.

하지만 위와 같은 방법으로 구현한다면 아두이노가 다른 작업도 수행할 수 있다는 것이다.

아두이노가 A 라는 작업을 하고 있을 때, 중간에 끊고 B라는 작업을 하게 하는 것이 interrupt "인터럽트" 이다.

크게 인터럽트는 Timer-interrupt (타이머 인터럽트) 와 External-interrupt (외부 신호 인터럽트) 가 있다고 볼 수 있다.

타이머 인터럽트는 아두이노 자체 타이머가 계속 돌아가면서 일정 시간마다 작업을 실행시키는 것이며,

외부 신호 인터럽트는 쉽게 말해서 특정 버튼이 눌리면 기존의 코드를 멈추고 특별 작업을 실행시키는 것이다.

가장 대표적인 예가 기계 장치의 STOP 스위치가 되겠다.

 

이번 강의부터는 코드가 복잡하고 어려워지므로 자세하게 코드설명을 하도록 하겠다.

 

전역변수 선언 구간으로써,

LED핀은 내장LED를 사용한다. (= digital 13번 핀으로 설정한다.)

ledState 라는 변수에 초기 led상태를 LOW로 설정한다.

previousMillis 라는 변수에 초기값 0을 설정한다. 변수이름을 보면 이전 시간을 저장하는 변수이다.

interval 라는 변수에 값을 1000으로 설정한다. 시간 간격을 1000 ms로 한다고 짐작할 수 있다.

 

 

setup 에서

내장 LED에 해당하는 핀(13번핀)을 출력으로 설정한다.

 

loop 에서

현재 타이머를 저장시킬 변수로 currentMillis 라는 변수를 선언하고, millis() 함수를 통해 타이머를 시작시킨다.

조건문을 통해서  현재 타이머 값과 이전 타이머 값의 차이가 설정한 시간 간격 1000ms보다 크다면

아래의 명령들(1~3)을 수행한다.

 

  1. 우선, 이전 타이머 변수(perviousMillis)에 현재 타이머 값을 저장시킨다.

 

  2. 그리고 만약 현재 led상태가 꺼져있는 상태라면 ledState 변수에 HIGH로 저장한다.

만약 현재 led상태가 켜져있는 경우라면 ledState 변수에 LOW 로 저장한다.

 

  3. digitalWrite()함수를 통해 LED핀에 해당 출력을 내보낸다.

 

 

즉, 아두이노가 전원이 켜지고난 후로 약 1초마다 코드를 실행시키면서 이전 타이머 변수를 최신화하고

LED 상태를 바꿔주면서 점등과 소등을 반복시키는 것이다.

 

해당 코드를 다른 코드와 합쳐서 사용하더라도 LED는 정상적으로 1초마다 점등과 소등을 반복하게 된다.

 

 

이 방법에도 문제가 있다는 것을 눈치채신 분도 계실거라 생각한다.

곰곰히 생각해보면 loop 반복문 안에서 실행이 되는 경우로,

아두이노 코드가 길어지고 사용하는 센서가 많아졌을 때

전체 코드를 1회 도는데 2초가 걸렸다고 한다면 led는 1초마다 점등과 소등을 반복하는것이 아니라 2초마다 반복하게 된다.

이런경우에도 해결방법이 있지만 여기서는 다루지 않도록 한다.

 

그리고 위의 방법은 인터럽트이기는 하지만, 소프트웨어 인터럽트이다. 하드웨어 인터럽트로 설정하는 방법은 다음에 기회되면 다루도록 하겠다.

하드웨어 인터럽트가 더 정확하며 명확하다.

 


※ 궁금하시거나 질문사항이 있으시면 댓글로 작성해주시면 답변해 드릴 수 있는 부분에서 친절히 답변드리겠습니다!

 

 

 

 

댓글