-
아두이노 | 디지털 인터럽트Technology/Arduino 2024. 11. 15. 17:31
1. 디지털 인터럽트
디지털 인터럽트는 디지털 신호가 특정 조건을 만족할 때 자동으로 특정 함수를 실행하는 기능이다. 이때 아두이노 루프 함수에서 실행되던 프로그램은 일시 정지되고, 인터럽트 서비스 루틴(Interrupt Service Routine, ISR)에 할당된 프로그램을 먼저 실행한 뒤, 루프 함수에서 실행되던 프로그램을 다시 실행한다. 조건문으로 디지털 신호를 감지하여 프로그램을 실행하는 것과 무엇이 다른지 비교해보기 위해 아래 예시를 살펴보자.
volatile byte LEDState = LOW; // LED 상태 변수 정의 volatile byte SwitchState = LOW; // 택트 스위치 상태 변수 정의 void setup() { pinMode(11, OUTPUT); // 디지털 11번 핀을 출력(OUTPUT) 모드로 설정 pinMode(2, INPUT); // 디지털 2번 핀을 입력(INPUT) 모드로 설정 Serial.begin(9600); // 시리얼 통신 시작 (통신 속도: 9600 bps) } void loop() { // 시리얼 모니터에 숫자를 오름차순으로 출력 for (int i = 0; i <= 10; i++) { Serial.println(i); volatile byte SwitchRead = digitalRead(2); // 디지털 신호를 저장하기 위한 변수 정의 // 택트 스위치 버튼 누름 감지 if (SwitchRead != SwitchState) { if (SwitchState == HIGH) { LEDState = !LEDState; // LED 상태 변수 반전 digitalWrite(11, LEDState); // 디지털 11번 핀에 디지털 신호를 출력 } SwitchState = SwitchRead; // 택트 스위치 상태 변수 갱신 } delay(1000); // 1000 ms 대기 } // 시리얼 모니터에 숫자를 내림차순으로 출력 for (int i = 9; i >= 1; i--) { Serial.println(i); SwitchRead = digitalRead(2); if (SwitchRead != SwitchState) { if (SwitchState == HIGH) { LEDState = !LEDState; digitalWrite(11, LEDState); } SwitchState = SwitchRead; } delay(1000); } }
위 예시는 아두이노 IDE 시리얼 모니터에 0과 10 사이의 숫자를 오름차순과 내림차순으로 출력하는 한편, 택트 스위치로부터 디지털 신호를 읽어 LED를 제어하는 프로그램이다. 시리얼 모니터에 숫자를 나타낸 직후 택트 스위치에 연결된 디지털 입출력 핀으로부터 디지털 신호를 읽어들이며, 이때 택트 스위치가 눌렸다가 다시 올라오는 순간을 감지한다. 위 프로그램을 실제로 작동시켜보면 우리가 의도한 대로 동작하지 않는 것을 확인할 수 있다. 이는 아두이노가 디지털 신호를 읽어들이는 순간에 맞게 우리가 택트 스위치를 눌렀다 떼어야 하는데 그 순간을 제대로 맞추지 못했기 때문이다. 반복문 등을 통해 디지털 신호를 일정 시간동안 반복해서 읽어들인다면 이 문제는 해결되겠지만, 디지털 신호를 읽어들이는 시간 동안은 시리얼 모니터에 숫자가 출력되지 않을 것이다. 이때 디지털 인터럽트를 사용한다면 프로그램을 방해하지 않으면서 우리가 원하는 동작을 구현할 수 있다.
2. 확인사항
모든 아두이노 하드웨어는 기본적으로 디지털 인터럽트 기능을 탑재하고 있으며, 디지털 입출력 핀에 해당 기능이 할당되어 있다. 아두이노 하드웨어에 따라 인터럽트를 지원하는 핀의 위치와 개수가 다른데, 아두이노 우노 기준으로 디지털 입출력 핀 2번과 3번에 인터럽트 기능이 할당되어 있다. 해당 핀들을 인터럽트 핀으로 사용하기 위해서는 setup 함수에서 각 핀의 기능을 선언하는 것과 같이 인터럽트 기능을 할당한다는 함수를 선언해야 한다. 이때 사용하고자 하는 디지털 입출력 핀, 실행하고자 하는 함수, 실행 조건을 함께 설정해주어야 한다. 실행 조건에는 ① LOW에서 HIGH로 변하는 RISING, ② HIGH에서 LOW로 변하는 FALLING, ③ LOW 상태를 감지하는 LOW, ④ RISING과 FALLING을 모두 감지하는 CHANGE가 있는데, 아두이노 우노의 경우 RISING, FALLING, LOW만 지원한다. 아래 링크로 접속하면 아두이노에서 지원하는 인터럽트 기능에 대한 전반적인 정보를 얻을 수 있다.
3. 주의사항
디지털 인터럽트가 기존에 동작하고 있던 loop 함수를 일시 정지시키고 다른 함수를 동작시키는 만큼, 인터럽트로 실행되는 함수는 최대한 간단하게 작성되어야 한다. 따라서 인터럽트 함수에는 delay 함수, millis 함수, Serial 클래스 메소드 등 동작하는 데 오랜 시간을 소요하는 함수는 사용할 수 없다. 또한 인터럽트 함수 내에서는 전역 변수만 사용해야 하며, 컴파일 에러를 방지하기 위해 휘발성(volatile) 변수만을 사용하는 것을 권장한다.
4. 예제
4.1. 회로 구성
4.2. 프로그램 작성
volatile byte LEDState = LOW; // LED 상태 변수 정의 void setup() { pinMode(11, OUTPUT); // 디지털 11번 핀을 출력(OUTPUT) 모드로 설정 pinMode(2, INPUT); // 디지털 2번 핀을 입력(INPUT) 모드로 설정 // 디지털 인터럽트 정의 // (1) 디지털 2번 핀을 인터럽트로 사용 // (2) 인터럽트 시 blink 함수 호출 // (3) 디지털 신호가 HIGH에서 LOW로 변할 때 함수 호출 attachInterrupt(digitalPinToInterrupt(2), blink, FALLING); Serial.begin(9600); // 시리얼 통신 시작 (통신 속도: 9600 bps) } void loop() { // 시리얼 모니터에 숫자를 오름차순으로 출력 for (int i = 0; i <= 10; i++) { Serial.println(i); delay(1000); // 1000 ms 대기 } // 시리얼 모니터에 숫자를 내림차순으로 출력 for (int i = 9; i >= 1; i--) { Serial.println(i); delay(1000); } } void blink() { LEDState = !LEDState; // LED 상태 변수 반전 digitalWrite(11, LEDState); // 디지털 11번 핀에 디지털 신호를 출력 }
[함께 읽으면 좋은 페이지]
참고문헌
- Arduino. (n.d.). attachInterrupt(). https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/. 2024.11.15.
- DroneBot Workshop. (2022).Understanding Arduino Interrupts | Hardware, Pin Change & Timer Interrupts. YouTube. https://www.youtube.com/watch?v=wIcC8-g9Lnw. 2024.11.15.
반응형'Technology > Arduino' 카테고리의 다른 글
아두이노 | 유도형 근접 스위치 DC 5V 모듈 (0) 2024.11.19 아두이노 프로젝트 | 컨베이어 벨트 (0) 2024.11.17 아두이노 | 바이폴라 스텝모터 드라이버 TB6600 모듈 (4) 2024.11.14 아두이노 라이브러리 | 스텝모터 가속 제어 (3) 2024.11.13 아두이노 | 바이폴라 스텝모터 드라이버 A4988 모듈 마이크로 스테핑 (4) 2024.11.09