본문으로 바로가기
반응형

회로에서는

5V == on == 1 == True
0V == off == 0 == False  임을 기억하고있자.

 

회로를 구성했을때 on인지 off인지 모르는 상태를 떠있는 상태라고해서 플로팅상태라고 부른다.

스위치를 뗐을때(스위치가 오픈일때) 어떤 값인지 모르는 상태이기때문에 스위치가 연결되어있지 않았을때는 그라운드와 연결해서 input 핀에 0이 감지되어야 할것이다.

 

풀업(평상시 1을 읽고 있다가 스위치를 눌렀을때 0을 들고와야함.)

풀다운(평상시 0을 읽고 있다가 스위치를 눌렀을때 1을 들고와야함.)

 

 

 

1. 풀다운 회로에서 스위치를 눌렀을때 pushed가 출력되는 회로와 코드를 구성해보자.

# -*- coding: utf-8-*-
import RPi.GPIO as GPIO     # 모듈 RPi.GPIO를 사용하겠다는 뜻임(as로 명명가능)
import time                 # time.sleep을 쓰기위해 import로 선언

switch1 = 6                  # 입력핀 설정
GPIO.setmode(GPIO.BCM)       # BCM 모드 사용(pin은 BCM으로 쓰겠다는 뜻)

GPIO.setup(switch1, GPIO.IN) # 핀모드(입력) (출력으로 사용하려면 GPIO.OUT으로 사용)
GPIO.setup(LED, GPIO.OUT)

try:
   while True:
     if GPIO.input(switch1) == True:
         print("1번Pushed")
         time.sleep(0.3)    # 이거 없으면 스위치눌렀을때 Pushed가 주르륵나옴
                            # 스위치를 눌렀을때의 진동때문에 주르륵나오는데                  
                            # 진동구간을 잠시 무시하고 눌러지는 순간의 데이터만 읽겠다는 뜻

except KeyboardInterrupt:   # 컨트롤 + C 누르면 프로그램 종료
   GPIO.cleanup()

 

 

if문에 time.sleep(0.3)을 해줬는데

실제로 스위치를 눌렀을때 신호가 0에서 바로 1이 되는게 아니라 스위치를 눌렀을때의  시점으로보면 아주 미세한 진동이 일어나서 신호가 오락가락하다가 1이 된다.

지금 하던 회로는 왼쪽의 경우이다

따라서 빨간 네모구간을 스킵하고, 그 다음의 신호만 감지하겠다는 뜻으로 time.sleep() 을 사용하는 것이다.

 

 

 

 

 

 

2. 풀다운 회로 2개를 사용해서 1번 스위치를 눌렀을때 LED on,

                                        2번 스위치를 눌렀을때 LED off하는 회로와 코드를 설계해보자.

# -*- coding: utf-8-*-
# 파일이름 : sw2.py
# 1번 스위치누르면 ON, 2번 스위치누르면 off
import RPi.GPIO as GPIO     # 모듈 RPi.GPIO를 사용하겠다는 뜻임(as로 명명가능)
import time                 # time.sleep을 쓰기위해 import로 선언

switch1 = 6                  # 입력핀 설정
switch2 = 5
LED = 2
GPIO.setmode(GPIO.BCM)      # BCM 모드 사용(pin은 BCM으로 쓰겠다는 뜻)

GPIO.setup(switch1, GPIO.IN) # 핀모드(입력) (출력으로 사용하려면 GPIO.OUT으로 사용)
GPIO.setup(switch2, GPIO.IN)
GPIO.setup(LED, GPIO.OUT)
GPIO.output(LED, False)
try:
   while True:
      if GPIO.input(switch1) == True:
         print("1번Pushed=>LED On")
         GPIO.output(LED, True)
         time.sleep(0.3)
      elif GPIO.input(switch2) == True:
         print("2번Pushed=>LED Off")
         GPIO.output(LED, False)
         time.sleep(0.3)
except KeyboardInterrupt:
   GPIO.cleanup()

 

 

 

 

 

 

3. 스위치 한개로만 LED의 on과 off를 제어해보자.(회로 구성은 1개)

# -*- coding: utf-8-*-
# 파일 이름 : sw3.py
# 스위치 한번 누르면 켜지고, 한번 누르면 꺼지게하는 코드
import RPi.GPIO as GPIO     # 모듈 RPi.GPIO를 사용하겠다는 뜻임(as로 명명가능)
import time                 # time.sleep을 쓰기위해 import로 선언

switch1 = 6                  # 입력핀 설정
LED = 2
state = 1
GPIO.setmode(GPIO.BCM)      # BCM 모드 사용(pin은 BCM으로 쓰겠다는 뜻)

GPIO.setup(switch1, GPIO.IN) # 핀모드(입력) (출력으로 사용하려면 GPIO.OUT으로 사용)
GPIO.setup(LED, GPIO.OUT)

GPIO.output(LED, False)   # 처음 코드 실행때는 불을 끈 상태에서 시작

try:
   while True:
      if GPIO.input(switch1) == True:
         print("Pushed")
         if (state == 1):           # state가 1이면 불을 킴(홀수)
            GPIO.output(LED, True)
         else:                      # state가 짝수면 불을 끔
            GPIO.output(LED, False)
         time.sleep(0.3)
         state = state + 1          # 스위치 누를때마다 +1해줌
         state = state % 2          # 스위치 누를때마다 나머지연산으로 홀짝을 구분

except KeyboardInterrupt:
   GPIO.cleanup()

 

회로는 새로 구성하기 귀찮아서 스위치 2개쓰던 회로에서 연결만 1개로 해놨다

 

해당 코드는 플래그를 state의 홀짝으로 구분하여 작성하였다.

처음에는 1로 시작해서 ++을 해주고, 나머지 연산 %를 통해 홀짝이 되도록하면서 state가 너무 커지지않게 작성하였다.

 

 

 

위의 예제는 플래그를 홀짝으로 나눴는데, T/F로 플래그를 선언해서 좀 더 간편하게 코드를 구성해보자.

 

4. 풀다운 저항기준. 플래그를 T/F로 코드를 작성

 #-*-coding: utf-8-*-
import RPi.GPIO as GPIO
import time

switch = 6
flag = False

GPIO.setmode(GPIO.BCM)
GPIO.setup(switch, GPIO.IN, pull_up_down = GPIO.PUD_DOWN) # 내부풀다운 사용

def swBlink(chaneel):  # callback 함수
   global flag         # 전역변수로쓰려면 global로 선언해줘야함.
   if flag == False:
      print("interrupt")
     flag = True
   else:
      flag = False

#인터럽터핀에 라이징 신호가 인가되면 콜백함수로 리턴되어 실행
GPIO.add_event_detect(switch, GPIO.RISING, callback=swBlink)

try:
   while True:
      pass

except KeyboardInterrupt:
   print()
   GPIO.cleanup()

 

스위치를 누를때마다 "interrupt"가 프린트되어 출력된다.

 

위 코드는 스위치 감지를위한 time.sleep() 코드가 필요없는데, 스위치를 누름으로써 신호의 변화가 감지했을때를 interrupt이기 때문에 감지했을때만 콜백함수가 호출되기때문에 코드가 좀 더 간소화 되었다.

 

함수 내에서 볼때는 플래그가 거짓이 될때마다 interrupt가 출력된다.

 

(콜백 : 다른 코드의 인수로서 넘겨주는 실행 가능한 코드를 말한다. 이게 실행되면 자동적으로 함수가 호출된다.)

 

스위치를 누르면 하드웨어가 신호를 캐치해서 시그널이 함수를 호출하는 것임.

 

 

 

1. High 일때 (Low였다가 High일때)

2. Low 일때 (High였다가 Low일때)

3. Rising 일때 (Low였다가 High가 변하는 순간)

4. falling 일때 (Low였다가 High가되는데 다시 Low가 될때의 순간)

 

 

 

여기에 LED를 연결해서 인터럽트가 되면(스위치누르면) LED를 켜고, 또 인터럽트를 감지하면(또 스위치누르면) LED를 끄는 회로와 코드를 작성해보자. (회로는 어제했던 풀다운 회로와 같다)

 

5. 플래그 T/F를 적용하여 스위치를 한번 누르면 LED On, 또 한번 누르면 LED Off가 되는 코드 작성(회로는 풀다운)

 #-*-coding: utf-8-*-
# 파일이름 : int2.py
import RPi.GPIO as GPIO
import time

switch = 6
LED = 2
flag = False

GPIO.setmode(GPIO.BCM)
GPIO.setup(switch, GPIO.IN, pull_up_down = GPIO.PUD_DOWN) # 내부풀다운 사용
GPIO.setup(LED, GPIO.OUT)
GPIO.output(LED, False)

def swBlink(channel):      #callback 함수
   global flag
   if flag == False:
      GPIO.output(LED, True)
      print("interrupt")
      flag = True
      time.sleep(0.3)
   else:
      flag = False
      GPIO.output(LED, False)
      time.sleep(0.3)

#인터럽터핀에 라이징 신호가 인가되면 콜백함수로 리턴되어 실행
GPIO.add_event_detect(switch, GPIO.RISING, callback=swBlink)

try:
   while True:
      pass
except KeyboardInterrupt:
   print()
   GPIO.cleanup()

인터럽트 신호가 감지될때마다 콜백함수가 호출되는데, 기존의 코드에서 LED를 켜고 끄는 코드만 추가해주면된다.

 

 

반응형