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)

การเฟดตอนนี้รู้สึกเรียบเนียนในความสว่างที่รับรู้จากปิดไปเต็ม