Arduino – Sử dụng chức năng PWM

Arduino – Sử dụng chức năng PWM

Analog và Digital

Trước khi tìm hiểu về PWM, chúng ta nên bắt đầu với 1 khái niệm đơn giản hơn nhưng vô cùng quan trọng trong điện tử, đó là Digital signalAnalog signal.

Từ đầu cuốn sách đến giờ, chúng ta chỉ sử dụng các mức điện áp VCC hoặc HIGH (mức 1) và 0V hoặc GND (mức 0). Trên thực tế, thế giới ta đang sống hầu như là các tín hiệu Analog. Ví dụ như màu sắc, nhiệt độ, độ ẩm hay cường độ ánh sáng của môi trường,…​

analog digital
Hình 1. Hình ảnh so sánh tín hiệu Analog và Digital.

Hiểu 1 cách đơn giản, Analog là những tín hiệu liên tục. Ví dụ trong dải điện áp từ 0-5VDC, tại 1 thời điểm, giá trị điện áp có thể là 1 số bất kì giữa 0 và 5 và thường được biểu diễn dưới giống như dạng sóng. Nó hiện hữu trong đời sống như âm thanh ta nghe được, hình ảnh ta thấy…​ Với Digital thì ngược lại, nó là những tín hiệu rời rạc. Ví dụ trong dải điện áp từ 0-5VDC, tại 1 thời điểm, giá trị điện áp chỉ có thể là 0V hoặc 5V, nó giống như 1 cái công tắc, 1 bức ảnh đen-trắng…​

Trong máy tính, vi điều khiển hoặc các thiết bị điện tử, tín hiệu số thường được sử dụng bởi nó có thể dễ dàng lưu trữ cũng như xử lí dữ liệu. Để có thể xử lí, chuyển đổi dữ liệu tương tự sang dữ liệu số, người ta thường chia nhỏ các phần của tín hiệu tương tự (quá trình này gọi là lấy mẫu), sau đó các phần chia nhỏ này được gán cho các giá trị 0 hoặc 1.

Các vi điều khiển thường có bộ chuyển đổi dữ liệu tương tự sang dữ liệu số gọi là ADC (Analog to Digital Converter) và 1 số vi điều khiển có luôn 1 bộ chuyển đổi dữ liệu số sang tương tự (DAC).

PWM

PWM là chữ viết tắt của Pulse Width Modulation, dịch theo nghĩa tiếng Việt có nghĩa là điều chế độ rộng xung. Đây là 1 công nghệ giúp các tín hiệu số cho ra kết quả gần giống như tín hiệu tương tự. Tín hiệu điều khiển số tạo ra bởi các xung (pulse), đó là sự lặp lại của việc thay đổi điện áp giữa mức 0 và mức 1. Yếu tố đặc trưng của PWM là chu kì và độ rộng xung.

Ví dụ, với 1 bóng LED, trong 1 chu kì sáng, nếu thời gian ở mức HIGH dài hơn thời gian mức LOW thì đèn LED sẽ sáng mạnh, thời gian mức HIGH thấp hơn thời gian mức LOW thì đèn sẽ sáng thấp hơn. Lợi dụng tính tăng này ta có thể thay đổi thời gian mức HIGH và mức LOW để điều chỉnh cường độ sáng của bóng LED. Tỉ số giữa thời gian của mức HIGH và mức LOW được gọi là Duty cycle.

pwm cycle
Hình 2. Hình ảnh về sự thay đổi duty cycle trong PWM (nguồn www.arduino.cc).
pwm
Hình 3. Hình ảnh về mối tương quan giữa PWM và tín hiệu analogWrite (nguồn commons.wikimedia.org).

Fade LED

Fade LED là 1 ví dụ cơ bản giúp chúng ta có thể sử dụng PWM trong Arduino.

Yêu cầu

Tự động thay đổi cường độ sáng của bóng đèn LED.

Linh kiện cần dùng

  • Board Arduino Uno

  • Đèn LED

  • Điện trở 330Ω

  • Dây kết nối

led pin
Hình 4. Hình ảnh kết nối LED với board Arduino Uno

Source code

int ledPin = 13;       //  Chân kết nối với LED
int brightness = 0;   //  Biến thiết lập cường độ sáng cho LED trên board
int fadeAmount = 15;  //  Biến thiết lập 1 bước thay đổi cường độ sáng.

void setup()
{
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  analogWrite(ledPin, brightness);

  brightness = brightness + fadeAmount;

  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  delay(30);
}

Giải thích source code

  • Biến brightness: Thiết lập cường độ sáng cho led, fadeAmount là 1 bước thay đổi cường độ sáng. Sử dụng hàm analogWrite() nhằm set giá trị cường độ sáng cho ledPin. LED sẽ sáng dần đến giá trị 255 sau đó sẽ tắt dần khi đến giá trị 0 và lặp đi lặp lại nhờ điều kiện trong câu lệnh if.

  • Giá trị từ 0 đến 255 tương ứng với Duty cycle từ 0% đến 100%.

Arduino không có bộ chuyển đổi DAC nhưng chúng ta có thể dùng PWM để có thể cho ra tín hiệu ngõ ra ở dạng gần như Analog, giá trị maximum = 255 là giá trị lớn nhất của chuyển đổi PWM chứ không liên quan đến bộ ADC (10 bits) của chip Atmega328.

Điều khiển LED RGB

Giới thiệu

LED RGB là module LED có 3 chân tín hiệu điều khiển tương ứng với 3 màu đỏ (Red), xanh lá (Green) và xanh dương (Blue). Chúng ta có thể phối hợp giữa các màu để tạo ra các hiệu ứng màu sắc đẹp mắt.

moduleRGB
Hình 5. Hình ảnh module LED RGB

Yêu cầu

Sử dụng button với 4 chế độ điều khiển:

  • Nhấn lần 1, LED sáng màu đỏ (Red).

  • Nhấn lần 2, LED sáng màu xanh lá (Green).

  • Nhấn lần 3, LED sáng màu xanh dương (Blue).

  • Nhấn lần 4, LED sáng cả 3 màu.

  • Nhấn lần 5, quay lại như lúc nhấn lần 1.

Linh kiện cần dùng

  • Board Arduino Uno

  • Module LED RGB

  • Nút nhấn

  • Điện trở 10KΩ

  • Dây kết nối

Đấu nối

Trên board Arduino Uno có các chân kí hiệu ~ đều có thể sử dụng chức năng PWM.

Bảng 1. Bảng đấu nối chân của module LED RGB và board Arduino Uno
Số thứ tự Chân trên Module LED RGB Chân trên board Arduino Uno

1

R

9

2

G

10

3

B

11

4

V/G

3.3V hoặc GND

ledrgb
Hình 6. Hình ảnh kết nối module LED RGB với board Arduino Uno

Source code

Nội dung source code đã được giải thích trong file.

#define pinLedRed     9         //  Chân kết nối với pin R của module LED-RGB
#define pinLedGreen   10        //  Chân kết nối với pin G của module LED-RGB
#define pinLedBlue    11        //  Chân kết nối với pin B của module LED-RGB
#define pinButton     2         //  Nút nhấn trên board

boolean lastPinButton = LOW;    //  Biến lưu trạng thái cuối của nút nhấn
boolean currentPinButton = LOW; //  Biến lưu trạng thái hiện tại của nút nhấn
int ledMode = 0;                //  Các chế độ của nút nhấn.

void setup()
{
  // Cài đặt các hướng của các chân
  pinMode (pinLedRed, OUTPUT);
  pinMode (pinLedGreen, OUTPUT);
  pinMode (pinLedBlue, OUTPUT);
  pinMode (pinButton, INPUT);
}

// Function chống dội phím khi nhấn (decoucing)
boolean debounce(boolean lastState)
{
  boolean currentState;                  // Biến currentState chỉ có 2 trạng trái LOW hoặc HIGH, khai báo kiểu boolean nhằm tiết kiệm tài nguyên CPU.
  currentState = digitalRead(pinButton); // Đọc trạng thái của button
  if (lastState != currentState) {       // Nếu nhấn Nút, chờ 20 mili giây, sau đó đọc lại trạng thái button 1 lần nữa.

    delay(20);
    currentState = digitalRead(pinButton);
  }
  return currentState;                   // Trả về trạng thái của button hiện tại
}

void setMode(int mode)
{
  if (mode == 1) {                      //  Màu đỏ: button nhấn lần 1
    digitalWrite(pinLedBlue, HIGH);
    digitalWrite(pinLedGreen, LOW);
    digitalWrite(pinLedRed, LOW);
  } else if (mode == 2) {               //  Màu xanh lá: button nhấn lần 2
    digitalWrite(pinLedBlue, LOW);
    digitalWrite(pinLedGreen, HIGH);
    digitalWrite(pinLedRed, LOW);
  } else if (mode == 3) {               //  Màu xanh dương: button nhấn lần 3
    digitalWrite(pinLedBlue, LOW);
    digitalWrite(pinLedGreen, LOW);
    digitalWrite(pinLedRed, HIGH);
  } else if (mode == 4) {               //  Sáng cả 3 màu: button nhấn lần 4
    int fadeAmount = 0;                 //  Bước thay đổi cường độ sáng
    int brightness;
    digitalWrite(pinLedBlue, LOW);
    digitalWrite(pinLedGreen, LOW);
    digitalWrite(pinLedRed, LOW);
    for (fadeAmount = 0; fadeAmount < 255; fadeAmount += 10) {
      brightness = fadeAmount;
      analogWrite(pinLedBlue, brightness);
      analogWrite(pinLedGreen, brightness);
      analogWrite(pinLedRed, brightness);
      delay(30);                        //  delay 30 mili giây để hiển thị kết quả
    }
  }
}
void loop()
{
  currentPinButton = debounce(lastPinButton);           //  Đọc trạng thái của nút nhấn ở function debounce()
  if (lastPinButton == LOW && currentPinButton == HIGH) //  Trạng thái nút nhấn đã thay đổi => đã nhấn phím
    ledMode++;
  lastPinButton = currentPinButton;                     //  Reset lại trạng thái nút nhấn.
  if (ledMode == 5)                                     //  Đang ở chế độ sáng 3 màu và nhấn button thì chuyển sang chế độ sáng màu đỏ (lặp lại chu kì)
    ledMode = 1;
  setMode(ledMode);                                     //  Đưa biến ledMode vào hàm setMode() để thực thi chế độ sáng tương ứng.
}
Với ledMode == 4, chương trình sẽ chạy hết vòng lặp for mới kiểm tra trạng thái của button. Ta có thể sử dụng interrupt để chương trình tối ưu hơn.

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *