03. Python GPIO ์ œ์–ด

03. Python GPIO ์ œ์–ด

ํ•™์Šต ๋ชฉํ‘œ

  • RPi.GPIO ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ๋ฒ• ์Šต๋“
  • gpiozero ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•œ ๊ฐ„ํŽธํ•œ GPIO ์ œ์–ด
  • LED ์ถœ๋ ฅ ์ œ์–ด (๋””์ง€ํ„ธ/PWM)
  • ๋ฒ„ํŠผ ์ž…๋ ฅ ์ฒ˜๋ฆฌ (ํ’€์—…/ํ’€๋‹ค์šด, ์ธํ„ฐ๋ŸฝํŠธ)
  • ์„ผ์„œ ์—ฐ๊ฒฐ ๋ฐ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ (DHT11, PIR)

1. GPIO ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ฐœ์š”

1.1 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋น„๊ต

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŠน์ง• ๋‚œ์ด๋„ ๊ถŒ์žฅ ์šฉ๋„
RPi.GPIO ์ €์ˆ˜์ค€, ์„ธ๋ฐ€ํ•œ ์ œ์–ด ์ค‘๊ธ‰ ์ •๋ฐ€ ์ œ์–ด, ํƒ€์ด๋ฐ
gpiozero ๊ณ ์ˆ˜์ค€, ์ง๊ด€์  API ์ž…๋ฌธ ๊ต์œก, ๋น ๋ฅธ ํ”„๋กœํ† ํƒ€์ดํ•‘
pigpio ์›๊ฒฉ ์ œ์–ด, ์ •๋ฐ€ ํƒ€์ด๋ฐ ๊ณ ๊ธ‰ ์„œ๋ณด, ์ •๋ฐ€ PWM
lgpio ์ตœ์‹ , Pi 5 ์ง€์› ์ค‘๊ธ‰ Pi 5 ํ”„๋กœ์ ํŠธ

1.2 ์„ค์น˜

# RPi.GPIO (๋ณดํ†ต ๊ธฐ๋ณธ ์„ค์น˜๋จ)
sudo apt install python3-rpi.gpio

# gpiozero (๊ถŒ์žฅ)
sudo apt install python3-gpiozero

# pigpio (์ •๋ฐ€ ํƒ€์ด๋ฐ ํ•„์š”์‹œ)
sudo apt install pigpio python3-pigpio
sudo systemctl enable pigpiod
sudo systemctl start pigpiod

2. RPi.GPIO ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

2.1 ๊ธฐ๋ณธ ๊ตฌ์กฐ

#!/usr/bin/env python3
"""RPi.GPIO ๊ธฐ๋ณธ ๊ตฌ์กฐ"""

import RPi.GPIO as GPIO
import time

# 1. ํ•€ ๋ฒˆํ˜ธ ์ฒด๊ณ„ ์„ค์ •
GPIO.setmode(GPIO.BCM)  # BCM ๋ฒˆํ˜ธ ์‚ฌ์šฉ (GPIO ๋ฒˆํ˜ธ)
# GPIO.setmode(GPIO.BOARD)  # ๋ฌผ๋ฆฌ์  ํ•€ ๋ฒˆํ˜ธ ์‚ฌ์šฉ

# 2. ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€ ๋น„ํ™œ์„ฑํ™” (์„ ํƒ)
GPIO.setwarnings(False)

# 3. ํ•€ ์„ค์ •
LED_PIN = 17
GPIO.setup(LED_PIN, GPIO.OUT)  # ์ถœ๋ ฅ ํ•€

BUTTON_PIN = 27
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # ์ž…๋ ฅ ํ•€ (ํ’€์—…)

try:
    # 4. GPIO ์‚ฌ์šฉ
    GPIO.output(LED_PIN, GPIO.HIGH)
    time.sleep(1)
    GPIO.output(LED_PIN, GPIO.LOW)

finally:
    # 5. ์ •๋ฆฌ (ํ•„์ˆ˜!)
    GPIO.cleanup()

2.2 LED ์ œ์–ด (๋””์ง€ํ„ธ ์ถœ๋ ฅ)

#!/usr/bin/env python3
"""LED ๊นœ๋นก์ด๊ธฐ (RPi.GPIO)"""

import RPi.GPIO as GPIO
import time

LED_PIN = 17

def blink_led(times: int = 5, interval: float = 0.5):
    """LED๋ฅผ ์ง€์ • ํšŸ์ˆ˜๋งŒํผ ๊นœ๋นก์ž„"""
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(LED_PIN, GPIO.OUT)

    try:
        for i in range(times):
            print(f"Blink {i + 1}/{times}")
            GPIO.output(LED_PIN, GPIO.HIGH)
            time.sleep(interval)
            GPIO.output(LED_PIN, GPIO.LOW)
            time.sleep(interval)
    finally:
        GPIO.cleanup()

if __name__ == "__main__":
    blink_led(10, 0.3)

2.3 PWM ์ถœ๋ ฅ (๋ฐ๊ธฐ ์กฐ์ ˆ)

#!/usr/bin/env python3
"""LED ๋ฐ๊ธฐ ์กฐ์ ˆ - PWM (RPi.GPIO)"""

import RPi.GPIO as GPIO
import time

LED_PIN = 18  # ํ•˜๋“œ์›จ์–ด PWM ์ง€์› ํ•€ ๊ถŒ์žฅ

def fade_led():
    """LED ํŽ˜์ด๋“œ ์ธ/์•„์›ƒ"""
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(LED_PIN, GPIO.OUT)

    # PWM ๊ฐ์ฒด ์ƒ์„ฑ (ํ•€, ์ฃผํŒŒ์ˆ˜ Hz)
    pwm = GPIO.PWM(LED_PIN, 1000)  # 1kHz
    pwm.start(0)  # ๋“€ํ‹ฐ ์‚ฌ์ดํด 0%๋กœ ์‹œ์ž‘

    try:
        while True:
            # ํŽ˜์ด๋“œ ์ธ (0% -> 100%)
            for duty in range(0, 101, 5):
                pwm.ChangeDutyCycle(duty)
                time.sleep(0.05)

            # ํŽ˜์ด๋“œ ์•„์›ƒ (100% -> 0%)
            for duty in range(100, -1, -5):
                pwm.ChangeDutyCycle(duty)
                time.sleep(0.05)

    except KeyboardInterrupt:
        pass
    finally:
        pwm.stop()
        GPIO.cleanup()

if __name__ == "__main__":
    fade_led()

2.4 ๋ฒ„ํŠผ ์ž…๋ ฅ (ํด๋ง ๋ฐฉ์‹)

#!/usr/bin/env python3
"""๋ฒ„ํŠผ ์ž…๋ ฅ - ํด๋ง ๋ฐฉ์‹ (RPi.GPIO)"""

import RPi.GPIO as GPIO
import time

BUTTON_PIN = 27
LED_PIN = 17

def polling_button():
    """ํด๋ง์œผ๋กœ ๋ฒ„ํŠผ ์ƒํƒœ ํ™•์ธ"""
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.setup(LED_PIN, GPIO.OUT)

    print("๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด LED๊ฐ€ ์ผœ์ง‘๋‹ˆ๋‹ค. Ctrl+C๋กœ ์ข…๋ฃŒ.")

    try:
        while True:
            # ํ’€์—…์ด๋ฏ€๋กœ ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋ฉด LOW
            if GPIO.input(BUTTON_PIN) == GPIO.LOW:
                GPIO.output(LED_PIN, GPIO.HIGH)
                print("๋ฒ„ํŠผ ๋ˆŒ๋ฆผ!")
            else:
                GPIO.output(LED_PIN, GPIO.LOW)
            time.sleep(0.1)  # ๋””๋ฐ”์šด์‹ฑ

    except KeyboardInterrupt:
        pass
    finally:
        GPIO.cleanup()

if __name__ == "__main__":
    polling_button()

2.5 ๋ฒ„ํŠผ ์ž…๋ ฅ (์ธํ„ฐ๋ŸฝํŠธ ๋ฐฉ์‹)

#!/usr/bin/env python3
"""๋ฒ„ํŠผ ์ž…๋ ฅ - ์ธํ„ฐ๋ŸฝํŠธ ๋ฐฉ์‹ (RPi.GPIO)"""

import RPi.GPIO as GPIO
import time

BUTTON_PIN = 27
LED_PIN = 17
led_state = False

def button_callback(channel):
    """๋ฒ„ํŠผ ๋ˆŒ๋ฆผ ์ฝœ๋ฐฑ ํ•จ์ˆ˜"""
    global led_state
    led_state = not led_state
    GPIO.output(LED_PIN, led_state)
    print(f"LED {'ON' if led_state else 'OFF'}")

def interrupt_button():
    """์ธํ„ฐ๋ŸฝํŠธ๋กœ ๋ฒ„ํŠผ ๊ฐ์ง€"""
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.setup(LED_PIN, GPIO.OUT)

    # ์ธํ„ฐ๋ŸฝํŠธ ๋“ฑ๋ก (ํ•˜๊ฐ• ์—์ง€, ๋””๋ฐ”์šด์‹ฑ 200ms)
    GPIO.add_event_detect(
        BUTTON_PIN,
        GPIO.FALLING,
        callback=button_callback,
        bouncetime=200
    )

    print("๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด LED๊ฐ€ ํ† ๊ธ€๋ฉ๋‹ˆ๋‹ค. Ctrl+C๋กœ ์ข…๋ฃŒ.")

    try:
        while True:
            time.sleep(1)  # ๋ฉ”์ธ ๋ฃจํ”„๋Š” ๋‹ค๋ฅธ ์ž‘์—… ๊ฐ€๋Šฅ
    except KeyboardInterrupt:
        pass
    finally:
        GPIO.cleanup()

if __name__ == "__main__":
    interrupt_button()

3. gpiozero ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

3.1 gpiozero ์žฅ์ 

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    gpiozero ํŠน์ง•                             โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                              โ”‚
โ”‚  โœ“ ๊ฐ์ฒด ์ง€ํ–ฅ์  API                                          โ”‚
โ”‚  โœ“ ์ž๋™ cleanup (with ๋ฌธ ๋˜๋Š” ์ข…๋ฃŒ์‹œ)                       โ”‚
โ”‚  โœ“ ๋‹ค์–‘ํ•œ ์žฅ์น˜ ์ถ”์ƒํ™” (LED, Button, Sensor ๋“ฑ)              โ”‚
โ”‚  โœ“ ๊ฐ€๋…์„ฑ ๋†’์€ ์ฝ”๋“œ                                         โ”‚
โ”‚  โœ“ ์›๊ฒฉ GPIO ์ง€์› (๋‹ค๋ฅธ Pi ์ œ์–ด)                            โ”‚
โ”‚  โœ“ Mock ํ•€ ์ง€์› (ํ…Œ์ŠคํŠธ์šฉ)                                  โ”‚
โ”‚                                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

3.2 LED ์ œ์–ด

#!/usr/bin/env python3
"""LED ์ œ์–ด (gpiozero)"""

from gpiozero import LED
from time import sleep

# LED ๊ฐ์ฒด ์ƒ์„ฑ (GPIO 17)
led = LED(17)

# ๊ธฐ๋ณธ ์ œ์–ด
led.on()        # ์ผœ๊ธฐ
sleep(1)
led.off()       # ๋„๊ธฐ
sleep(1)

# ํ† ๊ธ€
led.toggle()    # ์ƒํƒœ ๋ฐ˜์ „
sleep(1)
led.toggle()

# ๊นœ๋นก์ด๊ธฐ (๋น„๋™๊ธฐ)
led.blink(on_time=0.5, off_time=0.5, n=5, background=True)
sleep(6)

# ์Šคํฌ๋ฆฝํŠธ ์ข…๋ฃŒ ์‹œ ์ž๋™ cleanup

3.3 PWM LED

#!/usr/bin/env python3
"""PWM LED ์ œ์–ด (gpiozero)"""

from gpiozero import PWMLED
from time import sleep

led = PWMLED(18)

# ๋ฐ๊ธฐ ์ง์ ‘ ์„ค์ • (0.0 ~ 1.0)
led.value = 0.5  # 50% ๋ฐ๊ธฐ
sleep(1)

led.value = 1.0  # 100% ๋ฐ๊ธฐ
sleep(1)

# ํŽ˜์ด๋“œ ํšจ๊ณผ (pulse)
# ๊ธฐ๋ณธ๊ฐ’: fade_in_time=1, fade_out_time=1
led.pulse(fade_in_time=2, fade_out_time=2)
sleep(10)

# ์ˆ˜๋™ ํŽ˜์ด๋“œ
for brightness in range(0, 101, 10):
    led.value = brightness / 100
    sleep(0.1)

3.4 ๋ฒ„ํŠผ ์ฒ˜๋ฆฌ

#!/usr/bin/env python3
"""๋ฒ„ํŠผ ์ œ์–ด (gpiozero)"""

from gpiozero import Button, LED
from signal import pause

led = LED(17)
button = Button(27, pull_up=True, bounce_time=0.2)

# ๋ฐฉ๋ฒ• 1: ์ฝœ๋ฐฑ ํ•จ์ˆ˜
def on_pressed():
    print("๋ฒ„ํŠผ ๋ˆŒ๋ฆผ!")
    led.on()

def on_released():
    print("๋ฒ„ํŠผ ๋–ผ์ง!")
    led.off()

button.when_pressed = on_pressed
button.when_released = on_released

# ๋ฐฉ๋ฒ• 2: LED์™€ ์ง์ ‘ ์—ฐ๊ฒฐ
# led.source = button  # ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋ฉด LED ์ผœ์ง

print("๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด์„ธ์š”. Ctrl+C๋กœ ์ข…๋ฃŒ.")
pause()  # ํ”„๋กœ๊ทธ๋žจ ์œ ์ง€

3.5 ๋ฒ„ํŠผ์œผ๋กœ LED ํ† ๊ธ€

#!/usr/bin/env python3
"""๋ฒ„ํŠผ์œผ๋กœ LED ํ† ๊ธ€ (gpiozero)"""

from gpiozero import Button, LED
from signal import pause

led = LED(17)
button = Button(27, bounce_time=0.2)

# ๋ฒ„ํŠผ ๋ˆ„๋ฅผ ๋•Œ๋งˆ๋‹ค LED ํ† ๊ธ€
button.when_pressed = led.toggle

print("๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด LED๊ฐ€ ํ† ๊ธ€๋ฉ๋‹ˆ๋‹ค.")
pause()

3.6 ๋‹ค์ค‘ LED ์ œ์–ด

#!/usr/bin/env python3
"""๋‹ค์ค‘ LED ์ œ์–ด (gpiozero)"""

from gpiozero import LEDBoard, LED
from time import sleep
from signal import pause

# ๊ฐœ๋ณ„ LED
leds = [LED(pin) for pin in [17, 27, 22]]

# ์ˆœ์ฐจ ์ ๋“ฑ
for i, led in enumerate(leds):
    led.on()
    sleep(0.5)
    led.off()

# LEDBoard ์‚ฌ์šฉ
led_board = LEDBoard(17, 27, 22)

led_board.on()       # ๋ชจ๋‘ ์ผœ๊ธฐ
sleep(1)
led_board.off()      # ๋ชจ๋‘ ๋„๊ธฐ
sleep(1)

# ๊นœ๋นก์ด๊ธฐ
led_board.blink(on_time=0.2, off_time=0.2, n=5)
sleep(3)

# ๊ฐ’ ์„ค์ • (๊ฐœ๋ณ„ ์ œ์–ด)
led_board.value = (1, 0, 1)  # ์ฒซ์งธ, ์…‹์งธ๋งŒ ์ผœ๊ธฐ
sleep(1)

4. ์„ผ์„œ ์—ฐ๊ฒฐ

4.1 DHT11 ์˜จ์Šต๋„ ์„ผ์„œ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                   DHT11 ์—ฐ๊ฒฐ๋„                               โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                              โ”‚
โ”‚   DHT11 ํ•€           Raspberry Pi                            โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                โ”‚
โ”‚   โ”‚ VCC (+) โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ 3.3V (ํ•€ 1)                         โ”‚
โ”‚   โ”‚ DATA    โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ GPIO4 (ํ•€ 7) + 10kฮฉ ํ’€์—…           โ”‚
โ”‚   โ”‚ NC      โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ์—ฐ๊ฒฐ ์•ˆํ•จ                           โ”‚
โ”‚   โ”‚ GND (-) โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ GND (ํ•€ 6)                          โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                โ”‚
โ”‚                                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
#!/usr/bin/env python3
"""DHT11 ์˜จ์Šต๋„ ์„ผ์„œ ์ฝ๊ธฐ"""

import time

# adafruit-circuitpython-dht ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ
# pip install adafruit-circuitpython-dht
# sudo apt install libgpiod2

import adafruit_dht
import board

# DHT11 ์„ผ์„œ ์ดˆ๊ธฐํ™” (GPIO4)
dht = adafruit_dht.DHT11(board.D4)

def read_dht11():
    """DHT11 ์„ผ์„œ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ"""
    try:
        temperature = dht.temperature
        humidity = dht.humidity

        if humidity is not None and temperature is not None:
            return {
                "temperature": temperature,
                "humidity": humidity,
                "status": "ok"
            }
        else:
            return {"status": "error", "message": "Failed to read"}

    except RuntimeError as e:
        # DHT ์„ผ์„œ๋Š” ๊ฐ€๋” ์ฝ๊ธฐ ์‹คํŒจํ•จ (์ •์ƒ)
        return {"status": "error", "message": str(e)}

def monitor_environment(interval: int = 5):
    """ํ™˜๊ฒฝ ๋ชจ๋‹ˆํ„ฐ๋ง"""
    print("์˜จ์Šต๋„ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์ž‘ (Ctrl+C๋กœ ์ข…๋ฃŒ)")

    while True:
        data = read_dht11()

        if data["status"] == "ok":
            print(f"์˜จ๋„: {data['temperature']:.1f}ยฐC, "
                  f"์Šต๋„: {data['humidity']:.1f}%")
        else:
            print(f"์ฝ๊ธฐ ์‹คํŒจ: {data.get('message', 'Unknown error')}")

        time.sleep(interval)

if __name__ == "__main__":
    try:
        monitor_environment(3)
    except KeyboardInterrupt:
        print("\n๋ชจ๋‹ˆํ„ฐ๋ง ์ข…๋ฃŒ")
    finally:
        dht.exit()

4.2 PIR ๋ชจ์…˜ ์„ผ์„œ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                   PIR ์„ผ์„œ ์—ฐ๊ฒฐ๋„                            โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                              โ”‚
โ”‚   PIR ํ•€             Raspberry Pi                            โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                โ”‚
โ”‚   โ”‚ VCC     โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ 5V (ํ•€ 2)                           โ”‚
โ”‚   โ”‚ OUT     โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ GPIO17 (ํ•€ 11)                      โ”‚
โ”‚   โ”‚ GND     โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ GND (ํ•€ 6)                          โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                โ”‚
โ”‚                                                              โ”‚
โ”‚   * ๊ฐ๋„/์ง€์—ฐ ์กฐ์ ˆ: ์„ผ์„œ ๋’ท๋ฉด ๊ฐ€๋ณ€์ €ํ•ญ ์กฐ์ ˆ                  โ”‚
โ”‚                                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
#!/usr/bin/env python3
"""PIR ๋ชจ์…˜ ์„ผ์„œ (gpiozero)"""

from gpiozero import MotionSensor, LED
from datetime import datetime
from signal import pause

pir = MotionSensor(17)
led = LED(27)

def motion_detected():
    """๋ชจ์…˜ ๊ฐ์ง€ ์‹œ ํ˜ธ์ถœ"""
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    print(f"[{timestamp}] ๋ชจ์…˜ ๊ฐ์ง€!")
    led.on()

def motion_ended():
    """๋ชจ์…˜ ์ข…๋ฃŒ ์‹œ ํ˜ธ์ถœ"""
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    print(f"[{timestamp}] ๋ชจ์…˜ ์ข…๋ฃŒ")
    led.off()

pir.when_motion = motion_detected
pir.when_no_motion = motion_ended

print("PIR ๋ชจ์…˜ ๊ฐ์ง€ ์‹œ์ž‘...")
print("์„ผ์„œ ์•ˆ์ •ํ™” ๋Œ€๊ธฐ ์ค‘ (์•ฝ 10์ดˆ)...")
pir.wait_for_no_motion()
print("์ค€๋น„ ์™„๋ฃŒ! ๋ชจ์…˜์„ ๊ฐ์ง€ํ•ฉ๋‹ˆ๋‹ค.")

pause()

4.3 ์ดˆ์ŒํŒŒ ๊ฑฐ๋ฆฌ ์„ผ์„œ (HC-SR04)

#!/usr/bin/env python3
"""HC-SR04 ์ดˆ์ŒํŒŒ ๊ฑฐ๋ฆฌ ์„ผ์„œ (gpiozero)"""

from gpiozero import DistanceSensor
from time import sleep

# TRIGGER: GPIO23, ECHO: GPIO24
# ์ฃผ์˜: ECHO ํ•€์€ 5V ์ถœ๋ ฅ์ด๋ฏ€๋กœ ๋ถ„์•• ํšŒ๋กœ ํ•„์š”!
sensor = DistanceSensor(echo=24, trigger=23, max_distance=4)

def measure_distance():
    """๊ฑฐ๋ฆฌ ์ธก์ •"""
    distance_m = sensor.distance
    distance_cm = distance_m * 100
    return distance_cm

def proximity_monitor(threshold_cm: float = 30):
    """๊ทผ์ ‘ ๊ฐ์ง€ ๋ชจ๋‹ˆํ„ฐ๋ง"""
    print(f"๊ฑฐ๋ฆฌ ์ž„๊ณ„๊ฐ’: {threshold_cm}cm")

    while True:
        distance = measure_distance()

        if distance < threshold_cm:
            print(f"๊ทผ์ ‘ ๊ฐ์ง€! ๊ฑฐ๋ฆฌ: {distance:.1f}cm")
        else:
            print(f"๊ฑฐ๋ฆฌ: {distance:.1f}cm")

        sleep(0.5)

if __name__ == "__main__":
    try:
        proximity_monitor()
    except KeyboardInterrupt:
        print("\n์ข…๋ฃŒ")

5. ์ข…ํ•ฉ ์˜ˆ์ œ: ์„ผ์„œ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ

#!/usr/bin/env python3
"""์ข…ํ•ฉ ์„ผ์„œ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ"""

from gpiozero import Button, LED, MotionSensor
from datetime import datetime
import time
import json

class IoTSensorSystem:
    """IoT ์„ผ์„œ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ"""

    def __init__(self):
        # GPIO ์„ค์ •
        self.led_status = LED(17)
        self.led_alarm = LED(27)
        self.button = Button(22, bounce_time=0.2)
        self.pir = MotionSensor(23)

        # ์ƒํƒœ
        self.is_armed = False
        self.motion_count = 0
        self.last_motion = None

        # ์ฝœ๋ฐฑ ์„ค์ •
        self.button.when_pressed = self.toggle_arm
        self.pir.when_motion = self.on_motion

    def toggle_arm(self):
        """์‹œ์Šคํ…œ ํ™œ์„ฑํ™”/๋น„ํ™œ์„ฑํ™” ํ† ๊ธ€"""
        self.is_armed = not self.is_armed
        self.led_status.value = self.is_armed

        status = "ํ™œ์„ฑํ™”" if self.is_armed else "๋น„ํ™œ์„ฑํ™”"
        print(f"[์‹œ์Šคํ…œ] {status}")

    def on_motion(self):
        """๋ชจ์…˜ ๊ฐ์ง€ ํ•ธ๋“ค๋Ÿฌ"""
        self.last_motion = datetime.now()
        self.motion_count += 1

        if self.is_armed:
            print(f"[๊ฒฝ๊ณ ] ๋ชจ์…˜ ๊ฐ์ง€! (์ด {self.motion_count}ํšŒ)")
            self.trigger_alarm()
        else:
            print(f"[์ •๋ณด] ๋ชจ์…˜ ๊ฐ์ง€ (์‹œ์Šคํ…œ ๋น„ํ™œ์„ฑ)")

    def trigger_alarm(self):
        """์•Œ๋žŒ ํŠธ๋ฆฌ๊ฑฐ"""
        # LED ๊นœ๋นก์ž„
        self.led_alarm.blink(on_time=0.1, off_time=0.1, n=10)

    def get_status(self) -> dict:
        """ํ˜„์žฌ ์ƒํƒœ ๋ฐ˜ํ™˜"""
        return {
            "is_armed": self.is_armed,
            "motion_count": self.motion_count,
            "last_motion": self.last_motion.isoformat() if self.last_motion else None,
            "timestamp": datetime.now().isoformat()
        }

    def run(self):
        """๋ฉ”์ธ ๋ฃจํ”„"""
        print("=== IoT ์„ผ์„œ ์‹œ์Šคํ…œ ์‹œ์ž‘ ===")
        print("๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์‹œ์Šคํ…œ์„ ํ™œ์„ฑํ™”/๋น„ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค.")

        try:
            while True:
                # ์ฃผ๊ธฐ์ ์œผ๋กœ ์ƒํƒœ ์ถœ๋ ฅ
                status = self.get_status()
                print(f"\r์ƒํƒœ: {json.dumps(status, ensure_ascii=False)}", end="")
                time.sleep(5)

        except KeyboardInterrupt:
            print("\n\n์‹œ์Šคํ…œ ์ข…๋ฃŒ")
            self.cleanup()

    def cleanup(self):
        """์ •๋ฆฌ"""
        self.led_status.off()
        self.led_alarm.off()

if __name__ == "__main__":
    system = IoTSensorSystem()
    system.run()

6. ์‹œ๋ฎฌ๋ ˆ์ด์…˜ (ํ•˜๋“œ์›จ์–ด ์—†์ด)

6.1 Mock ํ•€ ํŒฉํ† ๋ฆฌ

#!/usr/bin/env python3
"""ํ•˜๋“œ์›จ์–ด ์—†์ด GPIO ์‹œ๋ฎฌ๋ ˆ์ด์…˜"""

from gpiozero import Device, LED, Button
from gpiozero.pins.mock import MockFactory

# Mock ํ•€ ํŒฉํ† ๋ฆฌ ์„ค์ •
Device.pin_factory = MockFactory()

led = LED(17)
button = Button(27)

# LED ์ œ์–ด
print(f"LED ์ดˆ๊ธฐ ์ƒํƒœ: {led.is_lit}")
led.on()
print(f"LED on ํ›„: {led.is_lit}")
led.off()
print(f"LED off ํ›„: {led.is_lit}")

# ๋ฒ„ํŠผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
print(f"\n๋ฒ„ํŠผ ์ดˆ๊ธฐ ์ƒํƒœ: {button.is_pressed}")

# ๋ฒ„ํŠผ ํ•€์„ ์ง์ ‘ ์กฐ์ž‘ํ•˜์—ฌ ๋ˆ„๋ฆ„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
button.pin.drive_low()
print(f"๋ฒ„ํŠผ ๋ˆ„๋ฆ„: {button.is_pressed}")

button.pin.drive_high()
print(f"๋ฒ„ํŠผ ๋–ผ๊ธฐ: {button.is_pressed}")

์—ฐ์Šต ๋ฌธ์ œ

๋ฌธ์ œ 1: ํŠธ๋ž˜ํ”ฝ ๋ผ์ดํŠธ

๋นจ๊ฐ•-๋…ธ๋ž‘-์ดˆ๋ก LED 3๊ฐœ๋กœ ์‹ ํ˜ธ๋“ฑ์„ ๊ตฌํ˜„ํ•˜์„ธ์š”: - ๋นจ๊ฐ• 3์ดˆ โ†’ ๋…ธ๋ž‘ 1์ดˆ โ†’ ์ดˆ๋ก 3์ดˆ โ†’ ๋…ธ๋ž‘ 1์ดˆ ๋ฐ˜๋ณต

๋ฌธ์ œ 2: ๋ฒ„ํŠผ ์นด์šดํ„ฐ

๋ฒ„ํŠผ์„ ๋ˆ„๋ฅธ ํšŸ์ˆ˜๋ฅผ ์„ธ๊ณ , 5ํšŒ๋งˆ๋‹ค LED๋ฅผ ๊นœ๋นก์ด์„ธ์š”.

๋ฌธ์ œ 3: ํ™˜๊ฒฝ ์•Œ๋žŒ

DHT11 ์„ผ์„œ๋กœ ์˜จ๋„๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ , 30๋„ ์ด์ƒ์ด๋ฉด ์•Œ๋žŒ LED๋ฅผ ์ผœ์„ธ์š”.


๋‹ค์Œ ๋‹จ๊ณ„

  • 04_WiFi_Networking.md: ์„ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋„คํŠธ์›Œํฌ๋กœ ์ „์†ก
  • 06_MQTT_Protocol.md: MQTT๋กœ ์‹ค์‹œ๊ฐ„ ์„ผ์„œ ๋ฐ์ดํ„ฐ ๋ฐœํ–‰

์ตœ์ข… ์—…๋ฐ์ดํŠธ: 2026-02-01

to navigate between lessons