Arduino Uno Switch Input EXTI Method for LED Control
스위치 인터럽트 방식을 이용하여 우선순위에 따라 사용할 수 있는 두 가지 코드 예제
를 소개합니다.Hardware
준비물
본 예제의 구성품은 아래와 같습니다.
- Arduino Uno x 1 EA
- Dip Type LED x 1 EA
- Dip Type Tact Switch x 1 EA
- Dip Type Resistor x 1 EA
- Bread Board x 1 EA
- Jumper Wires
회로도 : 스위치, LED연결
(좌) 회로도, (우) 연결 방법 예시
본 예제의 회로 구성은 아래와 같습니다.
- D2 : 스위치 인터럽트 FALLING EDGE 로 설정, 내부 풀업 사용
- Switch ON 시점 : LED Toggle
- D13 : LED 출력
- HIGH 출력 일 때 LED 켜짐
- LOW 출력일 때 LED 꺼짐
예제 설명
- 예제1 - 스위치 동작 우선 순위 최고 높은 경우 :
ISR()에서 모두 실행 - 예제2 - 스위치 동작 우선 순위 높으나 즉시 실행 하지 않아도 될 때 :
ISR()에서flag활성화loop()에서 기능 동작
※
Interrupt Service Routine(ISR)은 인터럽트가 접수되었을 때 실행 되는 코드입니다.ISR은Interrupt Handler와 동일한 용어 입니다.
예제1 : ISR에서 모두 실행
Code
스위치가 ON 되는 타이밍에 LED 를 토글시키는 명령어 입니다.
Serial.println() 문은 인터럽트 우선 순위 처리를 확인하기 위해 작성하였습니다.
loop() 문의 delay() 함수는 코드 실행 순서롤 보여 주기 위해 억지로 시간 지연을 추가하였습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #define switchPin 2 // 스위치 핀 번호 #define ledPin 13 // LED 핀 번호 volatile int state = LOW; void setup() { pinMode(switchPin, INPUT_PULLUP); pinMode(ledPin, OUTPUT); attachInterrupt(digitalPinToInterrupt(switchPin),INT0_ISR,FALLING); //Interrupt Init Serial.begin(9600); while(!Serial) {;} Serial.println("Program Start...."); delay(1000); } void loop() { Serial.println("Statement 1"); delay(300); Serial.println("Statement 2"); delay(300); Serial.println("Statement 3"); delay(300); Serial.println("Statement 4"); delay(300); Serial.println("Statement 5"); delay(300); } void INT0_ISR() //Interrupt ISR { digitalWrite(ledPin, !digitalRead(ledPin)); Serial.println("LED Toggled!"); } | cs |
실행 결과
아래 영상과 같이 Tack-Switch 를 누르는 순간 LED 가 Toggle 되는 결과를 볼 수 있습니다.
예제2 : ISR에서 Flag 만 활성화
Code
스위치가 ON 되는 타이밍에 bFlag 를 True 로 활성화하고, LED 토글기능은 loop() 문 안에서 다른 기능들과 함께 순차적으로 처리 합니다.
Serial.print() 문은 Example 1 과 처리 방식 차이를 보여주기 위해 작성한 코드입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #define switchPin 2 // 스위치 핀 번호 #define ledPin 13 // LED 핀 번호 volatile boolean bFlag = false; void setup() { pinMode(switchPin, INPUT_PULLUP); pinMode(ledPin, OUTPUT); attachInterrupt(digitalPinToInterrupt(switchPin),INT0_ISR,FALLING); //Interrupt Init Serial.begin(9600); while(!Serial) {;} Serial.println("Program Start...."); delay(1000); } void loop() { Serial.println("Statement 1"); delay(300); Serial.println("Statement 2"); delay(300); Serial.println("Statement 3"); delay(300); Serial.println("Statement 4"); delay(300); Serial.println("Statement 5"); delay(300); if(bFlag == true){ // bFlag 가 True 인 경우 실행 bFlag = false; digitalWrite(ledPin, !digitalRead(ledPin)); Serial.println("----> LED Toggled!"); } } void INT0_ISR() //Interrupt ISR, 버튼 ON 되는 경우 bFlag 를 반전 { bFlag = !bFlag; Serial.println("----> Button Pushed!!"); } | cs |
실행 결과
아래 동영상과 같이 Tact-Switch 누르는 순간에 ISR() 함수로 진입하고, LED Toggle 기능은 "Statement 5" 실행 이 후 동작합니다. Tact-Switch 가 Statement 5 실행 완료 전까지 짝수만큼 눌려지는 경우 LED Toggle 기능은 수행하지 않습니다.
Review
예제1, 예제2 결과비교
아래 그림은 예제1과 예제2의 프로그램 순서도를 나타냅니다. 예제1은 INT0 인터럽트가 발생하면 LED Toggle 기능을 수행 후 ISR 함수를 빠져나옵니다. 예제2는 INT0 인터럽트가 발생하면 전역변수 bFlag 를 반전하고, loop() 문에서 순차적인 동작을 수행합니다.
(좌) 예제1, (우) 예제2 프로그램 순서도 및 결과
위의 두가지 방식으로 프로그램을 작성하였지만, 어느 것이 더 좋다고 말할 수는 없습니다. 이벤트의 종류에 따라 최우선적으로 실행이 되어야 하는지, 이벤트를 기억하고 실행을 누락만 하지 않으면 되는 지에 따라 코드 작성 방법이 선택되어야 합니다.
ISR(Interrupt Handler) 함수는 메인 loop() 에서 잠깐 빠져나와 동작을 하기 떄문에, ISR() 함수 내에서 최소한의 코드만 수행되어야 하는 것이 보편적입니다. 하지만, 용도에 따라, 코드작성에 따라 유연하게 사용이 가능합니다.
문제점 : 디바운스 소개
위 프로그램 실행 결과 스위치를 한번 눌려질 때 스위치의 물리적인 진동에 의해 접촉면이 붙었다가 떨어지는 현상이 발생합니다. 이런 현상을 채터링(Chattering) 이라고 하고 방지하기 위해 디바운스라는 방법을 사용합니다. 해결 방법으로 회로조치, 소프트웨어 코드 추가 등의 방법이 있고, 일반적으로 두가지 모두 사용합니다.
마무리
본 포스트는 인터럽트 방식으로 스위치를 입력 받아 LED를 제어하는 코드에 대해 알아보았습니다. 사용자가 결정하는 버튼 동작 인터럽트 우선순위에 따라 2가지 방식의 코드를 소개하였습니다.
이 회로와 코드에서는 채터링 현상을 방지하는데는 한계가 있습니다. 다음 포스트는 소프트웨어적인 방법으로 채터링을 방지하는 디바운스 코드를 소개할 예정입니다.
끝까지 읽어주셔서 감사합니다.^^
'Embedded > Arduino' 카테고리의 다른 글
아두이노 코딩 : 엔터 입력시(문장단위) Serial Echo 프로그램, Putty 로 CR+LF 전송 (0) | 2020.07.23 |
---|---|
아두이노 코딩 스위치 채터링과 디바운스 디바운싱 (4) | 2020.07.21 |
아두이노 코딩 스위치 입력 폴링 방식 (Switch Polling) 으로 LED 제어 (0) | 2020.07.19 |
아두이노 코딩 LED Toggle (On/OFF) 여러 가지 방식 (0) | 2020.07.19 |
아두이노 팁 #4. Visual Studio Code로 아두이노 디버깅 환경 설정 및 실행 (8) | 2020.07.18 |