Lập trình ESP32 PWM với Arduino IDE (Analog Output)

Bài viết này sẽ hướng dẫn cách tạo ra tín hiệu PWM với ESP32 sử dụng Arduino IDE.
Để làm ví dụ, chúng ta sẽ cần một mạch điện đơn giản để điều khiển độ sáng của LED bằng tín hiệu PWM bởi ESP32. Bên cạnh đó, bài viết này cũng hướng dẫn bạn cách nhận cùng một tín hiệu PWM trên các GPIO khác nhau cùng một lúc.

Bạn cũng có thể tham khảo thêm nhiều nguồn sau đây:

Bộ điều khiển PWM ESP32


ESP32 có bộ điều khiển PWM với 16 kênh độc lập có thể được cấu hình để tạo tín hiệu PWM với các đặc tính khác nhau.
Dưới đây là các bước để làm mờ đèn LED với PWM bằng Arduino IDE:

  1. Chọn một kênh PWM. Có 16 kênh từ 0 đến 15.

2. Set tần số tín hiệu PWM. Đối với đèn LED thông thường tần số là 5000 Hz.

3. Set độ phân giải chu kỳ xung của tín hiệu. Chúng ta sẽ sử dụng độ phân giải 8 bit, có nghĩa là bạn có thể kiểm soát độ sáng của LED sử dụng giá trị từ 0 đến 255.

4. Chọn GPIO mà tín hiệu sẽ xuất hiện. Sử dụng hàm sau:

ledcAttachPin(GPIO, channel)


Hàm này chấp nhận hai đối số. Đầu tiên là GPIO sẽ xuất tín hiệu và thứ hai là kênh sẽ tạo ra tín hiệu.

5. Cuối cùng, để điều khiển độ sáng đèn LED bằng PWM, bạn sử dụng hàm sau:

ledcWrite(channel, dutycycle)


Hàm này sử dụng channel đang tạo tín hiệu PWM và chu kỳ xung.

Điều khiển LED

Hãy xem một ví dụ đơn giản để biết cách sử dụng bộ điều khiển ESP32 PWM bằng Arduino IDE.

Sơ đồ mạch

Nối dây LED vào ESP32 như trong sơ đồ sau. LED được kết nối với GPIO 16.

(Sơ đồ này sử dụng phiên bản module ESP32 DEVKIT V1 với 30 GPIO – nếu bạn đang sử dụng board khác nên kiểm tra sơ đồ chân của board.)

Lưu ý: bạn có thể sử dụng bất kỳ pin nào bạn muốn, miễn là nó có thể hoạt động như một đầu ra. Tất cả các chân có thể hoạt động như đầu ra đều có thể được sử dụng làm chân PWM. Để biết thêm thông tin về các GPIO của ESP32, tham khảo: Tham khảo Chân Ra của ESP32: Chân GPIO nào nên dùng?

Code

// the number of the LED pin
const int ledPin = 16;  // 16 corresponds to GPIO16

// setting PWM properties
const int freq = 5000;
const int ledChannel = 0;
const int resolution = 8;
 
void setup(){
  // configure LED PWM functionalitites
  ledcSetup(ledChannel, freq, resolution);
  
  // attach the channel to the GPIO to be controlled
  ledcAttachPin(ledPin, ledChannel);
}
 
void loop(){
  // increase the LED brightness
  for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++){   
    // changing the LED brightness with PWM
    ledcWrite(ledChannel, dutyCycle);
    delay(15);
  }

  // decrease the LED brightness
  for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle--){
    // changing the LED brightness with PWM
    ledcWrite(ledChannel, dutyCycle);   
    delay(15);
  }
}

Phân tích đoạn code trên:

Xác định chân mà LED được gắn vào. LED được gắn vào GPIO 16.

const int ledPin = 16; // 16 corresponds to GPIO16

Sau đó, set thuộc tính tín hiệu PWM. Tần số 5000Hz, chọn kênh 0 để tạo tín hiệu và đặt độ phân giải 8 bit. Bạn có thể chọn các thuộc tính khác, để tạo ra các tín hiệu PWM khác nhau.

const int freq = 5000; 
const int ledChannel = 0; 
const int resolution = 8;

Trong setup(), cấu hình LED PWM với các thuộc tính đã xác định trước đó bằng cách sử dụng hàm ledcSetup() với đối số ledChannel, tần số và độ phân giải, như sau:

ledcSetup(ledChannel, freq, resolution);

Tiếp theo, chọn GPIO nhận tín hiệu. Sử dụng hàm ledcAttachPin() với đối số ledpin ledChannel . Trong ví dụ này, chúng ta sẽ nhận tín hiệu ở GPIO ledPin, tương ứng với GPIO 16. Kênh tạo ra tín hiệu là ledChannel, tương ứng với kênh 0.

ledcAttachPin(ledPin, ledChannel);

Trong vòng lặp, thay đổi chu kỳ xung từ 0 đến 255 để tăng độ sáng của đèn LED.

for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++)
{
    // changing the LED brightness with PWM
    ledcWrite(ledChannel, dutyCycle);
    delay(15); 
}

Và sau đó, điều chỉnh từ 255 đến 0 để giảm độ sáng.

for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle--){
    // changing the LED brightness with PWM
    ledcWrite(ledChannel, dutyCycle);
    delay(15);
 }

Để set độ sáng của đèn LED, sử dụng hàm ledcWrite() với đối số kênh đang tạo tín hiệu và chu kỳ xung.

ledcWrite(ledChannel, dutyCycle);

Vì đang sử dụng độ phân giải 8 bit nên chu kỳ xung có giá trị từ 0 đến 255. Lưu ý rằng trong hàm ledcWrite(), chúng ta sử dụng kênh đang tạo tín hiệu chứ không phải GPIO.

Kiểm tra ví dụ

Upload code lên ESP32, chọn đúng board và cổng COM. Mạch của bạn sẽ có LED điều chỉnh được độ sáng tăng hoặc giảm.

Nhận cùng một tín hiệu trên các GPIO khác nhau

Bạn có thể nhận cùng một tín hiệu từ cùng một kênh trong các GPIO khác nhau. Để làm được điều đó, bạn cần thêm những GPIO đó vào cùng một kênh trong hàm setup().
Hãy sửa ví dụ trước để làm điều khiển 3 đèn LED sử dụng cùng một tín hiệu PWM từ cùng một kênh.


Sơ đồ mạch

Thêm hai LED nữa vào mạch theo sơ đồ sau:

(Sơ đồ này sử dụng phiên bản module ESP32 DEVKIT V1 với 30 GPIO – nếu bạn đang sử dụng board khác nên kiểm tra sơ đồ chân của board.)

Code

// the number of the LED pin
const int ledPin = 16;  // 16 corresponds to GPIO16
const int ledPin2 = 17; // 17 corresponds to GPIO17
const int ledPin3 = 5;  // 5 corresponds to GPIO5

// setting PWM properties
const int freq = 5000;
const int ledChannel = 0;
const int resolution = 8;
 
void setup(){
  // configure LED PWM functionalitites
  ledcSetup(ledChannel, freq, resolution);
  
  // attach the channel to the GPIO to be controlled
  ledcAttachPin(ledPin, ledChannel);
  ledcAttachPin(ledPin2, ledChannel);
  ledcAttachPin(ledPin3, ledChannel);
}
 
void loop(){
  // increase the LED brightness
  for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++){   
    // changing the LED brightness with PWM
    ledcWrite(ledChannel, dutyCycle);
    delay(15);
  }

  // decrease the LED brightness
  for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle--){
    // changing the LED brightness with PWM
    ledcWrite(ledChannel, dutyCycle);   
    delay(15);
  }
}

Phân tích đoạn code trên:

Đoạn code trên khá giống với code dành cho 1 LED, khác ở chỗ thêm 2 biến cho 2 LED mới là GPIO 5 và GPIO 17.

const int ledPin2 = 17; // 17 corresponds to GPIO17 
const int ledPin3 = 5;  // 5 corresponds to GPIO5

Trong hàm setup() thêm 2 dòng code được gán cả 2 GPIO cho kênh 0.

ledcAttachPin(ledPin2, ledChannel); 
ledcAttachPin(ledPin3, ledChannel);

Kiểm tra

Upload code mới lên ESP32 của bạn. Đảm bảo chọn đúng board và cổng COM. Cùng xem hình dưới đây:

Tất cả GPIO đang xuất ra cùng một tín hiệu PWM. Vì vậy, cả ba LED tăng và giảm độ sáng đồng thời, tạo ra hiệu ứng đồng bộ.

Xem Video Hướng dẫn

Tổng kết

Đến đây chắc hẳn bạn đã biết cách điều khiển LED bằng tín hiệu PWM của ESP32 với Arduino IDE. Các khái niệm mà bài viết đưa ra hy vọng bạn có thể học và vận dụng vào việc điều khiển các đầu ra khác sử dụng tín hiệu PWM.

Bạn có thể tham khảo nhiều bài viết khác dưới đây:

Icons made by Freepik from www.flaticon.com