การเปลี่ยนความถี่ PWM ของ Arduino

pwm หรือที่มีชื่อเต็มว่า Pulse-width modulation คือเทคนิคการการสั่ง on off ขา output ที่ความถี่สูง โดยสั่งงานจากโมดุล timer ภายใน

ปกติแล้ว Arduino จะมีขา pwm ให้เลือกใช้หลายขา โดยแต่ละขา pwn จะมีความถี่มาตราฐานของ pwm ที่แตกต่างกัน ขึ้นอยู่กับว่าขานั้นๆถูกควบคุมด้วย timer ตัวไหน ซึ่งขา pwm ที่ใช้ timer ร่วมกันจะต้องมีความถี่ของ pwm เท่ากันด้วย

ยกตัวอย่างเช่นขา pwm ขา D5 และ D6 ของ arduino uno จะใช้ timer 0 เป็นตัวสั่งงานและความถี่ pwm มาตรฐานเท่ากับ 976.56 เฮิร์ต แต่ว่าขา pwm D9 D10 ใช้ timer 1 มีความถี่ pwm มาตรฐานคือ 490.20 เฮิร์ต

โดยส่วนใหญ่แล้วเราก็มักจะใช้ขา pwm ในการสั่งงานที่ต้องการที่จะเร่งหรี่เอาพูดได้ ยกตัวอย่างเช่น การปรับความสว่างของหลอดไฟ การปรับความร้อนของฮิตเตอร์ หรือการควบคุมความเร็วของมอเตอร์

แล้วความถี่ของ pwm สำคัญอย่างไรล่ะทำไมเราถึงต้องเปลี่ยนแปลงความถี่มันด้วย

เพื่อนๆคงเคยขับมอเตอร์ด้วย pwm แล้วใช่ไหมครับ บางครั้งเราจะได้ยินเสียงความถี่สูงตอนมอเตอร์ทำงาน นั่นเป็นเพราะขา pwm ที่ขับมอเตอร์นั้นมีความถี่ที่อยู่ในระดับที่มนุษย์ได้ยินหรือตัวมอเตอร์ยังตอบสนองได้(~500 เฮิร์ต หรือ ~1000 เฮิร์ต ) จึงทำให้เราได้ยินเสียงรบกวนดังนั้นถ้าเราเพิ่มความถี่ของขา pwm ที่ขับมอเตอร์ให้สูงขึ้น ยกตัวอย่างเช่น เพิ่มความถี่เ ป็นประมาณ 4,000 เฮิร์ต หรือ 8000 เฮิร์ต ก็จะทำให้เสียงความถี่สูงรบกวนตอนมอเตอร์ทำงาน ลดลง หรืออาจจะหายไปเลยก็ได้

หรือในบางครั้งเราใช้ขา pwm ในการปรับความสว่างของหลอดไฟ LED แต่เมื่อเรามองหลอดไฟ LED ผ่านกล้องมือถือหรือกล้องถ่ายรูป ปรากฏว่ากล้องถ่ายรูปนั้นเห็น หลอดไฟ LED กระพริบ เราก็สามารถเพิ่มความถี่ของขา pwm ให้สูงขึ้น เพื่อกล้องไม่สามารถจับได้ทัน ตอนถ่ายรูปหรือถ่ายวีดีโอภาพก็จะมีความสวยงามมากขึ้น

แต่ในการเปลี่ยนความถี่ของขา pwm นั้น ต้องมีข้อระวังด้วย เพราะว่าก็อาจมีการทำงานของฟังก์ชันอื่นๆที่ใช้ timer มาช่วยผิดพลาดไป ยกตัวอย่าง เช่น คำสั่ง millis() หรือว่าคำสั่ง delay() ที่ใช้ timer 0 เข้ามาช่วย ถ้าหากเราปรับเปลี่ยนการทำงานของ timer 0 ก็จะทำให้การทำงานของฟังก์ชัน delay() และฟังก์ชัน millis() ผิดเพี้ยนไปจากเดิมครับ

โดยด้านล่างนี้เป็นตัวอย่าง code การตั้งค่าความถี่ pwm ของ Arduino ขาต่างๆโดยแยกเป็นกลุ่มแต่ละ timer โดยจะแสดงค่า default ของความถี่ของแต่ละขาไว้
การใช้งานให้ copy code ของขาที่ต้องการเซตความถี่ไปไว้ใน function void setup () จากนั้นเลือก uncomment ความถี่ที่ต้องการใช้

Code สำหรับบอร์ด Arduino ที่ใช้ชิพ ATmega 8, 168 หรือ ATmega328

//---------------------------------------------- Set PWM frequency for D5 & D6 -------------------------------
//NOTE: Changing this timer 0 affects millis() and delay!
//TCCR0B = TCCR0B & B11111000 | B00000001;    // set timer 0 divisor to     1 for PWM frequency of 62500.00 Hz
//TCCR0B = TCCR0B & B11111000 | B00000010;    // set timer 0 divisor to     8 for PWM frequency of  7812.50 Hz
  TCCR0B = TCCR0B & B11111000 | B00000011;    // set timer 0 divisor to    64 for PWM frequency of   976.56 Hz (The DEFAULT)
//TCCR0B = TCCR0B & B11111000 | B00000100;    // set timer 0 divisor to   256 for PWM frequency of   244.14 Hz
//TCCR0B = TCCR0B & B11111000 | B00000101;    // set timer 0 divisor to  1024 for PWM frequency of    61.04 Hz


//---------------------------------------------- Set PWM frequency for D9 & D10 ------------------------------

//TCCR1B = TCCR1B & B11111000 | B00000001;    // set timer 1 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR1B = TCCR1B & B11111000 | B00000010;    // set timer 1 divisor to     8 for PWM frequency of  3921.16 Hz
  TCCR1B = TCCR1B & B11111000 | B00000011;    // set timer 1 divisor to    64 for PWM frequency of   490.20 Hz (The DEFAULT)
//TCCR1B = TCCR1B & B11111000 | B00000100;    // set timer 1 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR1B = TCCR1B & B11111000 | B00000101;    // set timer 1 divisor to  1024 for PWM frequency of    30.64 Hz

//---------------------------------------------- Set PWM frequency for D3 & D11 ------------------------------

//TCCR2B = TCCR2B & B11111000 | B00000001;    // set timer 2 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR2B = TCCR2B & B11111000 | B00000010;    // set timer 2 divisor to     8 for PWM frequency of  3921.16 Hz
//TCCR2B = TCCR2B & B11111000 | B00000011;    // set timer 2 divisor to    32 for PWM frequency of   980.39 Hz
  TCCR2B = TCCR2B & B11111000 | B00000100;    // set timer 2 divisor to    64 for PWM frequency of   490.20 Hz (The DEFAULT)
//TCCR2B = TCCR2B & B11111000 | B00000101;    // set timer 2 divisor to   128 for PWM frequency of   245.10 Hz
//TCCR2B = TCCR2B & B11111000 | B00000110;    // set timer 2 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR2B = TCCR2B & B11111000 | B00000111;    // set timer 2 divisor to  1024 for PWM frequency of    30.64 Hz

Code สำหรับบอร์ด Arduino ที่ใช้ชิพ ATmega1280 หรือ ATmega2560

//---------------------------------------------- Set PWM frequency for D4 & D13 ------------------------------

//TCCR0B = TCCR0B & B11111000 | B00000001;    // set timer 0 divisor to     1 for PWM frequency of 62500.00 Hz
//TCCR0B = TCCR0B & B11111000 | B00000010;    // set timer 0 divisor to     8 for PWM frequency of  7812.50 Hz
  TCCR0B = TCCR0B & B11111000 | B00000011;    <// set timer 0 divisor to    64 for PWM frequency of   976.56 Hz (Default)
//TCCR0B = TCCR0B & B11111000 | B00000100;    // set timer 0 divisor to   256 for PWM frequency of   244.14 Hz
//TCCR0B = TCCR0B & B11111000 | B00000101;    // set timer 0 divisor to  1024 for PWM frequency of    61.04 Hz


//---------------------------------------------- Set PWM frequency for D11 & D12 -----------------------------

//TCCR1B = TCCR1B & B11111000 | B00000001;    // set timer 1 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR1B = TCCR1B & B11111000 | B00000010;    // set timer 1 divisor to     8 for PWM frequency of  3921.16 Hz
  TCCR1B = TCCR1B & B11111000 | B00000011;    // set timer 1 divisor to    64 for PWM frequency of   490.20 Hz (Default)
//TCCR1B = TCCR1B & B11111000 | B00000100;    // set timer 1 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR1B = TCCR1B & B11111000 | B00000101;    // set timer 1 divisor to  1024 for PWM frequency of    30.64 Hz

//---------------------------------------------- Set PWM frequency for D9 & D10 ------------------------------

//TCCR2B = TCCR2B & B11111000 | B00000001;    // set timer 2 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR2B = TCCR2B & B11111000 | B00000010;    // set timer 2 divisor to     8 for PWM frequency of  3921.16 Hz
//TCCR2B = TCCR2B & B11111000 | B00000011;    // set timer 2 divisor to    32 for PWM frequency of   980.39 Hz
  TCCR2B = TCCR2B & B11111000 | B00000100;    // set timer 2 divisor to    64 for PWM frequency of   490.20 Hz (Default)
//TCCR2B = TCCR2B & B11111000 | B00000101;    // set timer 2 divisor to   128 for PWM frequency of   245.10 Hz
//TCCR2B = TCCR2B & B11111000 | B00000110;    // set timer 2 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR2B = TCCR2B & B11111000 | B00000111;    // set timer 2 divisor to  1024 for PWM frequency of    30.64 Hz


//---------------------------------------------- Set PWM frequency for D2, D3 & D5 ---------------------------

//TCCR3B = TCCR3B & B11111000 | B00000001;    // set timer 3 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR3B = TCCR3B & B11111000 | B00000010;    // set timer 3 divisor to     8 for PWM frequency of  3921.16 Hz
  TCCR3B = TCCR3B & B11111000 | B00000011;    // set timer 3 divisor to    64 for PWM frequency of   490.20 Hz (Default)
//TCCR3B = TCCR3B & B11111000 | B00000100;    // set timer 3 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR3B = TCCR3B & B11111000 | B00000101;    // set timer 3 divisor to  1024 for PWM frequency of    30.64 Hz


//---------------------------------------------- Set PWM frequency for D6, D7 & D8 ---------------------------

//TCCR4B = TCCR4B & B11111000 | B00000001;    // set timer 4 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR4B = TCCR4B & B11111000 | B00000010;    // set timer 4 divisor to     8 for PWM frequency of  3921.16 Hz
  TCCR4B = TCCR4B & B11111000 | B00000011;    // set timer 4 divisor to    64 for PWM frequency of   490.20 Hz (Default)
//TCCR4B = TCCR4B & B11111000 | B00000100;    // set timer 4 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR4B = TCCR4B & B11111000 | B00000101;    // set timer 4 divisor to  1024 for PWM frequency of    30.64 Hz


//---------------------------------------------- Set PWM frequency for D44, D45 & D46 ------------------------

//TCCR5B = TCCR5B & B11111000 | B00000001;    // set timer 5 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR5B = TCCR5B & B11111000 | B00000010;    // set timer 5 divisor to     8 for PWM frequency of  3921.16 Hz
  TCCR5B = TCCR5B & B11111000 | B00000011;    // set timer 5 divisor to    64 for PWM frequency of   490.20 Hz (Default)
//TCCR5B = TCCR5B & B11111000 | B00000100;    // set timer 5 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR5B = TCCR5B & B11111000 | B00000101;    // set timer 5 divisor to  1024 for PWM frequency of    30.64 Hz

ตัวอย่างการใช้เพิ่มความถี่ขา D9 เป็น 3921.16 เฮิร์ต บนบอร์ด Arduino Uno

/*
  Fade

  This example shows how to fade an LED on pin 9 using the analogWrite()
  function.

  The analogWrite() function uses PWM, so if you want to change the pin you're
  using, be sure to use another PWM capable pin. On most Arduino, the PWM pins
  are identified with a "~" sign, like ~3, ~5, ~6, ~9, ~10 and ~11.

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Fade
*/

int led = 9;           // the PWM pin the LED is attached to
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

// the setup routine runs once when you press reset:
void setup() {
  // declare pin 9 to be an output:
  pinMode(led, OUTPUT);

  //---------------------------------------------- Set PWM frequency for D9 & D10 ------------------------------

  //TCCR1B = TCCR1B & B11111000 | B00000001;    // set timer 1 divisor to     1 for PWM frequency of 31372.55 Hz
  TCCR1B = TCCR1B & B11111000 | B00000010;    // set timer 1 divisor to     8 for PWM frequency of  3921.16 Hz
  //TCCR1B = TCCR1B & B11111000 | B00000011;    // set timer 1 divisor to    64 for PWM frequency of   490.20 Hz (The DEFAULT)
  //TCCR1B = TCCR1B & B11111000 | B00000100;    // set timer 1 divisor to   256 for PWM frequency of   122.55 Hz
  //TCCR1B = TCCR1B & B11111000 | B00000101;    // set timer 1 divisor to  1024 for PWM frequency of    30.64 Hz

}

// the loop routine runs over and over again forever:
void loop() {
  // set the brightness of pin 9:
  analogWrite(led, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);
}

แหล่งข้อมูล: https://arduinoinfo.mywikis.net/wiki/Arduino-PWM-Frequency

Leave a Comment