라즈베리 파이 보드에서 파이선 코딩에 의해 LED를 디지탈하게 ON 또는 OFF 가 가능하다. 더 나아가서 아날로그적으로 완전히 꺼진 상태에서 최대 밝기까지 연속적으로 LED를 ON했다가 다시 서서히 완전히 꺼질때까지 OFF 해 보도록 하자. LED 의 밝기를 연속적으로 변화시키는 것을 Dimmering 또는 Fading 이라고 한다.
아두이노 편집기 예제 사례를 보면 BASIC에 Fade 코드 예제가 들어 있다. 단순한 디지털 ON OFF는 digitalWrite(#pin, HIGH) 와 digitalWrite(#pin, LOW)를 사용하여 가능한 반면에 연속적으로 밝기가 변하는 아날로그적으로 LED 밝기를 변화 시키기 위해서는 별도로 anlogWrite(#pin, 0∼255) 명령이 사용되고 있다.
이미 라즈베리 파이 보드에서 파이선 사용 경험이 일년 반이 지났지만 지금까지 라즈베리 파이 보드에서도 아두이노의 analogWrite() 명령처럼 LED 밝기 조절이 가능한지 모르고 있었다가 지금에서야 RPi.GPIO 라이브러리 모듈에서 PWM 명령을 지원한다는 것을 뒤늦게 알게 되어 그 코딩 방법을 올리도록 한다.
라즈베리 파이 보드에서 위 그림의 배선도를 참조하여 BCM 16번 또는 GPIO 16번에 LED 와 220Ω 전류제한 저항을 직렬로 연결하고 그 끝을 GND 에 연결 배선한다. LED 의 양극 + 는 LED 의 두 리드선중에 긴쪽이다.
PWM 이란 Pulse Width Modulation 의 약어이다. 펄스 파를 대상으로 PWM을 기술하려면 두가지 즉 주파수(frequency)와 듀티(duty)를 염두에 두어야 한다.
물리학에서 Sine 파의 주파수 정의에 의하면 같은 모양의 1 사이클이 1초에 몇 번 되풀이 되느냐에 따라서 주파수가 정해진다. 마찬가지로 ON OFF 로 이루어지는 디지털 파형에서도 되풀이 되는 1 사이클을 1 듀티라 하고 1초에 몇 개의 듀티가 반복되느냐에 따라 주파수가 결정된다. 아울러 1 듀티를 100%라고 하면 ON 인 시간의 % 에 따라 듀티 값이 설정된다. 위 그림의 경우 50% 듀티와 75% 듀티 사례를 보여 준다.
digitalWrite() 명령으로 LED를 ON OFF 할 경우에는 듀티 관점에서 보면 ON은 100% 듀티이고 OFF 는 0% 듀티로 볼 수 있으며 100% 일 경우 밝기는 항상 일정하다.
반면에 주파수 값과 듀티 값을 조정하게 되면 LED의 밝기가 변화된다.
라즈베리 파이 파이선 코딩에서 LED 의 밝기를 연속적으로 변화시키려면 이 두 가지 파라메타 즉 주파수와 듀티 값이 변동하도록 설정할 필요가 있으며 추가로 시간 지연 효과까지 추가한다. 참고로 라즈베리 파이 보드의 기본 주파수는 589Hz 로 알려져 있다.
헤더 영역에 time 과 RPi.GPIO 라이브러리를 불러온다. time은 default 라이브러리로서 파이선이 설치되어 있으면 이미 포함되어 있다.
LED 배선을 위한 핀 번호 넘버링은 가장 보편적인 BCM 즉 GPIO 방식의 넘버링을 사용하도록 하며 커버 배선도 그림에서처럼 16번 핀에 배선한다.
GPIO.PWM 명령을 사용하여 핀 번호를 지정해 주고 PWM 주파수를 설정한다.
try: while 1: 이 부분은 싱글 보드 컴퓨터인 라즈베리로 하여금 마이크로 콘트롤러인 아두이노처럼 무한 루프를 돌게 하는 명령이다. 콘트롤 C를 입력하면 빠져 나올 수 있다.
첨부된 코드를 다운받아 실행해 보자. 혹 indentation 이 훼손되었는지 꼭 살펴보고 그렇다면 복원해서 실행하자.
#PWM_LED_01.py
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(16, GPIO.OUT)
p = GPIO.PWM(16, 50) # channel=16 frequency=50Hz
p.start(0)
try:
while 1:
for dc in range(0, 101, 5):
p.ChangeDutyCycle(dc)
time.sleep(0.05)
for dc in range(100, -1, -5):
p.ChangeDutyCycle(dc)
time.sleep(0.05)
except KeyboardInterrupt:
pass
p.stop()
GPIO.cleanup()