วัด PWM
เป้าหมาย
หัวข้อที่มีชื่อว่า “เป้าหมาย”เมื่อจบบทเรียนนี้ คุณจะ
- วัดคาบเวลา (period) ความถี่ และ duty cycle ของ PWM จากรูปคลื่นได้
- เทียบ duty cycle ที่วัดได้กับค่าที่โปรแกรมสั่ง และอธิบายเมื่อไม่ตรงกัน
ก่อนเริ่ม
หัวข้อที่มีชื่อว่า “ก่อนเริ่ม”- ตั้งออสซิลโลสโคปให้ภาพนิ่งได้ (บทเรียน ออสซิลโลสโคปเบื้องต้น) และใช้ logic analyzer วัดเวลาได้ (บทเรียน จับสัญญาณดิจิทัลครั้งแรก)
- TESAIoT Dev Kit ที่ flash ตัวอย่าง QWA309 Header I/O Test ไว้ ออสซิลโลสโคปสองช่อง (หรือ logic analyzer) และมัลติมิเตอร์
- ส่วนเสริมของแล็บใช้เฟิร์มแวร์ MicroPython ของหลักสูตร AIoT in Action ที่มีคำสั่ง
led.brightness()ถ้าไม่มี ข้ามส่วนนั้นได้
ดูของจริงก่อน
หัวข้อที่มีชื่อว่า “ดูของจริงก่อน”หลักสูตร AIoT in Action มีตัวอย่าง 03_led_brightness.py
ที่หรี่ LED ด้วย led.brightness(pct) แล้วอ่านค่ากลับด้วย led.duty() ในตัวอย่างนั้นมีการทดลองหนึ่งที่สั่ง on() แล้วตามด้วย toggle()
หลอดดับไปแล้ว แต่ duty() ยังตอบเลขเดิม ความเห็นในโค้ดสรุปไว้ว่า “duty() = สิ่งที่สั่ง ไม่ใช่สิ่งที่วัด”
นี่คือคำถามของบทนี้ ตัวเลขที่โปรแกรมบอก กับสัญญาณที่ออกจากขาจริง ตรงกันไหม เราจะตอบด้วยเครื่องมือวัด ไม่ใช่ด้วยการเชื่อตัวเลขบนจอ
1. สามตัวเลขของ PWM
หัวข้อที่มีชื่อว่า “1. สามตัวเลขของ PWM”PWM (pulse-width modulation) คือสัญญาณสี่เหลี่ยมที่คาบเวลาคงที่ แต่ปรับสัดส่วนเวลาที่เป็น 1 ได้
คาบเวลา T = เวลาจากขอบขาขึ้นถึงขอบขาขึ้นถัดไปความถี่ f = 1 / Tduty cycle D = t_high / Tแรงดันเฉลี่ย V_avg = D × V_high (เมื่อโหลดหรือวงจรกรองเฉลี่ยสัญญาณ)ตัวอย่าง T = 2 ms, t_high = 0.5 ms บนขา 3.3 V
f = 1 / 2 ms = 500 Hz D = 0.5 / 2 = 25% V_avg = 0.25 × 3.3 V = 0.825 VLED ที่ขับด้วย PWM ความถี่สูงพอ ตาคนเห็นเป็นความสว่างเฉลี่ย (โดยทั่วไปสูงกว่าราว 100 Hz ขึ้นไปคนส่วนใหญ่ไม่เห็นกะพริบ แต่กล้องมือถืออาจยังเห็นเป็นแถบ) มัลติมิเตอร์โหมดแรงดันไฟตรงก็อ่านค่าเฉลี่ยได้ ถ้าคาบเวลาสั้นกว่าเวลาเฉลี่ยของเครื่องมาก ถ้าความถี่ต่ำอย่าง 25 Hz ตัวเลขจะกระโดดไปมา
2. PWM จากฮาร์ดแวร์กับ PWM จากซอฟต์แวร์
หัวข้อที่มีชื่อว่า “2. PWM จากฮาร์ดแวร์กับ PWM จากซอฟต์แวร์”PWM จากตัวจับเวลา (timer) ของฮาร์ดแวร์ ตัวนับนับขึ้นด้วยสัญญาณนาฬิกาความถี่ f_clk ครบ N ครั้งก็เริ่มใหม่ ขาเป็น 1 ขณะที่ค่านับยังน้อยกว่าค่าเปรียบเทียบ (compare)
f_PWM = f_clk / N D = compare / N ความละเอียดของ duty = 1 / Nตัวอย่าง f_clk = 1 MHz, N = 1000 ได้ PWM 1 kHz และ duty ปรับได้ละเอียด 0.1% ต่อขั้น ถ้าต้องการ 20 kHz จากนาฬิกา 100 MHz จะได้ N = 5000 ความละเอียด 0.02% รายละเอียดของรีจิสเตอร์ (ค่าที่ใส่คือ N หรือ N − 1) ต่างกันไปตามฮาร์ดแวร์ ใน PSoC บล็อกนี้ชื่อ TCPWM ให้ดูเอกสารของ PDL ประกอบ SDK ของ TESAIoT Dev Kit อธิบายว่าเส้นทางหรี่ไฟของ LED สี RGB ต่อขาเข้ากับสัญญาณของ TCPWM0 ส่วนหลักสูตร AIoT in Action อธิบายว่า LED ที่ไม่มีเส้นทาง PWM ของฮาร์ดแวร์ จะได้พัลส์สั้น ๆ ราว 12 ms แล้วดับ ไม่ค้างความสว่างไว้
PWM จากซอฟต์แวร์ โปรแกรมเขียนขาเป็น 1 หน่วงเวลา เขียนเป็น 0 หน่วงเวลา วนไป ปุ่ม PWM Out ของโปรแกรมทดสอบ header ทำแบบนี้ (เขียน P13.3 = 1, P13.4 = 0 หน่วง 20 ms แล้วสลับ ทำ 50 รอบ ตามโค้ดของตัวอย่าง) ข้อดีคือใช้ขาไหนก็ได้ ข้อเสียคือเวลาของคำสั่งอื่นและการขัดจังหวะ (interrupt) ปนเข้าไปในจังหวะ คาบเวลาจึงยาวกว่าที่ตั้งเล็กน้อยและแกว่งได้ (jitter) และ CPU ต้องไม่ไปทำอย่างอื่นระหว่างนั้น
คู่สัญญาณกลับเฟส (complementary) งานขับมอเตอร์ด้วยสะพาน H (H-bridge) ใช้สัญญาณสองเส้นที่กลับเฟสกัน สองเส้นนี้ ห้ามเป็น 1 พร้อมกัน ไม่อย่างนั้นทรานซิสเตอร์ด้านบนและด้านล่างจะนำไฟพร้อมกันและลัดวงจรแหล่งจ่าย (shoot-through) ระบบจริงจึงเว้น dead time ให้ทั้งสองเส้นเป็น 0 สั้น ๆ ก่อนสลับ
3. ทำไมค่าที่วัดได้ไม่ตรงกับค่าที่สั่ง
หัวข้อที่มีชื่อว่า “3. ทำไมค่าที่วัดได้ไม่ตรงกับค่าที่สั่ง”| สาเหตุ | อาการ | ตัวอย่าง |
|---|---|---|
| ความละเอียดของตัวนับ | duty ถูกปัดเป็นขั้น | N = 100 สั่ง 33.3% ได้จริง 33% |
| นับเกินหรือขาดหนึ่ง (off-by-one) | คาบเวลาหรือ duty คลาดหนึ่งขั้นเสมอ | ใส่ N แทน N − 1 ในรีจิสเตอร์ |
| PWM จากซอฟต์แวร์ | คาบเวลายาวกว่าที่ตั้ง และแกว่ง | ตั้ง 40 ms วัดได้ 40.1 ms |
| ขั้วกลับ | duty ที่วัดได้เป็น 100% ลบค่าที่สั่ง | LED ต่อแบบ active-low สั่ง 20% หลอดติด 80% ของเวลา |
| ตัวเลขในโปรแกรมไม่ใช่การวัด | โปรแกรมรายงานค่าที่สั่งครั้งล่าสุด | duty() ยังตอบ 100 หลัง toggle() ดับหลอดแล้ว |
| ขาไม่ได้ต่อกับ PWM ของฮาร์ดแวร์ | ได้พัลส์สั้นแล้วหยุด หรือไม่มีสัญญาณ | LED ที่ไม่มีเส้นทาง PWM |
| วิธีวัด | ความกว้างพัลส์เพี้ยนเมื่อขอบช้า | วัดที่ระดับ 10% แทน 50% ของแรงดัน |
วิธีวัดให้แม่น
- วัดความกว้างพัลส์ที่ ระดับ 50% ของแรงดัน (เครื่องส่วนใหญ่ใช้ระดับนี้ในการวัดอัตโนมัติ)
- วัดหลายคาบเวลาแล้วเฉลี่ย หรือใช้สถิติของเครื่อง (ค่าเฉลี่ย ต่ำสุด สูงสุด) ค่าต่ำสุดกับสูงสุดบอกได้ว่ามี jitter เท่าไร
- ความละเอียดของเวลาต้องละเอียดกว่าความละเอียดของ duty ที่อยากตรวจ ถ้าอยากเห็นขั้น 0.1% ของ PWM 1 kHz (1 µs) ต้องวัดเวลาได้ละเอียดกว่า 1 µs
ตัวอย่างสมบูรณ์
หัวข้อที่มีชื่อว่า “ตัวอย่างสมบูรณ์”โจทย์ วัด PWM จากปุ่ม PWM Out แล้วเทียบกับที่โค้ดสั่ง (ครึ่งคาบเวลา 20 ms, 50 รอบ, P13.3 กับ P13.4 กลับเฟสกัน) ตัวเลขที่วัดได้ด้านล่างเป็นข้อมูลตัวอย่าง
- ค่าที่สั่ง t_high = 20 ms, T = 40 ms, f = 25 Hz, D = 50%
- ต่อ ช่อง 1 ที่ P13.3 ช่อง 2 ที่ P13.4 กราวด์ของโพรบทั้งสองที่ GND ตั้ง 10 ms/div, 1 V/div, trigger ขาขึ้นของช่อง 1 ที่ 1.65 V, mode Normal
- วัดช่อง 1 (เฉลี่ย 10 คาบเวลา) T = 40.10 ms, t_high = 20.05 ms
f = 1 / 40.10 ms = 24.94 HzD = 20.05 / 40.10 = 50.0%คาบเวลายาวกว่าที่สั่ง 0.10 ms = 0.25%- อธิบาย duty ตรงกับที่สั่ง แต่คาบเวลายาวขึ้นเล็กน้อยทั้งครึ่งบนและครึ่งล่าง เป็นลักษณะของ PWM จากซอฟต์แวร์ที่มีเวลาของคำสั่งเขียนขาและวนลูปปนเข้าไปในทุกครึ่งคาบเวลา
- ตรวจคู่กลับเฟส ซูมที่ขอบที่สองช่องสลับกัน ดูว่ามีช่วงที่ทั้งสองเส้นเป็น 1 พร้อมกันไหม ในโค้ดตัวอย่าง ขาหนึ่งถูกเขียนเป็น 1 ก่อนอีกขาถูกเขียนเป็น 0 เพียงคำสั่งเดียว ถ้าเครื่องของคุณละเอียดพอ อาจเห็นช่วงซ้อนกันสั้นมาก ๆ ที่ขอบหนึ่งทุกรอบ นี่คือเหตุผลที่ระบบจริงต้องออกแบบ dead time ด้วยฮาร์ดแวร์ ไม่ใช่พึ่งลำดับคำสั่ง
- นับรอบ ต้องได้ 50 พัลส์บนช่อง 1
ฝึกเติม
หัวข้อที่มีชื่อว่า “ฝึกเติม”- PWM มีคาบเวลา 2 ms ความกว้างพัลส์ 0.5 ms หาความถี่ duty และแรงดันเฉลี่ยบนขา 3.3 V
- PWM 20 kHz duty 30% หาคาบเวลาและความกว้างพัลส์
- ตัวจับเวลาใช้นาฬิกา 10 MHz ต้องการ PWM 10 kHz ต้องนับกี่ครั้งต่อหนึ่งคาบเวลา ค่าเปรียบเทียบสำหรับ duty 33% คือเท่าไร และ duty ละเอียดได้เท่าไร
- LED ต่อแบบ active-low (ขาเป็น 0 หลอดติด) โปรแกรมสั่ง duty ของขา 20% หลอดติดกี่เปอร์เซ็นต์ของเวลา
- PWM จากซอฟต์แวร์ตั้งคาบเวลา 40.0 ms วัดได้ 40.4 ms คลาดกี่เปอร์เซ็นต์ ความถี่จริงเป็นเท่าไร
- ตัวจับเวลามี N = 100 โปรแกรมสั่ง 12.34% ฮาร์ดแวร์น่าจะให้ duty จริงเท่าไร
- ขา 3.3 V ขับ PWM duty 40% มัลติมิเตอร์โหมดแรงดันไฟตรงควรอ่านได้ราวเท่าไร ถ้าความถี่สูงพอ
- f = 500 Hz, D = 25%, V_avg = 0.825 V
- T = 1 / 20 kHz = 50 µs ความกว้างพัลส์ = 0.30 × 50 µs = 15 µs
- N = 10 MHz / 10 kHz = 1000 ค่าเปรียบเทียบ = 330 ความละเอียด 1 / 1000 = 0.1%
- หลอดติดเมื่อขาเป็น 0 คือ 100% − 20% = 80% ของเวลา
- (40.4 − 40.0) / 40.0 = 1% ความถี่ = 1 / 40.4 ms = 24.75 Hz
- 12 ขั้นจาก 100 คือ 12% (ถ้าโค้ดปัดเศษทิ้ง) คลาดจากที่สั่ง 0.34 จุดเปอร์เซ็นต์
- 0.40 × 3.3 V = 1.32 V
เช็กความเข้าใจ
หัวข้อที่มีชื่อว่า “เช็กความเข้าใจ”ตอบคำถามใน quiz.yaml ให้ถูกอย่างน้อย 4 ใน 5 ข้อ
ส่วน A: PWM Out บน P13.3 และ P13.4 ทำตามตัวอย่างสมบูรณ์ด้วยข้อมูลจริงของคุณ ใช้ออสซิลโลสโคป (หรือ logic analyzer ที่ 100 kHz ถ้าไม่มีสโคป)
ส่วน B: PWM3 Out บน P15.2 และ P15.3 กดปุ่ม PWM3 Out โปรแกรมขับคู่สัญญาณกลับเฟสแบบเดียวกันบนขาที่ใช้ร่วมกับ ADC วัดแบบเดียวกัน แล้วเทียบกับส่วน A
| ค่าที่สั่ง | P13.3 | P13.4 | P15.2 | P15.3 | |
|---|---|---|---|---|---|
| คาบเวลาเฉลี่ย | 40 ms | ||||
| ความถี่ | 25 Hz | ||||
| t_high | 20 ms | ||||
| duty | 50% | ||||
| jitter (T สูงสุด − ต่ำสุด) | 0 | ||||
| มีช่วงที่เป็น 1 พร้อมกับคู่ของมันไหม | ไม่มี |
ส่วน C: มัลติมิเตอร์กับ PWM วัด P13.3 ด้วยโหมดแรงดันไฟตรงระหว่างที่ PWM Out วิ่ง จดตัวเลขที่เห็น แล้วอธิบายว่าทำไมมันแกว่งรอบราว 1.65 V แทนที่จะนิ่ง
ส่วนเสริม: PWM ของ LED (ถ้ามีเฟิร์มแวร์ MicroPython และมีจุดวัดที่เข้าถึงได้)
- เปิดแผนผังวงจรของบอร์ด หาว่าขาของ LED สี RGB หรือตัวต้านทานที่ต่อกับมันมีจุดที่วัดได้อย่างปลอดภัยไหม ถ้าไม่มี ให้หยุดตรงนี้ ห้ามจิ้มขาชิป
- ถ้ามี สั่ง
led.brightness(10),led.brightness(50)และled.brightness(90)ทีละค่า วัดความถี่และ duty ที่จุดนั้น - อ่าน
led.duty()ทุกครั้งแล้วเทียบกับที่วัดได้ อย่าลืมพิจารณาขั้ว (LED ติดตอนขาเป็น 1 หรือ 0) ก่อนสรุป
โมดูลถัดไปเริ่มที่ ต่อวงจรบนเบรดบอร์ด เราจะต่อวงจรที่ใหญ่ขึ้นให้ถูกตั้งแต่ครั้งแรก และตรวจด้วยเครื่องมือทั้งหมดที่ใช้เป็นแล้วก่อนเสียบไฟ
สะท้อนคิด
หัวข้อที่มีชื่อว่า “สะท้อนคิด”ตัวเลขใดในโปรแกรมของคุณเองที่รายงาน “สิ่งที่สั่ง” แต่คุณเคยอ่านมันเป็น “สิ่งที่เกิดขึ้นจริง” และคุณจะพิสูจน์มันด้วยเครื่องมือตัวไหน
แหล่งอ้างอิง
หัวข้อที่มีชื่อว่า “แหล่งอ้างอิง”- AIoT in Action: examples/s03/03_led_brightness.py
- Oscilloscope (Wikipedia)
- Pulse-width modulation (Wikipedia)
- SDK: cm33/io/04_gpio_led_button.c (ขาของ LED สี RGB และเส้นทาง TCPWM)
- โค้ดของ QWA309 Header I/O Test (Developer Hub, commit 372d0d8)
คำถามทบทวน
ลองตอบเองก่อน แล้วค่อยเปิดดูเฉลย
-
PWM มีคาบเวลา 2 ms และความกว้างพัลส์ 0.5 ms ความถี่และ duty cycle เป็นเท่าไร (เป้าหมายข้อ 1)
- 500 Hz และ 25%
- 2 kHz และ 25%
- 500 Hz และ 75%
- 250 Hz และ 50%
ดูเฉลย
คำตอบ: A. 500 Hz และ 25%
f = 1 / 2 ms = 500 Hz และ D = 0.5 / 2 = 25%
-
ขา 3.3 V ขับ PWM duty 40% ความถี่สูง ต่อวงจรกรองที่เฉลี่ยสัญญาณ จะได้แรงดันเฉลี่ยเท่าไร (เป้าหมายข้อ 1)
- 1.32 V
- 1.98 V
- 3.3 V
- 0.40 V
ดูเฉลย
คำตอบ: A. 1.32 V
V_avg = D × V_high = 0.40 × 3.3 V = 1.32 V ส่วน 1.98 V คือกรณี duty 60%
-
วิธีใดทำให้วัด duty cycle ของ PWM ได้แม่นที่สุด (เป้าหมายข้อ 1)
- วัดคาบเวลาเดียวที่ระดับ 10% ของแรงดัน
- วัดความกว้างพัลส์ที่ระดับ 50% ของแรงดัน และเฉลี่ยหลายคาบเวลา
- อ่านค่าจากฟังก์ชัน duty() ของโปรแกรม
- ใช้มัลติมิเตอร์โหมดความต่อเนื่อง
ดูเฉลย
คำตอบ: B. วัดความกว้างพัลส์ที่ระดับ 50% ของแรงดัน และเฉลี่ยหลายคาบเวลา
ระดับ 50% ลดผลของขอบที่ช้า และการเฉลี่ยหลายคาบเวลาลดผลของความละเอียดเวลาและ jitter ค่าจากโปรแกรมคือค่าที่สั่ง ไม่ใช่ค่าที่วัด
-
โปรแกรมสั่ง duty 30% แต่วัดที่ขาได้ 70% ทุกค่าที่ลองสั่ง ผลรวมของค่าที่สั่งกับค่าที่วัดได้เป็น 100% เสมอ สาเหตุที่น่าจะเป็นที่สุดคืออะไร (เป้าหมายข้อ 2)
- ความละเอียดของตัวนับไม่พอ
- ขั้วของสัญญาณกลับ เช่น ขาออกตั้งเป็น active-low หรือวัดขาที่เป็นคู่กลับเฟส
- ความถี่ของ PWM สูงเกินไป
- ออสซิลโลสโคปเสีย
ดูเฉลย
คำตอบ: B. ขั้วของสัญญาณกลับ เช่น ขาออกตั้งเป็น active-low หรือวัดขาที่เป็นคู่กลับเฟส
D ที่วัดได้ = 100% − D ที่สั่ง คือรูปแบบของขั้วกลับ ความละเอียดของตัวนับทำให้คลาดเป็นขั้นเล็ก ๆ ไม่ได้กลับค่าทั้งหมด
-
หลังสั่ง on() แล้ว toggle() หลอด LED ดับ แต่ duty() ยังตอบ 100 อธิบายได้อย่างไร (เป้าหมายข้อ 2)
- หลอดเสีย
- duty() รายงานค่าที่สั่งครั้งล่าสุด ไม่ได้วัดสถานะจริงของขา
- toggle() ไม่ทำงาน
- PWM ของฮาร์ดแวร์ยังทำงานอยู่ที่ 100%
ดูเฉลย
คำตอบ: B. duty() รายงานค่าที่สั่งครั้งล่าสุด ไม่ได้วัดสถานะจริงของขา
ตัวอย่าง 03_led_brightness.py ของหลักสูตร AIoT in Action สาธิตเรื่องนี้ไว้ ตัวเลขในโปรแกรมคือสิ่งที่สั่ง การจะรู้ว่าขาทำอะไรจริงต้องวัดด้วยเครื่องมือ
อ้างอิงบทเรียนนี้
ถ้านำบทเรียนนี้ไปสอน ทำสไลด์ หรือทำเอกสารต่อ ให้อ้างอิงด้วยข้อความนี้ ถ้าดัดแปลงเนื้อหา ให้เติม (ดัดแปลง)ต่อท้ายชื่อบทเรียน
"วัด PWM" จาก TESA Open Knowledge โดยสมาคมสมองกลฝังตัวไทย (Thai Embedded Systems Association: TESA) https://github.com/tesaiot/tesa-qualification-program สัญญาอนุญาต CC BY-NC 4.0
ข้อความอ้างอิงภาษาอังกฤษ: "Measuring PWM" from TESA Open Knowledge by the Thai Embedded Systems Association (TESA), https://github.com/tesaiot/tesa-qualification-program, licensed under CC BY-NC 4.0
ลิงก์บทเรียน: https://tesaiot.github.io/tesa-qualification-program/courses/electronics-and-instruments/m05-oscilloscope/l02-measuring-pwm/
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0
เนื้อหาเผยแพร่ภายใต้ CC BY-NC 4.0 นำไปใช้ต่อในงานที่ไม่ใช่เพื่อการค้าได้ โปรดอ้างอิงสมาคมสมองกลฝังตัวไทย (TESA) ทุกครั้ง · วิธีอ้างอิง TESA