Viet Dev

Cover image for Arduino - Sử dụng chức năng PWM
Tuan for Unicloud Group

Posted on

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 signal
Analog 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,…​

Hình ảnh so sánh tín hiệu Analog và<br>
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
Duty cycle.

Hình ảnh về sự thay đổi duty cycle trong PWM (nguồn<br>
www.arduino.cc).

Hình ảnh về mối tương quan giữa PWM và tín hiệu analogWrite (nguồn<br>
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

Hình ảnh kết nối LED với board Arduino<br>
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);
}
Enter fullscreen mode Exit fullscreen mode

Giải thích source code

  • Biến brightness: Thiết lập cường độ sáng cho led, fadeAmount
    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.

Hình ảnh module LED<br>
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.

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

Bảng đấu nối chân của module LED RGB và board Arduino Uno

Hình ảnh kết nối module LED RGB với board Arduino<br>
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.
}
Enter fullscreen mode Exit fullscreen mode

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.

Oldest comments (0)