라즈베리파이 GPIO 입문에서 실전까지

하드웨어 환경: 라즈베리 파이 4 모델 B 리비전 1.5 · Debian 12 북웜 · 커널 6.12.25
테스트 날짜: 2026년 4월
작성자: zeruns (https://blog.zeruns.com/)
본문은 AI가 작성하였으며 참고용임 (Hermes Agent + DeepSeek V4 Flash)


목차

  1. GPIO 기초 개념
  2. 환경 준비 및 도구
  3. GPIO 입력/출력 (Shell 방식)
  4. GPIO 입력/출력 (Python 방식)
  5. I2C 통신
  6. SPI 통신
  7. 종합 사례
  8. 주의사항 및 오류 해결

1. GPIO 기초 개념

1.1 GPIO란 무엇인가

GPIO(General Purpose Input/Output, 범용 입력/출력)는 마이크로프로세서의 프로그래밍 가능한 핀 그룹입니다. 소프트웨어 제어를 통해 각 핀을 다음 모드 중 하나로 설정할 수 있습니다:

  • 출력 모드: 높은 전압(3.3V) 또는 낮은 전압(0V)을 출력하여 LED, 릴레이, 부저 등을 제어합니다.
  • 입력 모드: 외부 전압 상태(고/저)를 읽어 버튼, 센서 신호 등을 검출합니다.
  • 다중 기능(Multiplexing): I2C, SPI, UART, PWM 등의 전용 통신 프로토콜로 사용합니다.

1.2 라즈베리 파이 4B 핀 배열

라즈베리 파이 4B는 40핀 확장 핀 헤더를 사용하며, 핀 번호 지정 방식은 3가지가 있습니다:

번호 방식 설명 일반적인 라이브러리
물리 핀(Board) 1에서 40까지 번호 매기며 왼쪽 상단이 1번 RPi.GPIO setmode(GPIO.BOARD)
BCM 번호(Broadcom) 칩의 GPIO 번호를 사용, 예: GPIO17 RPi.GPIO setmode(GPIO.BCM), libgpiod
wiringPi 번호 wiringPi 라이브러리의 사용자 정의 번호 (현재 사용 중단됨) wiringPi 라이브러리

40핀 핀 기능표

                    ┌─────────────────────────────┐
                    │  🥝 라즈베리 파이 4B 40핀 핀 순서도   │
  3.3V  (01) ──●  ●── (02)  5V                    │
 GPIO2  (03) ──●  ●── (04)  5V                    │
 GPIO3  (05) ──●  ●── (06)  GND                   │
 GPIO4  (07) ──●  ●── (08)  GPIO14 (UART TX)      │
   GND  (09) ──●  ●── (10)  GPIO15 (UART RX)      │
GPIO17  (11) ──●  ●── (12)  GPIO18 (PWM0)         │
GPIO27  (13) ──●  ●── (14)  GND                   │
GPIO22  (15) ──●  ●── (16)  GPIO23                │
  3.3V  (17) ──●  ●── (18)  GPIO24                │
GPIO10 (19) ──●  ●── (20)  GND  (SPI_MOSI)        │
 GPIO9 (21) ──●  ●── (22)  GPIO25 (SPI_MISO)      │
GPIO11 (23) ──●  ●── (24)  GPIO8  (SPI_SCLK)      │
   GND (25) ──●  ●── (26)  GPIO7  (SPI_CE0)       │
 GPIO0 (27) ──●  ●── (28)  GPIO1  (ID_SDA / I2C)  │
 GPIO5 (29) ──●  ●── (30)  GND                    │
 GPIO6 (31) ──●  ●── (32)  GPIO12 (PWM0)          │
GPIO13 (33) ──●  ●── (34)  GND                    │
GPIO19 (35) ──●  ●── (36)  GPIO16                 │
GPIO26 (37) ──●  ●── (38)  GPIO20                 │
   GND (39) ──●  ●── (40)  GPIO21                 │
                    └─────────────────────────────┘

라즈베리 파이 4B 주요 핀 기능표

물리 핀 BCM 번호 기능 물리 핀 BCM 번호 기능
1 3.3V 2 5V
3 GPIO2 I2C1 SDA 4 5V
5 GPIO3 I2C1 SCL 6 GND
7 GPIO4 8 GPIO14 UART TX
9 GND 10 GPIO15 UART RX
11 GPIO17 12 GPIO18 PCM_CLK / PWM0
13 GPIO27 14 GND
15 GPIO22 16 GPIO23
17 3.3V 18 GPIO24
19 GPIO10 SPI0 MOSI 20 GND
21 GPIO9 SPI0 MISO 22 GPIO25
23 GPIO11 SPI0 SCLK 24 GPIO8 SPI0 CE0
25 GND 26 GPIO7 SPI0 CE1
27 GPIO0 ID_SDA (EEPROM) 28 GPIO1 ID_SCL (EEPROM)
29 GPIO5 30 GND
31 GPIO6 32 GPIO12 PWM0
33 GPIO13 PWM1 34 GND
35 GPIO19 PCM_FS / PWM1 36 GPIO16
37 GPIO26 38 GPIO20 PCM_DIN
39 GND 40 GPIO21 PCM_DOUT

1.3 주요 참고 사항

  • 논리 레벨: 라즈베리 파이 GPIO는 3.3V 논리 레벨이며 5V 신호를 직접 연결하면 안 됩니다.
  • 전류 제한: 각 GPIO 최대 출력 전류는 약 16mA, 전체 핀 합계는 50mA를 초과하지 않아야 합니다.
  • 기본 상태: 대부분의 GPIO 핀은 기본적으로 입력 모드이며 일부는 내부 풀업/풀다운 저항을 가지고 있습니다.
  • 3.3V 핀 (01/17): 최대 약 500mA 출력 가능
  • 5V 핀 (02/04): USB-C 전원에서 직접 공급되며 공급 전류는 전원 어댑터 사양에 따라 다릅니다.

2. 환경 준비 및 도구

2.1 설치된 도구 목록

이 튜토리얼은 Debian 12 북웜 기반 시스템에서 테스트 되었으며 다음 도구가 사전 설치되어 있습니다:

도구/라이브러리 버전 용도
libgpiod / gpioset / gpioget 1.6.3 쉘 명령어 방식 GPIO 제어
python3-libgpiod 1.6.3 Python libgpiod 바인딩
RPi.GPIO 0.7.2 고전적인 Python GPIO 라이브러리
smbus2 설치됨 Python I2C 통신
spidev 설치됨 Python SPI 통신
pigpiod 1.79 GPIO 데몬 (PWM/원격 제어)
i2c-tools 4.3 I2C 장치 스캔 도구

2.2 필요한 도구 설치

도구가 설치되지 않은 경우 아래 명령어로 설치할 수 있습니다.

# 기본 GPIO 도구 설치
sudo apt install gpiod libgpiod-dev python3-libgpiod

# I2C 도구 설치
sudo apt install i2c-tools

# Python 라이브러리 설치
pip install RPi.GPIO smbus2 spidev gpiozero

# pigpio 데몬 설치 (하드웨어 PWM, 권장)
sudo apt install pigpio pigpiod
sudo systemctl enable pigpiod --now

2.3 I2C / SPI 인터페이스 활성화

raspi-config를 사용하여 활성화:

sudo raspi-config

메뉴 경로:
Interface OptionsI2CEnableYes
Interface OptionsSPIEnableYes

또는 터미널에서 직접 /boot/firmware/config.txt(Debian 12) 파일을 편집합니다:

# 수동으로 추가
sudo tee -a /boot/firmware/config.txt <<EOF
dtparam=i2c_arm=on
dtparam=spi=on
EOF

# 다시 시작하여 적용
sudo reboot

활성화 성공 확인:

# I2C 확인
ls /dev/i2c*
# 출력: /dev/i2c-20  /dev/i2c-21

# SPI 확인 (활성화 후)
ls /dev/spi*
# 출력: /dev/spidev0.0  /dev/spidev0.1

2.4 모든 gpiochip 보기

$ gpioinfo
gpiochip0 - 58 lines:
        line   0:     "ID_SDA"       unused   input  active-high
        line   1:     "ID_SCL"       unused   input  active-high
        line   2:      "GPIO2"       unused   input  active-high
        ...

라즈베리 파이 4B의 BCM2711 칩은 하나의 gpiochip0을 제공하며 총 58개의 GPIO를 가지지만, GPIO0~GPIO27까지만 40핀 헤더를 통해 외부로 빠져나옵니다.


3. GPIO 입력/출력 (Shell 방식)

3.1 libgpiod 도구 모음

wiringPi에 의존하지 않는 libgpiod 도구 사용을 권장합니다. 현재 주류로 쓰이는 방법입니다.

주요 명령어:

명령 기능 예시
gpioinfo 모든 GPIO 상태 보기 gpioinfo
gpioset GPIO 출력 레벨 설정 gpioset 0 17=1
gpioget GPIO 입력 레벨 읽기 gpioget 0 17
gpiomon GPIO 이벤트 감시 gpiomon 0 17

형식 설명: gpioset <chip> <pin>=<va>chip`는 일반적으로 0(gpiochip0)이며, 핀 번호는 BCM 번호를 사용합니다.

3.2 출력: LED 켜기

LED의 양극(긴 핀)을 330Ω 저항을 통해 GPIO17(물리 핀 11)에 연결하고, 음극(짧은 핀)은 GND(물리 핀 9)에 연결하세요.

# GPIO17에 고전압 출력 설정 → LED 켜짐
gpioset 0 17=1

# GPIO17에 저전압 출력 설정 → LED 꺼짐
gpioset 0 17=0

3.3 입력: 버튼 상태 읽기

버튼 한쪽을 GPIO18(물리 핀 12)에 연결하고, 다른 쪽을 GND(물리 핀 14)에 연결하세요.

# GPIO18의 전압 레벨 읽기 (외부 풀업 혹은 내부 풀업 필요)
gpioget 0 18
# 출력: 1 (버튼 미누름, 고전압)
# 출력: 0 (버튼 누름, 저전압)

3.4 모든 핀 상태 보기

# 전체 핀 상태 보기
gpioinfo

# 특정 핀 보기 (BCM 17번)
gpioinfo | grep "GPIO17"
# 출력: line  17:      "GPIO17"       "myapp"   output  active-high

3.5 gpioset으로 풀업/풀다운 설정

libgpiod 1.6 버전부터는 요청 시 바이어스를 설정할 수 있습니다.

# GPIO17을 출력으로 설정하고 초기 전압을 고로 설정하며 풀업 적용
gpioset --bias=enable 0 17=1

4. GPIO 입출력 (파이썬 방식)

4.1 RPi.GPIO 사용 (전통적인 라이브러리)

RPi.GPIO는 가장 일반적으로 사용하는 파이썬 GPIO 라이브러리로, 간단하고 직관적입니다.

4.1.1 출력: LED 깜박이기

import RPi.GPIO as GPIO
import time

# BCM 핀 번호 방식 사용
GPIO.setmode(GPIO.BCM)

# GPIO17을 출력으로 설정
GPIO.setup(17, GPIO.OUT)

# LED를 5번 깜박임
for _ in range(5):
    GPIO.output(17, GPIO.HIGH)  # LED 켬
    time.sleep(0.5)
    GPIO.output(17, GPIO.LOW)   # LED 끔
    time.sleep(0.5)

# 자원 정리
GPIO.cleanup()

4.1.2 입력: 버튼 읽기

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

# GPIO18을 입력으로 설정하고 내부 풀업 저항 활성화
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)

try:
    while True:
        if GPIO.input(18) == GPIO.LOW:
            print("버튼 누름")
        else:
            print("버튼 뗌")
        time.sleep(0.1)
except KeyboardInterrupt:
    GPIO.cleanup()

GPIO.PUD_UP = 내부 풀업 (기본 고전압, 눌렀을 때 저전압)
GPIO.PUD_DOWN = 내부 풀다운 (기본 저전압, 눌렀을 때 고전압)

4.1.3 PWM 출력: 호흡등 효과

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)  # GPIO18은 하드웨어 PWM 지원

pwm = GPIO.PWM(18, 1000)  # 주파수 1kHz
pwm.start(0)  # 초기 듀티 사이클 0%

try:
    while True:
        # 서서히 밝아짐
        for duty in range(0, 101, 5):
            pwm.ChangeDutyCycle(duty)
            time.sleep(0.05)
        # 서서히 어두워짐
        for duty in range(100, -1, -5):
            pwm.ChangeDutyCycle(duty)
            time.sleep(0.05)
except KeyboardInterrupt:
    pwm.stop()
    GPIO.cleanup()

4.1.4 이벤트 감지: 인터럽트 방식으로 버튼 읽기

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)

def button_callback(channel):
    print(f"버튼 누름! (핀: {channel})")

# 하강 에지에서 트리거 (눌렀을 때)
GPIO.add_event_detect(18, GPIO.FALLING,
                      callback=button_callback,
                      bouncetime=200)

try:
    print("버튼 입력 대기...")
    time.sleep(60)
except KeyboardInterrupt:
    GPIO.cleanup()

4.2 gpiozero 사용 (고수준 래핑)

gpiozero는 더 고수준의 객체 지향 인터페이스를 제공하며, 빠른 개발에 적합합니다:

# 설치
pip install gpiozero
from gpiozero import LED, Button, Buzzer
from signal import pause

# LED: 자동 깜빡임
led = LED(17)
led.blink()

# 버튼: 누르면 LED 켜짐
btn = Button(18, pull_up=True)

# 방법 1: 직접 대입
btn.when_pressed = led.on
btn.when_released = led.off

# 방법 2: 사용자 정의 콜백
btn.when_pressed = lambda: print("누름!")

# 계속 실행
pause()

gpiozero에서 제공하는 주요 컴포넌트:

컴포넌트 클래스명 설명
LED LED(pin) LED 켜기/끄기, 깜빡임, 호흡등 제어
버튼 Button(pin, pull_up=True) 버튼 입력, 길게 누름 감지
부저 Buzzer(pin) 능동형 부저 제어
거리 센서 DistanceSensor(echo, trigger) HC-SR04 초음파 거리 측정
서보모터 Servo(pin) 서보모터 각도 제어
모터 Motor(forward, backward) DC 모터 제어

4.3 libgpiod 파이썬 바인딩 사용 (저수준 조작)

import gpiod
import time

# gpiochip0 열기
chip = gpiod.Chip('gpiochip0')

# GPIO17을 가져와 출력으로 요청
line = chip.get_line(17)
line.request(consumer='myapp', type=gpiod.LINE_REQ_DIR_OUT)

# 고전압 출력
line.set_value(1)
time.sleep(1)

# 저전압 출력
line.set_value(0)

# 해제
line.release()

입력 모드 예시:

import gpiod

chip = gpiod.Chip('gpiochip0')
line = chip.get_line(18)

# 입력으로 요청, 내부 풀업 사용
line.request(consumer='myapp',
             type=gpiod.LINE_REQ_DIR_IN,
             flags=gpiod.LINE_REQ_FLAG_BIAS_PULL_UP)

value = line.get_value()  # 0 또는 1
print(f"GPIO18 = {value}")

line.release()

5. I2C 통신

5.1 I2C 기본 원리

I2C(Inter-Integrated Circuit)는 두 개의 선을 사용하는 직렬 통신 버스입니다:

신호 기능
SCL GPIO3 (물리 핀 5) 클럭라인
SDA GPIO2 (물리 핀 3) 데이터라인

특징:

  • 마스터-슬레이브 아키텍처: 라즈베리파이는 마스터, 센서 등이 슬레이브
  • 7비트 주소: 각 슬레이브는 고유한 주소를 가짐 (예: 0x44)
  • 다중 장치 공유: 하나의 I2C 버스에 여러 장치 연결 가능
  • 속도: 표준 100kHz, 빠른 모드 400kHz

5.2 I2C 버스 확인

# I2C 버스 목록 보기
$ i2cdetect -l
i2c-20  i2c        bcm2711_i2c1                   I2C adapter
i2c-21  i2c        bcm2711_i2c0                   I2C adapter
  • i2c-20: 물리 핀 3(SDA)/5(SCL)에 해당 — 주 I2C 버스
  • i2c-21: ID_EEPROM(핀 27/28)에 연결, 일반적으로 외부 장치 연결 없음

5.3 I2C 장치 스캔

# i2c-20 버스에 연결된 장치 스캔
$ i2cdetect -y 20
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- 44 -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

주소 0x44에 장치 발견 — 이는 SHT30 온습도 센서(I2C 주소 0x44)입니다.

만약 아무 장치도 보이지 않고 전부 --이라면, 버스에 장치가 연결되지 않았음을 의미합니다.

5.4 smbus2를 사용한 I2C 읽기/쓰기

smbus2는 가장 일반적인 파이썬 I2C 라이브러리입니다.

5.4.1 SHT30 온습도 센서 읽기

import smbus2
import time

# SHT30 I2C 주소
SHT30_ADDR = 0x44

# I2C 버스 20 열기
bus = smbus2.SMBus(20)

# 측정 명령 전송: 고정밀도 모드
bus.write_i2c_block_data(SHT30_ADDR, 0x2C, [0x06])

time.sleep(0.015)  # 측정 완료 대기 (15ms)

# 6바이트 데이터 읽기
data = bus.read_i2c_block_data(SHT30_ADDR, 0x00, 6)

# 온도 및 습도 계산
temp_raw = ((data[0] << 8) | data[1])
temp = -45 + 175 * temp_raw / 65535.0

hum_raw = ((data[3] << 8) | data[4])
hum = 100 * hum_raw / 65535.0

print(f"온도: {temp:.2f}°C")
print(f"습도: {hum:.2f}%")

5.4.2 함수로 패키징하기

import smbus2
import time

class SHT30:
    def __init__(self, bus_id=20, addr=0x44):
        self.bus = smbus2.SMBus(bus_id)
        self.addr = addr

    def read(self):
        """온습도 측정, 형식: (온도°C, 습도%)"""
        self.bus.write_i2c_block_data(self.addr, 0x2C, [0x06])
        time.sleep(0.015)
        data = self.bus.read_i2c_block_data(self.addr, 0x00, 6)

        temp_raw = (data[0] << 8) | data[1]
        temp = -45 + 175 * temp_raw / 65535.0

        hum_raw = (data[3] << 8) | data[4]
        hum = 100 * hum_raw / 65535.0

        return round(temp, 2), round(hum, 2)

# 사용 예
sensor = SHT30()
t, h = sensor.read()
print(f"{t}°C, {h}%RH")

5.4.3 일반적인 I2C 입출력 작업

import smbus2

bus = smbus2.SMBus(20)
addr = 0x44  # 디바이스 I2C 주소

# 레지스터에 한 바이트 쓰기
bus.write_byte_data(addr, 0x2C, 0x06)

# 한 바이트 읽기
value = bus.read_byte_data(addr, 0x00)

# 여러 바이트 읽기
data = bus.read_i2c_block_data(addr, 0x00, 6)

# 여러 바이트 쓰기
bus.write_i2c_block_data(addr, 0x2C, [0x06])

# 레지스터 없이 한 바이트 쓰기
bus.write_byte(addr, 0x06)

# 레지스터 없이 한 바이트 읽기
value = bus.read_byte(addr)

bus.close()

5.5 명령줄 도구 i2cget / i2cset 사용

# SHT30 상태 레지스터 읽기 (1바이트)
$ i2cget -y 20 0x44 0x00
0x65

# 6바이트 원시 데이터 읽기
$ i2cget -y 20 0x44 0x00 b 6

6. SPI 통신

6.1 SPI 기본 원리

SPI Serial Peripheral Interface는 전이중 동기 직렬 버스로 4개의 선을 사용:

신호 라즈베리파이 핀 기능
MOSI GPIO10 (물리 핀 19) 마스터 출력, 슬레이브 입력
MISO GPIO9 (물리 핀 21) 마스터 입력, 슬레이브 출력
SCLK GPIO11 (물리 핀 23) 클럭 신호
CE0 GPIO8 (물리 핀 24) 칩 선택 0
CE1 GPIO7 (물리 핀 26) 칩 선택 1

특징:

  • 전이중: 송신과 수신을 동시에 가능
  • 마스터-슬레이브: 라즈베리파이는 마스터, 여러 슬레이브 장

6.3.2 일반 SPI 데이터 송수신

import spidev

spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 500000
spi.mode = 0

# 전송 및 수신(전이중, 0xFF 전송하면서 동시에 수신)
data_out = [0xFF, 0x00, 0x55]
data_in = spi.xfer2(data_out)  # 3바이트 전송, 3바이트 수신
print(f"전송: {[hex(x) for x in data_out]}")
print(f"수신: {[hex(x) for x in data_in]}")

# 전송만(수신 결과 무시)
spi.writebytes([0x01, 0x02, 0x03])

spi.close()

7. 종합 예제

7.1 예제 1: LED 브리딩 + 버튼 제어

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

LED_PIN = 17      # BCM 17
BTN_PIN = 18      # BCM 18

GPIO.setup(LED_PIN, GPIO.OUT)
GPIO.setup(BTN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

pwm = GPIO.PWM(LED_PIN, 500)
pwm.start(0)

running = True  # LED 상태

try:
    while True:
        if GPIO.input(BTN_PIN) == GPIO.LOW:
            running = not running
            time.sleep(0.3)  # 디바운싱

        if running:
            # 브리딩 효과
            for duty in range(0, 101, 2):
                pwm.ChangeDutyCycle(duty)
                time.sleep(0.01)
            for duty in range(100, -1, -2):
                pwm.ChangeDutyCycle(duty)
                time.sleep(0.01)
        else:
            pwm.ChangeDutyCycle(0)

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

7.2 예제 2: SHT30 온습도 측정 + 자동 기록

import smbus2
import time
import csv
from datetime import datetime

class SHT30:
    def __init__(self, bus_id=20, addr=0x44):
        self.bus = smbus2.SMBus(bus_id)
        self.addr = addr

    def read(self):
        self.bus.write_i2c_block_data(self.addr, 0x2C, [0x06])
        time.sleep(0.015)
        data = self.bus.read_i2c_block_data(self.addr, 0x00, 6)
        t = -45 + 175 * ((data[0] << 8) | data[1]) / 65535.0
        h = 100 * ((data[3] << 8) | data[4]) / 65535.0
        return round(t, 2), round(h, 2)

sensor = SHT30()

# 측정 테스트
t, h = sensor.read()
print(f"[{datetime.now()}] 온도: {t}°C, 습도: {h}%")

# CSV에 지속 기록(매분 1회)
with open('sensor_log.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(['시간', '온도(C)', '습도(%)'])
    for i in range(10):  # 10회 기록
        t, h = sensor.read()
        now = datetime.now().strftime('%H:%M:%S')
        writer.writerow([now, t, h])
        print(f"[{now}] {t}°C, {h}%")
        time.sleep(60)

7.3 예제 3: gpiozero로 한 번에 완성

from gpiozero import LED, Button
from signal import pause
import time

led = LED(17)
btn = Button(18, pull_up=True)

# 눌렀을 때 켜지고, 뗐을 때 꺼짐
btn.when_pressed = led.on
btn.when_released = led.off

# 더블 클릭 시 깜빡임 모드 전환
press_count = 0

def double_click():
    global press_count
    press_count += 1
    time.sleep(0.3)
    if press_count == 2:
        led.blink()
        print("더블 클릭! LED 깜빡임 모드")
        press_count = 0

btn.when_pressed = double_click

pause()

8. 주의사항과 오류 해결

8.1 전압 레벨 변환 (3.3V vs 5V)

:warning: 라즈베리파이 GPIO는 3.3V 로직이며, 절대 5V 장치에 직접 연결하지 마세요!

상황 방법
5V 센서 출력 → 라즈베리파이 입력 레벨 쉬프터 모듈(예: TXS0108E) 또는 저항 분압 방식 사용
라즈베리파이 출력 → 5V 장치 입력 일부 5V 장치는 3.3V를 고레벨로 인식함(예: WS2812B)
3.3V 센서 → 라즈베리파이 바로 연결 가능 :white_check_mark:

저항 분압 (5V → 3.3V):

    5V ──┬── R1 (1.8kΩ) ──┬── 라즈베리파이 GPIO
         │                │
        GND ── R2 (3.3kΩ) ─┘

8.2 풀업/풀다운 저항

  • 내부 풀업: RPi.GPIO에서는 pull_up_down=GPIO.PUD_UP
  • 내부 풀다운: RPi.GPIO에서는 pull_up_down=GPIO.PUD_DOWN
  • libgpiod: gpiod.LINE_REQ_FLAG_BIAS_PULL_UP
  • 외부 풀업: 4.7kΩ ~ 10kΩ 저항을 3.3V에 연결

8.3 전류 제한

항목 제한
개별 GPIO 최대 출력 전류 16mA
전체 GPIO 합산 50mA
3.3V 핀 총 전류 약 500mA
5V 핀 총 전류 전원 공급에 따라 다름

:light_bulb: LED 직접 구동 시 반드시 220Ω ~ 330Ω 제한 저항을 직렬로 연결하세요!

8.4 흔한 오류

오류 원인 해결 방법
RuntimeError: No access to /dev/mem 권한 부족 sudo python3 script.py 실행
RuntimeError: Pin already in use 핀이 다른 프로그램에 의해 사용 중 /sys/class/gpio/ 확인 후 해제 또는 재시작
[Errno 13] Permission denied + i2c I2C 미활성 또는 권한 부족 사용자를 i2c 그룹에 추가
Could not open /dev/spidev0.0 SPI 미활성 /boot/config.txt 확인
LED 역접속으로 켜지지 않음 양극/음극 거꾸로 연결 LED 긴 다리는 GPIO, 짧은 다리는 GND에 연결
버튼 오작동 디바운싱 미처리 코드에 bouncetime 또는 디바운스 지연 추가

8.5 권한 설정

# 현재 사용자를 i2c, gpio 그룹에 추가
sudo usermod -aG i2c,gpio $USER

# 다시 로그인하여 적용
exec su - $USER

8.6 빠른 온라인 참고 자료


작성자: zeruns
이 튜토리얼은 라즈베리파이 4B + Debian 12 Bookworm에서 직접 테스트하여 작성됨