프로젝트

일반

사용자정보

Actions

새기능 #6

진행중

[튜토리얼] ws2812 6개 led 제어

minkyu park이(가) 4달 전에 추가함.

상태:
신규
우선순위:
보통
담당자:
시작일:
2025/08/27
완료일:
2025/08/27 (약 4달 지연)
진척도:

100%

추정시간:

설명

라즈베리 파이에서 WS2812B (또는 NeoPixel) 주소 지정 가능 LED 6개를 제어하는 방법을 설명해 드릴게요. WS2812B LED는 각 LED의 색상과 밝기를 개별적으로 제어할 수 있어 매우 인기가 많습니다.

중요 고려사항:

전원 공급 (Power Supply): WS2812B LED는 픽셀당 최대 60mA (백색 최대 밝기 시)를 소비할 수 있습니다. 6개의 LED는 최대 360mA를 소비합니다. 라즈베리 파이의 5V 핀은 제한된 전류만 제공할 수 있으므로, LED 스트립이 길거나 밝게 사용하려면 별도의 5V 전원 공급 장치를 사용하는 것이 강력히 권장됩니다.

5V 2A~5A 이상의 전원 어댑터를 준비하는 것이 안전합니다.

외부 전원 공급 장치의 GND와 라즈베리 파이의 GND를 반드시 연결(공통 접지)해야 합니다.

논리 레벨 변환 (Logic Level Shifting): 라즈베리 파이의 GPIO 핀은 3.3V 논리 레벨을 출력하지만, WS2812B LED는 일반적으로 5V 논리 레벨의 데이터 신호를 기대합니다. 소수의 LED (약 5~10개 정도)에서는 직접 연결해도 작동하는 경우가 있지만, 안전하고 안정적인 작동을 위해서는 3.3V를 5V로 변환해주는 논리 레벨 변환기(Logic Level Shifter, 예: 74AHCT125 또는 양방향 레벨 변환 모듈)를 사용하는 것이 좋습니다.

간단한 대안으로, 첫 번째 WS2812 LED의 5V 전원 라인에 300~500옴 정도의 저항을 직렬로 연결하여 데이터 신호에 필요한 전압 강하를 유도하는 방법도 있지만, 이는 완벽한 해결책은 아닙니다.

데이터 핀 (Data Pin): WS2812B는 타이밍에 매우 민감합니다. 라즈베리 파이의 특정 GPIO 핀(예: GPIO 18 (PWM) 또는 GPIO 10 (SPI))을 사용하는 것이 권장됩니다. 이 핀들은 WS2812B 통신에 필요한 정확한 타이밍을 제공할 수 있기 때문입니다. 여기서는 일반적으로 널리 사용되는 GPIO 18을 기준으로 설명합니다.

🚨 준비물
라즈베리 파이 (모든 모델)

WS2812B LED 6개 (또는 WS2812B가 포함된 스트립 또는 링)

5V 전원 공급 장치 (LED 개수에 따라 충분한 전류 공급 가능한 것, 예: 5V 2A 이상 어댑터)

논리 레벨 변환기 (예: 74AHCT125 또는 TXS0108E 모듈) - 권장 사항

브레드보드 (선택 사항)

점퍼 와이어

🔌 배선 (연결)
옵션 1: 논리 레벨 변환기 사용 (권장)

이 방법이 가장 안정적이고 안전합니다.

외부 5V 전원 공급 장치 연결:

외부 5V 전원 공급 장치의 + (Positive) ↔ WS2812B LED 스트립의 5V (VCC)

외부 5V 전원 공급 장치의 - (Negative/GND) ↔ WS2812B LED 스트립의 GND

공통 접지 (Common Ground):

외부 5V 전원 공급 장치의 GND ↔ 라즈베리 파이의 GND 핀 (필수!)

논리 레벨 변환기 연결:

논리 레벨 변환기 LV (Low Voltage, 3.3V) ↔ 라즈베리 파이 3.3V 핀

논리 레벨 변환기 HV (High Voltage, 5V) ↔ 외부 5V 전원 공급 장치의 5V

논리 레벨 변환기 LV GND ↔ 라즈베리 파이 GND 핀

논리 레벨 변환기 HV GND ↔ 외부 5V 전원 공급 장치 GND

논리 레벨 변환기 LV 입력 핀 (예: A1) ↔ 라즈베리 파이 GPIO 18 (물리적 핀 12)

논리 레벨 변환기 HV 출력 핀 (예: B1, LV 입력 A1에 대응) ↔ WS2812B LED 스트립의 데이터 입력 (DIN/DI)

옵션 2: 레벨 변환기 없이 직접 연결 (작은 개수 LED, 위험 부담 있음)

이 방법은 라즈베리 파이 GPIO에 손상을 줄 가능성이 있으므로 주의하세요.

외부 5V 전원 공급 장치 연결:

외부 5V 전원 공급 장치의 + (Positive) ↔ WS2812B LED 스트립의 5V (VCC)

외부 5V 전원 공급 장치의 - (Negative/GND) ↔ WS2812B LED 스트립의 GND

공통 접지 (Common Ground):

외부 5V 전원 공급 장치의 GND ↔ 라즈베리 파이의 GND 핀 (필수!)

데이터 연결:

라즈베리 파이 GPIO 18 (물리적 핀 12) ↔ WS2812B LED 스트립의 데이터 입력 (DIN/DI)

선택적 (약간의 보호): GPIO 18과 WS2812B 데이터 핀 사이에 300~500옴 저항을 직렬로 연결.

⚙️ 소프트웨어 설정: rpi_ws281x (또는 Adafruit NeoPixel) 라이브러리 설치
WS2812B LED를 제어하기 위한 가장 널리 사용되는 라이브러리는 rpi_ws281x (C 라이브러리의 Python 래퍼) 또는 이를 기반으로 하는 Adafruit CircuitPython NeoPixel 라이브러리입니다. rpi_ws281x를 직접 설치하는 방법을 추천합니다.

터미널 열기: 라즈베리 파이에서 터미널을 엽니다.

필요한 패키지 설치:

sudo apt update
sudo apt install -y scons git build-essential python3-dev

rpi_ws281x 라이브러리 클론 및 빌드:

git clone https://github.com/jgarff/rpi_ws281x.git
cd rpi_ws281x
sudo scons
cd python
sudo python3 setup.py install

이 과정은 라이브러리를 컴파일하고 파이썬에 설치합니다.

🐍 Python 샘플 코드 (6개 LED 제어)
이제 6개의 WS2812B LED를 제어하는 Python 코드를 작성합니다.


import time
import rpi_ws281x # rpi_ws281x 라이브러리 임포트

# --- LED 스트립 설정 ---
LED_COUNT      = 6      # 제어할 WS2812B LED의 총 개수 (여기서는 6개)
LED_PIN        = 18     # WS2812B 데이터 핀이 연결된 GPIO 핀 (GPIO 18 = 물리적 핀 12)
LED_FREQ_HZ    = 800000 # LED 신호 주파수 (WS2812B는 800kHz)
LED_DMA        = 10     # DMA 채널 번호 (일반적으로 10 사용)
LED_BRIGHTNESS = 255    # 밝기 (0 = 가장 어둡게, 255 = 가장 밝게)
LED_INVERT     = False  # True로 설정 시 신호 반전 (NPN 트랜지스터 레벨 시프터 사용 시)
LED_CHANNEL    = 0      # 채널 0 사용 (대부분의 경우 0 사용)

# --- 색상 정의 (RGB) ---
# rpi_ws281x는 GRB (Green, Red, Blue) 순서를 사용합니다.
# Color(R, G, B) 함수를 사용하여 실제 LED에 맞는 색상 순서를 지정합니다.
# 만약 LED가 RGB 순서를 사용한다면, Color(G, R, B) 대신 Color(R, G, B)를 시도해 보세요.
def Color(red, green, blue, white = 0):
    return (white << 24) | (green << 16) | (red << 8) | blue

# --- LED 애니메이션 함수 ---
def colorWipe(strip, color, wait_ms=50):
    """모든 픽셀을 한 번에 한 가지 색상으로 채웁니다."""
    for i in range(strip.numPixels()):
        strip.setPixelColor(i, color)
        strip.show()
        time.sleep(wait_ms/1000.0)

def theaterChase(strip, color, wait_ms=50, iterations=10):
    """연극 추격 라이트 효과를 수행합니다."""
    for j in range(iterations):
        for q in range(3):
            for i in range(0, strip.numPixels(), 3):
                strip.setPixelColor(i+q, color)
            strip.show()
            time.sleep(wait_ms/1000.0)
            for i in range(0, strip.numPixels(), 3):
                strip.setPixelColor(i+q, 0) # 모든 LED 끄기

def wheel(pos):
    """레인보우 색상 휠 생성"""
    if pos < 85:
        return Color(pos * 3, 255 - pos * 3, 0)
    elif pos < 170:
        pos -= 85
        return Color(255 - pos * 3, 0, pos * 3)
    else:
        pos -= 170
        return Color(0, pos * 3, 255 - pos * 3)

def rainbow(strip, wait_ms=20, iterations=1):
    """모든 픽셀에 걸쳐 레인보우 색상 주기"""
    for j in range(256*iterations):
        for i in range(strip.numPixels()):
            strip.setPixelColor(i, wheel((i+j) & 255))
        strip.show()
        time.sleep(wait_ms/1000.0)

def clear_all_pixels(strip):
    """모든 픽셀 끄기"""
    for i in range(strip.numPixels()):
        strip.setPixelColor(i, Color(0,0,0)) # 검정색 (꺼짐)
    strip.show()

# --- 메인 실행 부분 ---
if __name__ == '__main__':
    # LED 스트립 객체 생성
    strip = rpi_ws281x.Ws2811(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL)

    # 스트립 초기화
    strip.begin()

    print(f"WS2812B LED 제어 시작 (LED 개수: {LED_COUNT}). Ctrl+C로 종료.")

    try:
        while True:
            print("빨간색으로 채우기")
            colorWipe(strip, Color(255, 0, 0))  # 빨간색
            time.sleep(1)

            print("녹색으로 채우기")
            colorWipe(strip, Color(0, 255, 0))  # 녹색
            time.sleep(1)

            print("파란색으로 채우기")
            colorWipe(strip, Color(0, 0, 255))  # 파란색
            time.sleep(1)

            print("시어터 체이스 (빨강)")
            theaterChase(strip, Color(255, 0, 0))
            time.sleep(1)

            print("레인보우")
            rainbow(strip)
            time.sleep(1)

            print("모든 LED 끄기")
            clear_all_pixels(strip)
            time.sleep(2)

    except KeyboardInterrupt:
        # Ctrl+C가 눌리면 모든 LED 끄고 종료
        print("\n프로그램 종료. 모든 LED를 끕니다.")
        clear_all_pixels(strip)

💡 코드 설명
LED_COUNT = 6: 제어할 LED의 총 개수를 6으로 설정합니다. 만약 더 많거나 적은 LED를 사용한다면 이 값을 변경해야 합니다.

LED_PIN = 18: LED 데이터 핀이 연결된 GPIO 핀 번호입니다. Raspberry Pi 2, 3, 4에서는 GPIO 18 (물리적 핀 12)이 권장됩니다.

LED_FREQ_HZ = 800000: WS2812B LED의 데이터 전송 주파수입니다. (800kHz)

LED_DMA = 10: DMA (Direct Memory Access) 채널을 사용하여 CPU의 개입 없이 효율적으로 데이터를 전송합니다.

LED_BRIGHTNESS = 255: LED의 전체 밝기를 0 (가장 어둡게)부터 255 (가장 밝게)까지 조절합니다.

Color(red, green, blue, white=0) 함수: 이 함수는 rpi_ws281x 라이브러리가 요구하는 픽셀 색상 값을 생성합니다. WS2812B는 RGB 순서가 아닌 GRB 순서로 데이터를 받으므로, (green << 16) | (red << 8) | blue와 같이 비트 시프트를 통해 순서를 맞춥니다. 만약 SK6812RGBW와 같은 RGBW LED를 사용한다면 white 매개변수도 함께 사용합니다.

colorWipe, theaterChase, rainbow 함수:

colorWipe: 모든 LED를 지정된 색상으로 차례대로 켜는 함수입니다.

theaterChase: 극장 간판처럼 LED가 순서대로 켜졌다 꺼지는 효과를 줍니다.

rainbow: LED 스트립에 무지개색 애니메이션을 보여줍니다.

clear_all_pixels(strip): 모든 LED를 끄는 유틸리티 함수입니다.

strip = rpi_ws281x.Ws2811(...): Ws2811 객체를 생성하여 LED 스트립을 제어합니다. 여기에 위에서 정의한 설정 값들이 들어갑니다.

strip.begin(): LED 스트립을 사용하기 전에 초기화합니다.

strip.setPixelColor(i, Color(...)): 특정 인덱스(i)의 LED 색상을 설정합니다.

strip.show(): setPixelColor로 설정한 변경 사항을 실제 LED에 적용합니다. show()를 호출하기 전까지는 LED에 아무 변화가 없습니다.

try...except KeyboardInterrupt: Ctrl+C를 눌러 프로그램을 종료할 때, 모든 LED를 끄고 깔끔하게 종료되도록 합니다.

🚀 실행 방법
위 코드를 ws2812_6leds.py와 같은 이름으로 저장합니다.

터미널을 열고 저장한 파일이 있는 디렉토리로 이동합니다.

반드시 sudo를 사용하여 실행해야 합니다. rpi_ws281x 라이브러리가 GPIO에 직접 접근하기 위해서는 루트 권한이 필요합니다.

sudo python3 ws2812_6leds.py

이제 6개의 WS2812B LED가 다양한 색상과 애니메이션 효과를 보여줄 것입니다. LED의 개수나 애니메이션 종류는 코드를 수정하여 자유롭게 변경할 수 있습니다.

Actions

내보내기 Atom PDF