[TH] Arduino: ESP32 PWM.

บทความนี้กล่าวถึงการใช้ PWM (Pulse Width Modulate) ของไมโครคอนโทรลเลอร์ ESP32 ในเฟรมเวิร์ก Arduino หลังจากที่ได้กล่าวถึงการทำงานของส่วนนี้ใน ESP-IDF และ MicroPython ไปแล้ว โดยบทความกล่าวถึงฟังก์ชัน การใช้งาน และตัวอย่างโปรแกรม ด้วยการเชื่อมต่อบอร์ดกับลำโพงดังภาพที่ 1

ภาพที่ 1 บอร์ด esp32G2 ที่ติดตั้งลำโพงแบบบัซเซอร์ไว้ที่ GPIO19

คำสั่ง

การใช้งาน 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