[아두이노] [아두이노 강좌] 22. Interrupt(인터럽트) (2) - 스위치로 LED 켜고 끄기 예제

자, 지난 시간에 인터럽트란 무엇인가에 대해서 알아봤으니, 이번 시간에는 인터럽트는 어디에 사용되는가에 대해 알아보자.


강좌 제목에 나와있다시피 스위치로 LED를 켜고 끄는 예제를 만들어 볼 것이다스위치를 한번 누르면 LED가 켜지고한번 더 누르면LED가 꺼지는 동작을 만들어 보자.

 

우선 브레드 보드에 스위치와 LED를 아래 그럼과 같이 연결한다.


da949dfd061c41205ae94514762df5d8.png


스위치의 검정색 선과 LED의 검정색 선은 아두이노 보드의 GND로 연결하고스위치의 주황색 선은 2번에, LED의 노란색 선은 13번에 꽂는다스위치 핀이야 어디에 꽂아도 상관없지만 LED를 다른 핀에 꽂을 경우 반드시 LED 동작 전압을 확인해서 저항을 사용하도록 한다안 그러면 LED가 터져요!


그리고 다음 소스를 입력한다.

 


 interruptTest01.ino

  

 int ledPin = 13;

 int swPin = 2;

 boolean bLedOn = false;

 

 void setup() {

   pinMode(ledPin, OUTPUT);

   pinMode(swPin, INPUT_PULLUP);

 

   digitalWrite(ledPin, LOW);

 }

 

 void loop() {

   if(digitalRead(swPin) == LOW) {

     if(bLedOn == false) {

       digitalWrite(ledPin, HIGH);

       bLedOn = true;

     } else {

       digitalWrite(ledPin, LOW);

       bLedOn = false;

     }

   }

 }





간단하게 소스 설명.


 

LED를 켜고 끄기 위한 출력 핀과 스위치 상태를 읽기 위한 입력 핀을 선언한 후 모드를 초기화 한다이 때스위치는 따로 풀업 저항을 사용하지 않았으므로 내부 풀업을 사용하도록 INPUT_PULLUP 모드로 설정한다는 것에 유의그리고 LED 핀의 초기 값을 LOW로 줘서 LED가 꺼진 상태로 동작을 시작하도록 한다.

 

“bLedOn” 변수는 LED의 현재 상태를 저장하기 위한 변수이며, bLedOn 값에 따라 LED를 켤 것인가끌 것인가를 결정한다.

 

그리고 loop() 함수에서 스위치 핀의 상태를 읽어서 스위치가 눌린 경우즉 swPin의 입력 값이 LOW인 경우에 bLedOn 값에 따라 LED를 켜거나 끈다. bLedOn false이면 LED를 켜고 bLedOn 값을 true로 변경아니라면 LED를 끄고 bLedOn 값을 false로 변경.

 

어렵지 않아요.




그럼 업로드 하기 전에 손 한번 들어볼까요~? 위 소스가 제대로 동작할 것이라고 생각하는 사람 손??

 


moon_and_james-39 

 

 


눈치 빠른 사람은 손 들어보라는 질문 자체에서 이미 동작이 안될 것이라는 것을 예상했을 것이고이미 왜 안 되는지 이유를 알고 있는 사람도 있을 것이여허허.

 

동작 안 된다.

 

스위치를 누르면 LED가 약간 어둡게 켜지거나 빠르게 깜빡이다가 스위치를 떼면 완전히 켜지거나 완전히 꺼진다왜요왜 때문이죠?


스위치가 눌려졌을 때의 입력 신호는 다음과 같다.

 

4724a2e37e705369232c640d8c25ab15.jpg


스위치가 눌리면 입력 값은 LOW로 떨어지고스위치에서 손을 뗄 때까지 LOW 값을 유지한다. loop()문에서 digitalRead() 함수가 반복되어 호출되므로 스위치가 눌려져 있는 동안은 LED가 계속해서 켜지고 꺼지는 동작을 반복하게 된다그리고 스위치에서 손을 떼면 마지막으로 변경된 LED의 상태가 지속되는 것이다.


이거 의외로 초보자들이 자주 하는 실수임. 

 

우리가 원하는 동작은 스위치가 눌렸을 때 한번만 LED의 상태가 바뀌는 건데그럼 어떻게 해야 하나요?

 



LED의 이전(previous) 상태를 알기 위해 변수를 하나 사용한 것처럼 스위치의 이전 상태를 알기 위한 변수를 하나 더 추가하면 된다다음 소스를 볼까?



 interruptTest02.ino


 ledPin = 13;

 int swPin = 2;

 boolean bLedOn = false;

 boolean bSwOn = false;

 

 void setup() {

   pinMode(ledPin, OUTPUT);

   pinMode(swPin, INPUT_PULLUP);

 

   digitalWrite(ledPin, LOW);

 }

 

 void loop() {

   if(digitalRead(swPin) == LOW) {

     if(bSwOn == false) {

       bSwOn = true;

       if(bLedOn == false) {

         digitalWrite(ledPin, HIGH);

         bLedOn = true;

       } else {

         digitalWrite(ledPin, LOW);

         bLedOn = false;

       }

     }

   } else {

     bSwOn = false;

   }

 }




빨간 색으로 굵게 표시된 부분이 추가된 부분이다.

 

“bSwOn”이라는 변수를 사용해서 스위치의 이전 상태를 확인하고 있다스위치가 눌렸을 경우(swPin LOW인 경우스위치의 이전 상태가 눌림 상태가 아닐 때(bSwOn 값이 false일 때) LED의 상태를 변경한다이 때 스위치의 상태를 눌림 상태(true)로 저장.

 

스위치의 상태가 눌림 상태로 바뀌었으므로 다시 loop() 함수가 돌아와 digitalRead(swPin) 함수로 읽어온 값이 여전히 LOW여도 LED의 상태를 변경하지 않는다스위치가 눌린 후 처음 조건문에 들어왔을 때에만 LED 상태를 변경하는 것그리고 swPin 상태가 HIGH가 됐을 때즉 스위치가 떨어졌을 때 다시 bSwOn 변수에 false 값을 저장해서 스위치가 눌림 상태가 아니라는 것을 기억한다.

 

이제 업로드 한 후 스위치를 눌러보자제대로 동작 해야 된대이hoppinmad_angry_line_characters-5

 

 

된다. brown_and_cony-76




오늘 실습 끝!

 

은 농담이고이거랑 인터럽트랑 무슨 상관??

 


스위치를 누를 때마다 LED를 켜고 끄는 간단한 동작을 만드는데소스가 좀 복잡해 보인다게다가 swPin 상태를 끊임없이계속쭈욱 확인해야 한다.

 



loop() 함수의 마지막 부분에 “delay(1000);”을 추가한 후 동작해보자


동작이 잘 안 된다반응이 느릴뿐더러 스위치를 짧게 누르면 아예 동작을 안 하기도 한다. 1초간 동작을 멈추는 동안 스위치의 상태를 읽어올 수 없어서 나타나는 현상이다. 만일 delay(1000)이 꼭 필요한 경우라면 어떻게 해야 하나?


 

이러한 상황을 위해 인터럽트가 있다. 똑같은 동작을 인터럽트를 사용한 소스로 바꿔보자. 아래 소스에서 swPin, 즉 스위치의 핀은 반드시 아두이노 보드의 2번 핀에 연결되어 있어야 한다.




 interruptTest03.ino

  

 int ledPin = 13;

 int swPin = 2;

 boolean bLedOn = false;

 

 void setup() {

   pinMode(ledPin, OUTPUT);

   pinMode(swPin, INPUT_PULLUP);

   attachInterrupt(0, swInterrupt, FALLING);

 

   digitalWrite(ledPin, LOW);

 }

 

 void loop() {

   delay(1000);

 }

 

 void swInterrupt() {

   if(bLedOn == false) {

     digitalWrite(ledPin, HIGH);

     bLedOn = true;

   } else {

     digitalWrite(ledPin, LOW);

     bLedOn = false;

   }

 } 




새로운 함수가 나왔어.

 

우선 동작부터 시켜볼까아까랑 똑같이 동작하는 걸 볼 수 있다. 어디에도 swPin의 상태를 확인하는 함수가 없는데도, 심지어 loop() 함수에 delay(1000) 구문이 있는데도 불구하고 버벅임이나 시간 지연 없이 자연스럽게 동작하는 것을 확인할 수 있을 것이다. 




attachInterrupt() 함수는 swPin의 상태를 확인해서 핀의 상태가 HIGH에서 LOW로 바뀔 때 swInterrupt() 함수를 자동 호출하도록 설정하는 함수이다. 


그래서 스위치가 눌려 swPin이 LOW로 변하면 loop() 문에 무슨 내용이 있든, 스위치가 눌린 후 계속 눌려져 있든, 금방 떨어지든 상관 없이, 딱 한 번만 swInterrupt() 함수가 호출되는 것이다. 




이제 인터럽트에 대해 조금은 이해가 되는가?




혹시 스위치를 눌렀을 때 swInterrupt() 함수가 여러 번 호출되는 듯한 느낌을 받는다면 아마 그건 채터링(Chattering)이라는 현상 때문일 것이다. 



attachInterrupt() 함수에 대한 자세한 내용과 채터링에 관련된 내용은 다음 강좌에서 살펴보도록 하겠다. 오늘은 여기까지. 안녕~!




뭔가 급하게 끝내는 기분..brown_and_cony-31

0
0
이 글을 페이스북으로 퍼가기 이 글을 트위터로 퍼가기 이 글을 카카오스토리로 퍼가기 이 글을 밴드로 퍼가기

임베디드 보드

번호 제목 글쓴이 날짜 조회수
38 아두이노 [강좌] 30. I2C 통신 (2) - Wire 함수 알아보기 icon 양재동메이커 03-20 23,764
37 아두이노 [강좌] 29. I2C 통신 (1) - I2C 통신이란 무엇인가 icon 양재동메이커 03-20 28,196
36 아두이노 [강좌] 28. 시간 관련 함수 (3) - MsTimer2 라이브러리 icon 양재동메이커 03-20 19,966
35 아두이노 [강좌] 27. 시간 관련 함수 (2) - BlinkWithoutDelay 예제 icon 양재동메이커 03-20 14,265
34 아두이노 [강좌] 26. 시간 관련 함수 (1) - delay() / millis() icon 양재동메이커 03-20 19,838
33 아두이노 [강좌] 25. tone()/noTone() 함수 (2) - 부저 실습 icon 양재동메이커 03-20 14,416
32 아두이노 [강좌] 24. tone()/noTone() 함수 (1) - 함수 설명 icon 양재동메이커 03-20 15,976
31 아두이노 [강좌] 23. Interrupt(인터럽트) (3) - 인터럽트 함수 알아보기 icon 양재동메이커 03-20 14,926
30 아두이노 [아두이노 강좌] 22. Interrupt(인터럽트) (2) - 스위치로 LED 켜고 끄기 예제 icon 양재동메이커 03-20 22,342
29 아두이노 [강좌] 21. Interrupt(인터럽트) (1) - 인터럽트란 무엇인가 icon 양재동메이커 03-16 14,596
28 아두이노 [아두이노 강좌] 20. String (3) - 유용한 함수들 icon 양재동메이커 03-16 22,412
27 아두이노 [강좌] 19. String (2) - String() 생성자와 + 연산 icon 양재동메이커 03-16 12,694
26 아두이노 [강좌] 18. String (1) - 문자형(char) 배열과 String icon 양재동메이커 03-16 22,452
25 아두이노 [강좌] 17. Serial 통신(3) - 유용한 기능들 icon 양재동메이커 03-15 16,705
24 아두이노 [강좌] 16. Serial 통신(2) - 시리얼 통신 함수 알아보기 icon 양재동메이커 03-15 21,016
23 아두이노 [강좌] 15. Serial 통신(1) - 시리얼 통신이란 무엇인가 icon 양재동메이커 03-15 19,293
22 아두이노 [강좌] 14. analogRead()/analogWrite() 실습 - 조도 센서 + LED icon 양재동메이커 03-15 12,671
21 아두이노 [강좌] 13. analogWrite() 실습 - LED 밝기 조절하기(Fade 예제) icon 양재동메이커 03-15 12,992
20 아두이노 [강좌] 12. 아날로그 기능(2) - analogWrite() 함수 icon 양재동메이커 03-14 14,513
19 아두이노 [강좌] 11. analogRead() 함수 실습 - 습도 센서 icon 양재동메이커 03-14 12,614