3.2.LED의 밝기 조절 - PWM I
in Mechatronics on Classnote
LED 밝기 조절
Hardware PWM
앞서 [한 번 해보기] 를 수행하는 도중 잘 관찰하였다면 어느 순간부터 깜빡이지 않고 LED가 어두워진 것을 확인하였을 것이다. LED를 켜고 끄는 것을 빠르게 반복했을 뿐인데 왜 LED가 어두워졌을까? 어두워지는 것을 다시 확인해보기 위해서 위 코드의 while
문을 아래처럼 고쳐보자.
while (1)
{
int cnt = 0;
for (; cnt < 1000; cnt++)
{
digitalWrite(LED, HIGH); // HIGH 신호 출력
delayMicroseconds(cnt); // (cnt) 마이크로초동안 대기
digitalWrite(LED, LOW); // LOW 신호 출력
delayMicroseconds(1000 - cnt); // (1000-cnt) 마이크로초동안 대기
}
}
위의 코드를 실행하면, LED가 켜져있는 시간이 0 마이크로초에서 1000 마이크로초까지 증가한다. 그리고 켜져있는 시간이 늘어날 수록 LED가 밝게 보인다. 그림으로 보면 1000 마이크로초 중에서 HIGH로 유지되는 시간이 점점 늘어나는 것이다.
-PWM의 개념도
위의 그림에서 HIGH가 유지되는 짧은 순간을 pulse라고 하면, 여기서 pulse의 폭을 조정하여 밝기를 조정한 것이다. 따라서 이를 Pulse Width Modulation (PWM) 이라고 한다. LED를 껐다가 켰다가, 즉 0과 1이라는 디지털 신호를 가지고 밝기라는 아날로그적 특성을 바꾼 것이다. 일반적으로 다시 말하면 PWM의 특징은 바로 HIGH와 LOW라는 디지털 신호를 가지고 아날로그 신호를 모사할 수 있다는 것이다.
왜 PWM이 등장하게 되었을까? 거꾸로 생각해서 PWM이 없으면 컴퓨터에서 어떻게 아날로그 신호를 내보냈을지 생각해보자. LED 밝기 조절이라는 간단한 작업을 수행하기 위하여 전압을 조정해주기 위한, 디지털 신호 발생기에 비해서 매우 큰 아날로그 회로가 필요했을 것이다. PWM이라는 개념은 라즈베리파이같은 소형 컴퓨터에서 아날로그 신호의 모사를 가능하게 하였다.
참고로 라즈베리파이에서는 하드웨어 수준에서 PWM을 지원한다. 바로 지금까지 쓰고 있었던 GPIO18 핀에서 하드웨어 PWM을 지원한다. 코드를 아래처럼 고쳐보자.
#include <stdio.h>
#include <wiringPi.h>
#define LED 18
int main(void)
{
wiringPiSetupGpio();
pinMode(LED, PWM_OUTPUT);
while (1)
{
int cnt = 0;
for (; cnt < 1024; cnt++)
{
pwmWrite(LED, cnt); // PWM 출력
delayMicroseconds(1000);
}
}
return 0;
}
Software PWM
하드웨어 수준에서의 PWM은 1 마이크로초 단위로 제어가 되므로 매우 빠르다. 그래서 delayMicroseconds(1000)
없이는 밝아지는 것을 보기가 어렵고 오히려 깜빡이는 것이 보인다. 관심이 있으면 delayMicroseconds()
없이 실행해보자. 참고로 GPIO12에서도 PWM이 된다. 하지만 GPIO18과 동기화되어있어서 결국 독립적인 하드웨어 PWM은 12번 또는 18번 둘 중 하나뿐이다. WiringPi 라이브러리의 개발자 Gordon Henderson은 하드웨어 PWM 핀이 부족하다는 문제를 인식하고 소프트웨어적으로 PWM을 구현할 수 있도록 하였다! 그래서 어느 GPIO 핀이나 PWM처럼 작동할 수 있다. 100 마이크로초 단위로 제어하기 때문에 성능은 하드웨어 PWM에 비하여 떨어지지만 실사용하기에는 충분하다. 소프트웨어 PWM을 구현하기 위해서는 Geany의 Build Commands를 바꿔주어야 한다. 왜냐하면 소프트웨어 PWM은 Linux에서의 POSIX thread를 만드는 작업이 수반되어서, pthread
라이브러리를 추가해야하기 때문이다. 라이브러리의 추가는 앞에서 한 번 해보았으니 어렵지 않을 것이다. Geany에서 Build -> Set Build Commands의 Compile과 Build 부에서 -l wiringPi
뒤에 띄어쓰기 한 칸과 아래의 명령어를 추가하자.
-l pthread
-l
은 라이브러리를 포함하라는 뜻으로 이해가 되기 시작할 것이다. 소프트웨어 PWM의 작동을 확인해보기 위해서 LED의 긴 다리를 GPIO23으로 옮긴다. 이제 아래의 소프트웨어 PWM의 예제 코드를 따라서 작성해보자.
#include <stdio.h>
#include <wiringPi.h>
#include <softPwm.h>
#define LED 23
int main(void)
{
wiringPiSetupGpio();
softPwmCreate(LED, 0, 100); // 소프트웨어 PWM을 사용하는 pin 마다 사용
while (1)
{
int cnt = 0;
for (; cnt < 100; cnt++)
{
softPwmWrite(LED, cnt); // 소프트웨어 PWM 출력
delayMicroseconds(1000);
}
}
return 0;
}
소프트웨어 PWM이 잘 작동한다면 LED가 밝아졌다가 꺼졌다가 하는 것을 반복할 것이다.