IoTLabs

Nghiên cứu, Sáng tạo và Thử nghiệm

PWM Trên Arduino — Điều Chỉnh Độ Sáng LED và Tốc Độ Motor

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ânTimer sử dụngTần số PWM
D3Timer2~490 Hz
D5Timer0~980 Hz
D6Timer0~980 Hz
D9Timer1~490 Hz
D10Timer1~490 Hz
D11Timer2~490 Hz

Lưu ý: D5 và D6 dùng Timer0 — timer này cũng dùng bởi delay()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ướcanalogWrite() 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ụngCách dùng
DC motoranalogWrite(motorPin, speed) — kiểm soát tốc độ
Servo motorDùng thư viện Servo.h (dựa trên PWM Timer1)
Còi buzzertone(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ệmGiá trị
Chân PWMD3, 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.