บทความนี้กล่าวถึงการใช้ PWM (Pulse Width Modulate) ของไมโครคอนโทรลเลอร์ ESP32 ในเฟรมเวิร์ก Arduino หลังจากที่ได้กล่าวถึงการทำงานของส่วนนี้ใน ESP-IDF และ MicroPython ไปแล้ว โดยบทความกล่าวถึงฟังก์ชัน การใช้งาน และตัวอย่างโปรแกรม ด้วยการเชื่อมต่อบอร์ดกับลำโพงดังภาพที่ 1
คำสั่ง
การใช้งาน PWM ในเฟรมเวิร์ค Arduino ของไมโครคอนโทรลเลอร์ esp32 นั้นประกอบด้วย 3 ขั้นตอน คือ
- ตั้งค่าเพื่อกำหนดค่าความถี่และความละเอียดของค่าดิวตี้
- เชื่อมการตั้งค่าเข้ากับขานำออกสัญญาณ
- ส่งค่าดิวตี้ไปที่ขานำออกสัญญาณ
จากขั้นตอนทั้ง 3 นี้มีคำสั่งสำหรับใช้งานและรายละเอียดคำสั่งตามหัวข้อต่อไปนี้
การตั้งค่า
วิธีการตั้งค่าให้กับ PWM ต้องกำหนดผ่านคำสั่ง ledcSetup() เพื่อกำหนดให้ช่องสัญญาณที่ต้องการนั้นสร้างความถี่ที่กำหนด และค่าความละเอียดของช่วงค่าดังนี้
ledcSetup( หมายเลขช่องสัญญาณ, ความถี่, ความละเอียด )
การตั้งค่านี้ส่งผลต่อความถี่ที่ส่งให้กับอุปกรณ์ที่ใช้ช่องสัญญาณที่ระบุ ด้วยวิธีการนี้ ถ้าเรากำหนดค่าความถี่เป็นความถี่เดียวกับตัวโน้ตดนตรีจะส่งผลให้เกิดเสียงตามตัวโน๊ตนั้น
ค่าความละเอียดนั้นมีค่าได้ในช่วง 1 บิต ถึง 16 บิต ขึ้นอยู่กับความต้องการของผู้เขียนโปรแกรมว่าต้องการควบคุมความละเอียดของการกำหนดค่าดิวตี้ไซเคิลในระดับใด เช่น ถ้ากำหนดเป็น 8 บิตจะสามารถกำหนดค่าดิวตี้ได้เป็น 0 ถึง 255 และถ้ากำหนดเป็น 12 บิตจะสามารถกำหนดช่วงค่าของดิวตี้ได้อยู่ในช่วง 0 ถึง 4095 เป็นต้น
การกำหนดขา
คำสั่งสำหรับกำหนดให้ขาใดทำหน้าที่ PWM ต้องใช้คำสั่ง ledcAttachPin() โดยกำหนดหมายเลขขาและหมายเลขช่องสัญญาณที่เลือกใช้งานดังรูปแบบต่อไปนี้
ledcAttachPin( หมายเลขขา, หมายเลขช่องสัญญาณ )
การส่งข้อมูลไปที่ขา
การส่งค่าดิวตี้ให้กับขาที่กำหนดหน้าที่ไว้ต้องใช้งานผ่านทางคำสั่ง ledcWrite() โดยระบุขาที่ต้องการนำออกค่าและค่าดิวตี้ที่ต้องการดังนี้
ledcWrite( หมายเลขขา, ค่าดิวตี้ )
จากคำสั่งนี้จะพบว่า การกำหนดค่า duty ทำให้ความดังของเสียงนั้นมากหรือน้อย
ตัวอย่างโปรแกรม
ตัวอย่างโปรแกรมต่อไปนี้เป็นการเล่นตัวโน๊ตต C5,D5,F5,G5,A5,B5 และ C6 เมื่อผู้เล่นกด keL, keU, keD, keR, swM1, swM2, swA และ swB ออกทางลำโพงที่เชื่อมไว้ที่ขา GPIO19
#include <Arduino.h>
#define spk 19
#define spkCh 0
#define keL 39
#define keU 34
#define keD 35
#define keR 32
#define swM1 33
#define swM2 25
#define swA 26
#define swB 27
uint8_t input[] = {
keL, keU, keD, keR, swM1, swM2, swA, swB
};
uint16_t freq[] = {
523, 587, 659, 698, 784, 880, 988, 1047
};
void setup() {
Serial.begin(115200);
int i;
for (i = 0; i < 8; i++) {
pinMode(input[i], INPUT_PULLUP);
}
pinMode( spk, OUTPUT );
ledcSetup( spkCh, 0, 8 );
ledcAttachPin( spk, spkCh );
}
int8_t pressed = 0;
void loop() {
for (int idx = 0; idx < 8; idx++) {
if (digitalRead( input[idx] ) == 0) {
if (pressed == idx + 1) {
ledcWrite( spkCh, 100 );
break;
}
ledcSetup( spkCh, freq[idx], 8 );
ledcAttachPin( spk, spkCh );
ledcWrite( spkCh, 100 );
pressed = idx + 1;
Serial.printf("%d [%d] pressed\n", input[idx], freq[idx]);
break;
}
}
delay(200);
ledcWrite( spkCh, 0 );
}
สรุป
จากบทความนี้จะพบว่า การใช้งาน PWM กับไมโครคอนโทรลเลอร์ ESP32 ทำให้เราสามารถสร้างความถี่และกำหนดความดังออกทางลำโพงได้ด้วยการตั้งค่าความถี่จาก ledcSetup() และ ledcWrite() ซึ่งสามารถนำไปประยุกต์กับการเล่นเสียงดนตรีที่ปรับความดังได้ นอกจากนี้ การใช้ PWM ทำให้ผู้เขียนโปรแกรมไม่จำเป็นต้องมาเขียนการวนรอบเองเพื่อส่งค่า 0 หรือ 1 อีกด้วย สุดท้ายนี้ ขอให้สนุกกับการเขียนโปรแกรมครับ
(C) 2020-2022, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2021-11-28, 2022-01-27