스위치를 이용한 3 Color LED 제어 > IoT 유무선제어

본문 바로가기

[실습] 스위치를 이용한 3 Color LED 제어

필기자
2025-03-25 14:29 115 2
  • - 첨부파일 : KakaoTalk_20240223_175217786.mp4 (4.7M) - 다운로드

본문

스위치를 이용한 3 Color LED 제어

목 적
  • 라즈베리파이에 GPIO 이벤트 방식에 대해 이해한다.
  • 라즈베리파이에 복합적인 액츄레이터 모듈 구현에 대해 이해한다.
목 차
1. LED 버튼 앳츄레이터 묘듈 설치
2. LED 버튼 앳츄레이터 묘듈 구동

1. LED 버튼 앳츄레이터 뮤듈 설치
  • YwRobot LED 버튼 모듈
    • 내장된 LED를 가진 푸시버튼 스위치로 버튼을 누르면 LED가 켜지거나 꺼진다.
    • 학습, 실험, 프로토타이핑에 주로 사용되며, 마이크로컨트롤러 보드에 쉽게 연결할 수 있다.
    • 전원(VCC), 접지(GND), 신호(OUT) 등의 핀을 포함하며, 디지털 입력으로 버튼 상태를 마이크로컨트롤러가 읽는다.
    • 다양한 전자 프로젝트에 사용자 인터페이스 요소로 활용된다.
    • GPIO 연결
      • GND  : Ground 접지(핀 14)
      • VCC : 5V Power(핀 2)
      • OUT : GPIO 18(핀 12)
3529946166_K5SIJTjG_1143fc1289e187aa325c67a115e90068d989fbd1.png


3529946166_bofVl7YE_266e303a143793bc94d7801369b5f2e0eaa9f6a1.png

2. LED 버튼 앳츄레이터 묘듈 구동
  • 라즈베리파이 가상환경에서 파이썬 코딩
    • VSCode에서 3_color_led_switch.py 파일 생성
    • GPIO 17, 27, 22 핀을 출력 모드로 설정, GPIO 18 핀을 입력 모드로 설정
    • GPIO 18 핀의 이벤트에 따라 LED 색상 변경
3529946166_qKEdom0h_82e1341f24ee84c14b813f0aa054006cbac1164c.png

import RPi.GPIO as GPIO
import time

# 핀 번호 설정
BUTTON_PIN = 18  # 버튼이 연결될 GPIO 핀 번호
BLUE_PIN = 17
GREEN_PIN = 22
RED_PIN = 27

# 글로벌 변수
led_state = 0  # LED 상태 (0: 모두 꺼짐, 1: 파란색, 2: 초록색, 3: 빨간색)

# GPIO 설정 함수
def setup_gpio():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.setup(BLUE_PIN, GPIO.OUT)
    GPIO.setup(GREEN_PIN, GPIO.OUT)
    GPIO.setup(RED_PIN, GPIO.OUT)

# 모든 LED 끄는 함수
def turn_off_leds():
    global led_state
    led_state = 0
    GPIO.output(BLUE_PIN, GPIO.LOW)
    GPIO.output(GREEN_PIN, GPIO.LOW)
    GPIO.output(RED_PIN, GPIO.LOW)

# LED 상태 변경 함수
def change_led_state():
    global led_state
    led_state += 1
    if led_state > 3:
        led_state = 1
    if led_state == 1:
        GPIO.output(BLUE_PIN, GPIO.HIGH)
        GPIO.output(GREEN_PIN, GPIO.LOW)
        GPIO.output(RED_PIN, GPIO.LOW)
    elif led_state == 2:
        GPIO.output(BLUE_PIN, GPIO.LOW)
        GPIO.output(GREEN_PIN, GPIO.HIGH)
        GPIO.output(RED_PIN, GPIO.LOW)
    elif led_state == 3:
        GPIO.output(BLUE_PIN, GPIO.LOW)
        GPIO.output(GREEN_PIN, GPIO.LOW)
        GPIO.output(RED_PIN, GPIO.HIGH)

# 버튼 이벤트 콜백 함수
def button_callback(channel):
    start_time = time.time()

    # 버튼이 눌린 상태 유지 확인
    while GPIO.input(BUTTON_PIN) == GPIO.LOW:
        # 누린 상태는 LOW, 뗀 상태는 HIGH
        # 버튼이 눌린 상태이면 무한반복 -> 버튼이 뗀 상태이면 반복문 빠짐
        # GPIO.FALLING 상태로 눌린 순간 이벤트가 발생하지만 GPIO.RISING 처럼 움직임(버튼을 뗀 순간 다음 로직 실행).
        time.sleep(0.01)  # 디바운싱 대기

    button_press_duration = time.time() - start_time
    if button_press_duration >= 1:  # 1초 이상 누르면 LED 끄기
        turn_off_leds()
    else:  # 짧게 누르면 LED 색상 변경
        change_led_state()

# GPIO 종료 함수
def cleanup_gpio():
    GPIO.cleanup()

# 메인 함수
def main():
    setup_gpio()
    # 프로그램 시작 시 모든 LED 끄기
    turn_off_leds()
    # 버튼 이벤트 감지 설정
    # GPIO.FALLING 는 누르는 순간(LOW) 이벤트 발생
    GPIO.add_event_detect(BUTTON_PIN, GPIO.FALLING, callback=button_callback, bouncetime=300)

    try:
        while True:
            time.sleep(0.1)
    except KeyboardInterrupt:
        pass
    finally:
        cleanup_gpio()

# 실행 진입점
if __name__ == "__main__":
    main()
  • GPIO.add_event_detect()
    • GPIO 핀에 이벤트 감지(callback) 기능을 추가하는 데 사용된다.
    • 특정 핀의 상태 변경(예: 라이징 엣지, 폴링 엣지)을 비동기적으로 감지한다.
    • 변경이 감지될 때마다 지정된 콜백 함수를 자동으로 호출할 수 있다. 
인자 이름 데이터 타입 기능
channel int 이벤트 감지를 추가할 GPIO 핀의 번호.
GPIO.RISING, GPIO.FALLING, GPIO.BOTH   감지할 이벤트의 종류를 지정. RISING은 0에서 1로의 변화, FALLING은 1에서 0으로의 변화, BOTH는 둘 다 감지.
callback function 이벤트가 감지될 때 호출될 콜백 함수.
bouncetime int 선택적. 이벤트 콜백 호출 사이에 적용될 디바운스(신호안정) 시간(밀리초 단위).
 
이벤트 감지 플레그 설명
GPIO.RISING GPIO 핀의 신호가 LOW에서 HIGH로 변할 때
GPIO.FALLING GPIO 핀의 신호가 HIGH에서 LOW로 변할 때
GPIO.BOTH GPIO 핀의 신호가 변화할 때(LOW에서 HIGH 또는 HIGH에서 LOW)
 
  • 3_color_led_switch.py 실행
    • VSCode > 하단 터미널 > python 3_color_led_switch.py 실행
3529946166_bqTtZrvW_7baf4afe0ac4a9c1aaa894c6f6c1f52bbbd1de8f.png

3529946166_0Bsn1tip_3c0c4bb07c63dcfdb7faa6b53dfb1e5b40a709f6.gif

[문제: RGB LED 색상 조합 제어 실습]
  • 하나의 공통형 RGB LED를 사용하여, 버튼을 누를 때마다 LED 색상이 아래 순서대로 변경되도록 하시오.
    • 버튼 누를 때마다 색상 변경 순서
      • 1. 빨강
      • 2. 초록
      • 3. 파랑
      • 4. 노랑
      • 5. 하늘
      • 6. 보라
      • 7. 흰색
      • 8. OFF
※ 버튼은 짧게 누를 때만 반응, 길게 눌렀을 때는 무시
※ 버튼은 GPIO.FALLING 이벤트로 감지


import RPi.GPIO as GPIO
import time

# 핀 설정
BUTTON_PIN = 18
RED_PIN = 22
GREEN_PIN = 27
BLUE_PIN = 17

# 상태 변수
led_state = 0  # 0: OFF, 1~7: 색 조합

# GPIO 설정
def setup_gpio():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.setup(RED_PIN, GPIO.OUT)
    GPIO.setup(GREEN_PIN, GPIO.OUT)
    GPIO.setup(BLUE_PIN, GPIO.OUT)

# 모든 LED 끄기
def turn_off():
    GPIO.output(RED_PIN, GPIO.LOW)
    GPIO.output(GREEN_PIN, GPIO.LOW)
    GPIO.output(BLUE_PIN, GPIO.LOW)

# LED 색상 설정
def set_color(state):
    colors = {
        1: (1, 0, 0),  # 빨강
        2: (0, 1, 0),  # 초록
        3: (0, 0, 1),  # 파랑
        4: (1, 1, 0),  # 노랑
        5: (0, 1, 1),  # 하늘
        6: (1, 0, 1),  # 보라
        7: (1, 1, 1),  # 흰색
    }
    if state == 0:
        turn_off()
    else:
        r, g, b = colors[state]
        GPIO.output(RED_PIN, GPIO.HIGH if r else GPIO.LOW)
        GPIO.output(GREEN_PIN, GPIO.HIGH if g else GPIO.LOW)
        GPIO.output(BLUE_PIN, GPIO.HIGH if b else GPIO.LOW)

# 버튼 콜백
def button_callback(channel):
    global led_state
    start = time.time()
    while GPIO.input(BUTTON_PIN) == GPIO.LOW:
        time.sleep(0.01)
    duration = time.time() - start
    if duration < 1:
        led_state += 1
        if led_state > 7:
            led_state = 0
        set_color(led_state)

# 메인
def main():
    setup_gpio()
    turn_off()
    GPIO.add_event_detect(BUTTON_PIN, GPIO.FALLING, callback=button_callback, bouncetime=300)
    try:
        while True:
            time.sleep(0.1)
    except KeyboardInterrupt:
        pass
    finally:
        GPIO.cleanup()

if __name__ == "__main__":
    main()

댓글목록2

kkl81님의 댓글

kkl81
2025-03-25 14:29
/home/pi/iot/ledSwitch.py:11: RuntimeWarning: This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
  GPIO.setup(BLUE_PIN, GPIO.OUT)
/home/pi/iot/ledSwitch.py:12: RuntimeWarning: This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
  GPIO.setup(GREEN_PIN, GPIO.OUT)
/home/pi/iot/ledSwitch.py:13: RuntimeWarning: This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
  GPIO.setup(RED_PIN, GPIO.OUT)
Traceback (most recent call last):
  File "/home/pi/iot/ledSwitch.py", line 55, in <module>
    GPIO.add_event_detect(BUTTON_PIN, GPIO.FALLING, callback=button_callback, bouncetime=300)
RuntimeError: Failed to add edge detection

필기자님의 댓글

필기자
2025-03-25 14:29
import os
import psutil

def kill_other_python_processes():
    current_pid = os.getpid()  # 현재 내 프로세스 PID
    for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
        try:
            # 프로세스 이름이 'python' 또는 'python3'인지 확인
            if ('python' in proc.info['name'] or 'python3' in proc.info['name']) and proc.info['pid'] != current_pid:
                os.kill(proc.info['pid'], 9)  # 강제 종료
                print(f"Killed PID: {proc.info['pid']}, CMD: {proc.info['cmdline']}")
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            continue

# 프로그램 시작 시 호출
kill_other_python_processes()
게시판 전체검색