알다시피 디지털 신호는 켜짐(HIGH)과 꺼짐(LOW) 딱 두 가지 상태만 가진다. 그런데 LED를 서서히 밝히거나 어둡게 하고 싶다면 어떻게 해야 할까? 마치 아날로그 신호처럼 부드러운 밝기 조절이 필요할 때, 바로 PWM(Pulse Width Modulation), 즉 펄스 폭 변조가 그 솔루션이 될 수 있다. PWM은 디지털 신호를 아날로그처럼 활용하는 기술이다.
PWM 개념
PWM은 일정한 주기를 가진 펄스 신호를 사용한다. 이 주기 안에서 신호가 켜져 있는 시간의 비율을 듀티 사이클(Duty Cycle)이라고 부른다.
- 듀티 사이클이 높으면: 켜져 있는 시간이 길어져 평균 전압이 높아진다.
- 듀티 사이클이 낮으면: 켜져 있는 시간이 짧아져 평균 전압이 낮아진다.
이때 펄스가 너무 느리게 켜지고 꺼지면 장치가 깜빡이거나 제대로 작동하지 않을 수 있다. 그래서 PWM은 충분히 빠른 주파수로 펄스를 반복해서, 장치가 마치 연속적인 아날로그 신호를 받는 것처럼 느끼게 한다. 예를 들어, LED의 밝기를 조절할 때 PWM 주파수가 충분히 높으면 사람 눈에는 LED가 깜빡이는 것이 아니라 밝기가 부드럽게 변하는 것처럼 보인다.
임베디드에서 PWM의 활용
임베디드 시스템에서 PWM은 매우 유용하게 사용된다. 디지털 핀만으로 아날로그적인 제어가 가능해지기 때문이다.
- LED 밝기 조절: 가장 흔한 예시로, LED의 밝기를 섬세하게 조절할 수 있다. 듀티 사이클을 0%부터 100%까지 변화시키면 LED가 완전히 꺼진 상태부터 최대로 밝은 상태까지 부드럽게 변한다.
- DC 모터 속도 제어: 모터에 인가되는 전압을 PWM으로 조절하여 모터의 회전 속도를 제어한다. 듀티 사이클이 높으면 모터가 빠르게 돌고, 낮으면 느리게 돈다.
- 서보 모터 제어: 서보 모터의 각도를 제어하는 데 PWM이 사용된다. 특정 듀티 사이클 값에 따라 모터가 정해진 각도로 움직인다.
- 오디오 출력: 스피커에 PWM 신호를 보내 소리를 만들어낼 수도 있다. 펄스 폭을 오디오 신호에 따라 변조하여 다양한 음량을 표현한다.
아두이노 코드 예제: LED 밝기 조절
아래 코드는 아두이노에서 PWM을 이용해 LED의 밝기를 서서히 밝게 했다가 다시 어둡게 하는 예제이다.
#include <Arduino.h>
int ledPin = 9;
void setup() {
}
void loop() {
for (int fadeValue = 0; fadeValue <= 255; fadeValue += 5) {
analogWrite(ledPin, fadeValue);
delay(30);
}
for (int fadeValue = 225; fadeValue >= 0; fadeValue -= 5) {
analogWrite(ledPin, fadeValue);
delay(30);
}
}
코드 설명:
- #include <Arduino.h> : 아두이노 개발에 필요한 기본적인 라이브러리를 포함한다.
- int ledPin = 9; : LED가 연결될 디지털 핀 번호를 9번으로 설정한다. 아두이노 보드에서 PWM을 지원하는 핀을 사용해야 한다. (보통 보드에 보면 핀 번호 옆에 물결 표시(~)가 있다.)
- void setup() { } : 아두이노 보드가 시작될 때 단 한 번만 실행되는 함수이다. 이 예제에서는 특별히 초기화할 내용이 없어서 비워져 있다.
- void loop() { } : setup() 함수가 실행된 후 계속해서 반복적으로 실행되는 함수이다. 실제 프로그램의 동작이 이곳에서 이루어진다.
- for (int fadeValue = 0; fadeValue <= 255; fadeValue += 5) { ... } :
- 이 for 루프는 LED의 밝기를 0부터 255까지 5단계씩 증가시킨다.
- analogWrite(ledPin, fadeValue); : ledPin에 fadeValue에 해당하는 PWM 신호를 출력한다. analogWrite() 함수는 0(완전히 꺼짐)부터 255(최대 밝기)까지의 값을 받아 PWM 듀티 사이클을 조절한다.
- delay(30); : 30밀리초(ms) 동안 프로그램 실행을 잠시 멈춘다. 이는 밝기 변화가 너무 빠르게 일어나 눈으로 확인하기 어려워지는 것을 방지한다.
- for (int fadeValue = 225; fadeValue >= 0; fadeValue -= 5) { ... } :
- 이 for 루프는 LED의 밝기를 225부터 0까지 5단계씩 감소시킨다.
- 이전 for 루프의 마지막 값(255)과 자연스럽게 연결하기 위해 225에서 시작했지만, 255에서 시작해도 무방하다.
- analogWrite(ledPin, fadeValue); : ledPin에 fadeValue에 해당하는 PWM 신호를 출력한다.
- delay(30); : 30밀리초(ms) 동안 대기하여 밝기 변화를 부드럽게 보여준다.
아두이노 회로 디자인 & 시뮬레이션 영상
코드만 보여주면 서운할 수 있으니 아두이노 회로 디자인도 함께 올려본다. (브레드 보드를 사용한 이유는 납땜을 하지 않는 상황을 가정했기 때문...)

아래 영상은 코드를 실행한 시뮬레이션 영상이다. 저항(레지스터) 때문에 LED 밝기가 제한이 되는데, 여기서 저항을 빼면 LED는 아주 밝게 빛나겠지만 실제로 그렇게 하면 LED 부품이 타버리는 수가 있다. (경험담...😅)
** 아두이노 시뮬레이션 방법은 TinkerCAD 포스팅을 참고하자.
'Journey to CS > 임베디드' 카테고리의 다른 글
| [아두이노] millis() 타이머 함수로 진동모터와 LED 동시에 작동시키기 (1) | 2025.07.27 |
|---|---|
| 아두이노 스케치를 작성하다가 loop()함수에 대해 생긴 의문...그리고 답 (1) | 2025.07.27 |
| ESP32 시뮬레이터 - WOKWI 소개 (2) | 2025.06.24 |
| [아두이노] 푸시버튼을 적용한 S.O.S 신호 점멸 구현 (0) | 2025.06.23 |
| 아두이노 내장 LED로 S.O.S 구조 신호 깜빡이게 만들어 보기 (0) | 2025.06.14 |