PWM Là Gì?
Arduino Uno là vi điều khiển digital — nó chỉ xuất được 0V hoặc 5V, không có “2.5V”. Vậy làm sao điều chỉnh độ sáng LED?
PWM (Pulse Width Modulation) là kỹ thuật tạo ra điện áp trung bình giả bằng cách bật/tắt tín hiệu rất nhanh:
Sáng 100%: ‾‾‾‾‾‾‾‾‾‾ (luôn HIGH = 5V)
Sáng 75%: ‾‾‾‾‾‾___ (HIGH 75% thời gian)
Sáng 50%: ‾‾‾‾____ (HIGH 50% thời gian)
Sáng 25%: ‾‾______ (HIGH 25% thời gian)
Sáng 0%: __________ (luôn LOW = 0V)
Mắt người không nhận ra sự nhấp nháy ở tần số ~490 Hz (mặc định của Arduino) — chỉ thấy độ sáng thay đổi mượt mà.
Duty Cycle là phần trăm thời gian tín hiệu ở mức HIGH trong một chu kỳ.
Các Chân PWM Trên Arduino Uno
Chỉ 6 chân có khả năng PWM — nhận ra bởi ký hiệu ~ trên board:
| Chân | Timer sử dụng | Tần số PWM |
|---|---|---|
| D3 | Timer2 | ~490 Hz |
| D5 | Timer0 | ~980 Hz |
| D6 | Timer0 | ~980 Hz |
| D9 | Timer1 | ~490 Hz |
| D10 | Timer1 | ~490 Hz |
| D11 | Timer2 | ~490 Hz |
Lưu ý: D5 và D6 dùng Timer0 — timer này cũng dùng bởi
delay()vàmillis(). Thay đổi tần số PWM trên D5/D6 có thể ảnh hưởng đến timing.
Hàm analogWrite()
analogWrite(pin, value);
// pin: một trong 6 chân PWM (~3, ~5, ~6, ~9, ~10, ~11)
// value: 0 (tắt hoàn toàn) đến 255 (sáng tối đa)
Ví dụ:
analogWrite(9, 0); // LED tắt (0%)
analogWrite(9, 64); // LED sáng 25%
analogWrite(9, 128); // LED sáng ~50%
analogWrite(9, 192); // LED sáng 75%
analogWrite(9, 255); // LED sáng tối đa (100%)
Không cần pinMode(OUTPUT) trước — analogWrite() tự cấu hình chân.
📷 [Hình minh hoạ: Biểu đồ PWM duty cycle 0%–25%–50%–75%–100% — sóng vuông teal trên nền trắng, nhãn thời gian ON/OFF rõ ràng]
Kết Nối LED
Kết nối LED vào chân D9 (có PWM):
Arduino D9 ──[220Ω]──▷|── GND
Không khác gì bài trước — chỉ khác là chuyển sang chân D9 thay vì D13.
Hiệu Ứng Fade (Mờ Dần)
const int LED_PIN = 9;
void setup() {
// analogWrite tự set OUTPUT, không cần pinMode
}
void loop() {
// Sáng dần từ 0 → 255
for (int brightness = 0; brightness <= 255; brightness++) {
analogWrite(LED_PIN, brightness);
delay(10); // Mỗi bước dừng 10ms → 2.55 giây để sáng hết
}
// Tối dần từ 255 → 0
for (int brightness = 255; brightness >= 0; brightness--) {
analogWrite(LED_PIN, brightness);
delay(10);
}
}
Kết quả: LED nhịp thở mượt mà, sáng tối liên tục.
Fade Không Dùng delay() — Dùng millis()
const int LED_PIN = 9;
int brightness = 0;
int step = 1;
unsigned long lastUpdate = 0;
const int INTERVAL = 10; // ms mỗi bước
void setup() {}
void loop() {
unsigned long now = millis();
if (now - lastUpdate >= INTERVAL) {
lastUpdate = now;
analogWrite(LED_PIN, brightness);
brightness += step;
if (brightness >= 255 || brightness <= 0) {
step = -step; // Đảo chiều
}
}
// Ở đây có thể đọc cảm biến, xử lý nút nhấn... không bị block!
}
Cách này để board làm nhiều việc song song trong khi LED vẫn fade mượt.
Điều Chỉnh Độ Sáng Bằng Biến Trở
Kết hợp analogRead() (bài tiếp theo) với analogWrite():
const int POT_PIN = A0; // Biến trở vào A0
const int LED_PIN = 9; // LED ra D9
void setup() {
Serial.begin(9600);
}
void loop() {
int potValue = analogRead(POT_PIN); // 0 – 1023
int ledBrightness = potValue / 4; // Scale xuống 0 – 255
// Hoặc dùng map(): map(potValue, 0, 1023, 0, 255)
analogWrite(LED_PIN, ledBrightness);
Serial.print("Pot: "); Serial.print(potValue);
Serial.print(" → LED: "); Serial.println(ledBrightness);
delay(50);
}
Xoay biến trở — LED thay đổi độ sáng theo thời gian thực!
Ứng Dụng PWM Ngoài LED
PWM không chỉ dùng cho LED:
| Ứng dụng | Cách dùng |
|---|---|
| DC motor | analogWrite(motorPin, speed) — kiểm soát tốc độ |
| Servo motor | Dùng thư viện Servo.h (dựa trên PWM Timer1) |
| Còi buzzer | tone(pin, frequency) — tần số âm thanh |
| Đèn dimmer | Điều chỉnh độ sáng đèn qua module TRIAC/MOSFET |
| Nhiệt độ | PID controller điều chỉnh công suất heater |
Tổng Kết
| Khái niệm | Giá trị |
|---|---|
| Chân PWM | D3, D5, D6, D9, D10, D11 (ký hiệu ~) |
analogWrite(pin, 0) | Tắt hoàn toàn |
analogWrite(pin, 128) | ~50% duty cycle |
analogWrite(pin, 255) | 100% — tương đương digitalWrite(HIGH) |
| Tần số mặc định | ~490 Hz (D3, D9, D10, D11) hoặc ~980 Hz (D5, D6) |
Bài tiếp theo: Đọc tín hiệu Analog — tìm hiểu ADC 10-bit, analogRead(), và cách đọc biến trở, cảm biến ánh sáng LDR.


