3.14. การหรี่ LED ด้วย PWM¶
หน้า การสร้างสัญญาณแอนะล็อกด้วย PWM และฟิลเตอร์ RC ใช้ตัวกรองความถี่ต่ำ RC เพื่อดึงแรงดัน DC จากสัญญาณ PWM สำหรับ LED ไม่จำเป็นต้องใช้ตัวกรอง -- ดวงตามนุษย์เองทำหน้าที่เฉลี่ย
เมื่อ LED เปิดปิดเร็วกว่าประมาณ 60 Hz ระบบการมองเห็นหยุดแยกแยะพัลส์แต่ละอันและรับรู้ความสว่างคงที่เท่ากับค่าเฉลี่ยของแสงที่ส่งออก duty cycle 50 % รับรู้เป็นประมาณครึ่งความสว่าง 25 % เป็นหนึ่งในสี่ 10 % เป็นหรี่
การต่อวงจรเหมือนกับ LED ภายนอกแบบ static บนหน้า GPIO เอาต์พุต -- ตัวต้านทานจำกัดกระแสต่ออนุกรมกับ LED โดยคำนวณขนาดตามกฎในหน้า พื้นฐานอิเล็กทรอนิกส์ การเปลี่ยนแปลงอยู่ในซอฟต์แวร์เท่านั้น: พินทำงานเป็นเอาต์พุต PWM แทนที่จะเป็น Pin.OUT แบบธรรมดา
3.14.1. การเลือกความถี่¶
สำหรับ LED dimming ความถี่ PWM ต้องผ่านค่าขีดแบ่งการกะพริบของดวงตาเท่านั้น:
ต่ำกว่า ~60 Hz ดวงตาเห็นพัลส์โดยตรง
ต่ำกว่า ~200 Hz การมองเห็นรอบนอกและการเคลื่อนไหวดวงตาอย่างรวดเร็วยังอาจเผยให้เห็นการกะพริบ
1 kHz อยู่เหนือทุกค่านั้นอย่างสบายและเป็นค่าเริ่มต้นทั่วไป
ไม่มีขีดจำกัดบนที่สำคัญสำหรับ LED ขนาดเล็กบน GPIO ทุกอย่างตั้งแต่ 1 kHz ถึง 10 kHz ให้ผลเหมือนกันต่อดวงตา
3.14.2. การเฟด¶
ลูป fade-in / fade-out กวาด duty cycle จากปิดไปเปิดเต็มและกลับ โดยรอชั่วครู่ที่แต่ละขั้นตอน:
import time
from machine import PWM, Pin
led = PWM(Pin("P7"), freq=1000, duty_u16=0)
while True:
for d in range(0, 65535, 256):
led.duty_u16(d)
time.sleep_ms(5)
for d in range(65535, 0, -256):
led.duty_u16(d)
time.sleep_ms(5)
ที่ PWM 1 kHz และขั้นตอน 5 ms ดวงตาจะเห็นการเฟดที่ราบเรียบทั้งสองทิศทาง โดยความสว่างที่รับรู้ติดตามค่า duty
ความสว่างที่รับรู้ไม่เป็นเส้นตรงตาม duty cycle อย่างเคร่งครัด -- การตอบสนองของดวงตาเป็นไปตามกฎกำลังสองหรือลูกบาศก์โดยประมาณ -- ดังนั้นการกวาด duty_u16 เป็นเส้นตรงไม่ได้ดูเหมือนการกวาดความสว่างเป็นเส้นตรง สำหรับการเฟดที่ราบเรียบในการรับรู้ ให้เพิ่ม duty บนเส้นโค้ง
เทคนิคจำนวนเต็มล้วนที่สะดวกคือการเพิ่มตัวนับ 8 บิตและใช้กำลังสองเป็น duty cycle 255 × 255 = 65025 อยู่ในระยะปัดเศษของสเกลเต็ม ดังนั้นการกวาดครอบคลุมช่วงทั้งหมด:
import time
from machine import PWM, Pin
led = PWM(Pin("P7"), freq=1000, duty_u16=0)
while True:
for step in range(256):
led.duty_u16(step * step) # 0..65025, roughly quadratic
time.sleep_ms(5)
for step in range(255, -1, -1):
led.duty_u16(step * step)
time.sleep_ms(5)
การเฟดตอนนี้รู้สึกเรียบเนียนในความสว่างที่รับรู้จากปิดไปเต็ม