Lab 5.2 – การใช้ Hardware PWM
โจทย์
- ให้ทำ LAB 5.1 แต่เปลี่ยนไปใช้ Hardware PWM
- กำหนดให้ความถี่ของสัญญาณ PWM = 5 kHz
แนวทาง
แม้ PWM จะสร้างได้โดยใช้ Software แต่ผลที่ได้อาจมีความละเอียดหรือความถี่ไม่เพียงพอกับการใช้งานบางประเภท เช่น การหรีไฟ LED หากความถี่ไม่สูงพอ (< 60 Hz) อาจยังเห็นว่ามันกระพริบได้ เป็นต้น ไมโครคอนโทรลเลอร์โดยปกติแล้วจะมี Hardware PWM มาให้ด้วย เช่น PIC16F886 ที่ใช้ในการทดลองนี้มีมาให้สองช่องโดยมีชื่อเรียกว่า CCP (Capture, Compare, PWM Module) โมดูล CCP1 จะอยู่ขา C2 และ CCP2 อยู่ขา C1 ตามลำดับ
การใช้งาน CCP
-
- ประกาศใช้งาน PWM – โดยใช้คำสั่ง
setup_ccp1(ccp_pwm); คำสั่งนี้เป็นการแจ้งให้ PIC ทราบว่าเราประสงค์จะใช้วงจรสร้างสัญญาณ PWM ตัวที่ 1 ของ PIC
- กำหนดคาบของ PWM – คาบถูกกำหนดโดย Timer2 ซึ่งมีรูปแบบดังนี้
setup_timer_2 (mode, period, postscale)
mode = T2_DIV_BY_1, T2_DIV_BY_4, หรือ T2_DIV_BY_16
period = ค่า 0-255
postscale = ค่า 1-16 (ค่านี้ไม่มีผลกับ pwm ใส่ค่าอะไรก็ได้, postscale มีผลเมื่อใช้กำหนดคาบของ Timer2 เท่านั้น)คาบของ PWM คำนวณได้ดังนี้
คาบ = (4/8) us . mode . (period+1)
เช่น
setup_timer_2(t2_div_by_16,0xff,8);
จะได้คาบ = 4/8 us . 16 . 256 = 2048 us หรือคือความถี่ 0.488 kHz
- กำหนด Duty – โดยใช้คำสั่ง
set_pwm1_duty(duty);
duty มีค่าได้ตั้งแต่ 0- 1023 สูตรคำนวนเวลาที่ pulse จะมีค่าเป็น high คือ
High time = (1/8) us . duty . modeเช่น ถ้าอยากได้ duty = 50% สำหรับคาบที่กำหนดไว้ในข้อ 2 ก็จะคำนวนค่า duty ได้ดังนี้
2048/2 us = 1/8 us . duty . 16
duty = 512ดังนั้นคำสั่งที่ต้องใช้คือ
set_pwm1_duty(512);
ข้อควรระวังในการตั้งค่า Dutyค่า duty 1023 อาจไม่ใช่ duty 100% เสมอไป duty 100% อาจเป็นค่าที่ต่ำกว่า 1023 ก็ได้ ต้องใช้การคำนวณเวลาที่ต้องการให้สัญญาณเป็น high เสมอ เช่น หาก คาบเท่ากับ 900 us และต้องการ duty 100% ค่า duty สำหรับคำสั่ง set_pwm1_duty() จะเป็น
900 = 1/8.duty.16
duty = 450
จะเห็นได้ว่าค่า duty แค่ 450 ก็ทำให้ได้ duty 100% แล้ว
- ประกาศใช้งาน PWM – โดยใช้คำสั่ง
ตัวอย่างโปรแกรม void main() { int16 my_duty; setup_ccp1(ccp_pwm); setup_timer_2(t2_div_by_16,0xff,8); // fade in example while (1) { set_pwm1_duty(my_duty); my_duty++; if (my_duty > 512) { my_duty = 0;} delay_ms(5); }
ข้อควรระวัง/คำแนะนำ
1. ค่า Duty ตัองใช้เป็น int16 เท่านั้น ถ้าเป็น int8 อาจทำให้ผลที่ได้เพี้ยนไปจากที่ต้องการ เช่น set_pwm1_duty(100); // แบบนี้ผิด ควรแก้เป็น
int16 duty = 100; set_pwm1_duty(duty);
หรือ
set_pwm1_duty((int16)100);
2. เมื่อใช้ Hardware PWM เราไม่จำเป็นต้องสั่ง output_low() หรือ output_high() เอง ตัววงจร PWM จะสร้างสัญญาณ low และ high ให้เองทันทีที่กำหนดค่า duty ผ่านทางคำสั่ง set_pwm1_duty()
3. แม้จะมีการ setup timer2 แต่เราไม่จำเป็นต้อง enable timer2 ในโปรแกรมก็ได้ วงจร PWM ยังทำงานได้แม้ interrup timer2 ไม่ถูกเปิดใช้งาน