PWM 방식 LED 밝기 조절 > 스마트기기시스템

본문 바로가기

[실습] PWM 방식 LED 밝기 조절

필기자
19시간 24분전 5 0

본문

PWM 방식 LED 밝기 조절  

목 적
  • PWM output 방식을 이해한다.
  • DutyCycle에 대해 이해한다.
목 차
1. PWM DutyCycle 
2. DutyCycle을 활용한 LED 발기 조절 프로그램

1. PWM DutyCycle 
  • PWM에서 LED 밝기 조절 공식
    • 전압, 전류, 저항, 전력
      • 전압 (V)  →  수압 (물을 밀어주는 힘)
      • 전류 (A)  →  수량 (실제 흐르는 물의 양)
      • 저항 (Ω)  →  파이프 좁기 (굵을수록 저항 작음, 좁을수록 저항 큼)
      • 전력 (W)  →  물레방아 회전력 (실제 일하는 양)
    • 공급 전압 Vsupply = 3.3V (라즈베리파이 GPIO 기준), 저항 R = 50Ω (GPIO 내부 저항), 듀티사이클 80%
    • LED 순방향 전압(Vf)은 색상마다 다름 (데이터시트 KY-009 5050 RGB 기준)
      • 빨강: 1.8V ~ 2.4V (대표값 2.0V)
      • 초록: 2.8V ~ 3.6V (데이터시트 기준, 실사용 시 약 2.7V로 낮아짐)
      • 파랑: 2.8V ~ 3.6V (데이터시트 기준, 실사용 시 약 2.7V로 낮아짐)
    • LED 밝기 단위 : mcd (밀리칸델라)
      • mcd는 특정 방향으로 얼마나 밝게 빛나는지를 나타내는 광도 단위이다.
      • 데이터시트 기준값 (KY-009 5050 RGB, 20mA 기준)
        • 빨강: 300 ~ 500 mcd
        • 초록: 500 ~ 700 mcd
        • 파랑: 200 ~ 400 mcd
      • 단, 데이터시트 mcd 값은 20mA 정격 전류 기준이므로, 이 실습(GPIO 내부 저항만 사용, 전류 다름)에서는 데이터시트 값을 그대로 적용할 수 없다.
      • 정확한 밝기(mcd)와 평균 전류의 비례 관계는 직접 실험으로 측정해야 한다.
        • 조도계 (lux meter) 준비
        • LED와 조도계 거리 고정
        • 듀티사이클 10% ~ 100% 단계별 변화
        • 각 단계별 조도 (lux) 측정
        • 평균 전류 vs 조도 그래프 작성
  1. 순간 전류 (옴의 법칙):
    I = (Vsupply − Vf) / R
  2. 평균 전류 (옴의 법칙 × 듀티사이클) ∝ LED 밝기 :
    Iavg = I × 듀티사이클

※ 색상별 순간 전류 (3.3V 기준, R = 50Ω GPIO 내부 저항)

색상 Vf (데이터시트) Vf (실사용 추정) 순간 전류 I (mA)
I = (3.3 − Vf) / 50
mcd (데이터시트, 20mA 기준)
빨강 1.8V ~ 2.4V 2.0V (3.3 − 2.0) / 50 = 26mA 300 ~ 500 mcd
초록 2.8V ~ 3.6V 약 2.7V ※ (3.3 − 2.7) / 50 = 12mA 500 ~ 700 mcd
파랑 2.8V ~ 3.6V 약 2.7V ※ (3.3 − 2.7) / 50 = 12mA 200 ~ 400 mcd

※ 초록/파랑은 데이터시트 기준 Vf가 3.2V이지만, LED는 비선형 소자이므로 전류가 낮아지면 실제 Vf도 함께 낮아진다. 3.3V GPIO 환경에서는 약 2.7V 수준에서 동작점이 형성되어 정상 발광한다.

※ Keyes CNT1 모듈은 전류 제한 저항이 내장되어 있지 않으므로, GPIO 내부 저항(약 50Ω)만으로 전류가 제한된다. 빨강의 경우 GPIO 핀 권장 전류(16mA)를 초과하므로, 정식 회로 설계 시에는 외부 저항(150Ω 권장) 추가를 권장한다.

※ 위 mcd 값은 20mA 정격 전류 기준이며, 실습 환경의 전류와 다르므로 실제 밝기는 데이터시트 값과 다를 수 있다. 정확한 밝기 측정이 필요한 경우 조도계를 이용한 직접 실험이 필요하다.

빨강 LED 기준 듀티사이클별 평균 전류 (I = 26mA)

듀티사이클 (%) 순간 전류 (mA)
I = (3.3−2.0)/50
평균 전류 (mA)
Iavg = I × 듀티
10% 26 26 × 0.1 = 2.6
20% 26 26 × 0.2 = 5.2
30% 26 26 × 0.3 = 7.8
40% 26 26 × 0.4 = 10.4
50% 26 26 × 0.5 = 13.0
60% 26 26 × 0.6 = 15.6
70% 26 26 × 0.7 = 18.2
80% 26 26 × 0.8 = 20.8
90% 26 26 × 0.9 = 23.4
100% 26 26 × 1.0 = 26.0

2. DutyCycle을 활용한 LED 발기 조절 프로그램 
  • 기본 구동 프로그램 : 라즈베리파이 가상환경에서 파이썬 코딩
    • VSCode에서 led_pwm_duty.py 파일 생성
    • GPIO 18핀(핀 12)을 출력 모드로 설정
    • GPIO 18핀의 DutyCycle을 조절

import RPi.GPIO as GPIO
import time
# GPIO 모드 설정
GPIO.setmode(GPIO.BCM)
# LED 핀 설정
LED_PIN = 18
GPIO.setup(LED_PIN, GPIO.OUT)
# PWM 인스턴스 생성 (주파수 1kHz)
pwm = None
pwm = GPIO.PWM(LED_PIN, 10000)
pwm.start(0)  # DutyCycle 0으로 시작 (꺼진 상태)
try:
    while True:
        # 점점 밝아짐
        for dc in range(0, 101, 2):
            pwm.ChangeDutyCycle(dc)
            print("밝아 짐", dc)
            time.sleep(0.1)
        time.sleep(2)
        # 점점 어두워짐
        for dc in range(100, -1, -2):
            print("어두워 짐", dc)
            pwm.ChangeDutyCycle(dc)
            time.sleep(0.1)
        time.sleep(1)
except KeyboardInterrupt:
    # Ctrl+C 눌렀을 때 실행 종료
    pass  
finally:
    if pwm is not None:
        try:
            pwm.stop()
        except:
            pass
        del pwm  # __del__ 호출 시 오류 방지
    GPIO.cleanup()


[문제: RGB LED 색상 조합 제어 실습]
  • 3컬러 RGB LED는 아래와 같이 연결되어 있다.
    • 빨강: GPIO 18
    • 초록: GPIO 23
    • 파랑: GPIO 24 (미사용)
  • PWM을 사용하여 빨강(R)과 초록(G) 색상의 듀티사이클을 조절한다.
  • 색상은 주황 → 노랑 → 연두 → 갈색 순으로 서서히 변화한다.
    • R 100 고정 후 G 50→100 (주황→노랑)
    • G 100 고정 후 R 100→50 (노랑→연두)
    • R 50 고정 후 G 100→30 (연두→갈색)
    • G 30 고정 후 R 50→100 (갈색→주황) 
  • 각 색상은 0.1초 간격으로 부드럽게 전환되도록 한다.
  • 색상 전환은 무한 반복되도록 한다.


import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
R_PIN = 18
G_PIN = 23
GPIO.setup(R_PIN, GPIO.OUT)
GPIO.setup(G_PIN, GPIO.OUT)
pwm_r = None
pwm_g = None
pwm_r = GPIO.PWM(R_PIN, 1000)
pwm_g = GPIO.PWM(G_PIN, 1000)
pwm_r.start(0)
pwm_g.start(0)
try:
    while True:
        for g in range(50, 101, 5):      # 주황 → 노랑
            pwm_r.ChangeDutyCycle(100)
            pwm_g.ChangeDutyCycle(g)
            time.sleep(0.5)
        print("주황 -> 노랑")
        time.sleep(3)
        for r in range(100, 49, -5):     # 노랑 → 연두
            pwm_r.ChangeDutyCycle(r)
            pwm_g.ChangeDutyCycle(100)
            time.sleep(0.5)
        print("노랑 -> 연두")
        time.sleep(3)            
        for g in range(100, 29, -5):     # 연두 → 갈색
            pwm_r.ChangeDutyCycle(50)
            pwm_g.ChangeDutyCycle(g)
            time.sleep(0.5)
        print("연두 -> 갈색")
        time.sleep(3)  
        for r in range(50, 101, 5):      # 갈색 → 주황
            pwm_r.ChangeDutyCycle(r)
            pwm_g.ChangeDutyCycle(30)
            time.sleep(0.5)
        print("갈색 -> 주황")
        time.sleep(3)
except KeyboardInterrupt:
    # Ctrl+C 눌렀을 때 실행 종료
    pass        
finally:
    if pwm_r is not None:
        try:
            pwm_r.stop()
        except:
            pass
        del pwm_r  # __del__ 호출 시 오류 방지
   
    if pwm_g is not None:
        try:
            pwm_g.stop()
        except:
            pass
        del pwm_g  # __del__ 호출 시 오류 방지
    GPIO.cleanup()

댓글목록0

등록된 댓글이 없습니다.
게시판 전체검색