3.14. עמעום LED באמצעות PWM

העמוד יצירת אות אנלוגי עם PWM ומסנן RC השתמש במסנן RC מעביר-נמוכים כדי לחלץ מתח DC מאות PWM. עבור LED, המסנן אינו נחוץ – העין האנושית עצמה מבצעת את המיצוע.

כאשר LED מודלק ומכובה מהר יותר מכ-60 Hz, מערכת הראייה מפסיקה להבחין בפעימות בודדות ותופסת בהירות יציבה השווה לפלט האור הממוצע. מחזור עבודה של 50 % נקרא כבהירות של בערך חצי; 25 % כרבע; 10 % כעמום.

החיווט זהה לזה של LED חיצוני סטטי ב-פלט GPIO – נגד מגביל זרם בטור עם ה-LED, שגודלו נקבע על פי הכללים מ-יסודות האלקטרוניקה. השינוי הוא רק בתוכנה: הפין פועל כפלט PWM במקום Pin.OUT רגיל.

3.14.1. בחירת התדר

עבור עמעום LED תדר ה-PWM צריך רק לעבור את סף ההבהוב של העין:

  • מתחת ל-~60 Hz העין רואה את הפעימות במישרין.

  • מתחת ל-~200 Hz ראייה היקפית ותנועת עיניים מהירה עדיין יכולות לחשוף הבהוב.

  • 1 kHz הוא הרבה מעל כל זה והוא ברירת מחדל טיפוסית.

אין חסם עליון בעל משמעות עבור LED קטן על GPIO; כל ערך מ-1 kHz עד 10 kHz מתנהג זהה לעין.

3.14.2. דעיכה

לולאת דעיכה-פנימה / דעיכה-החוצה סורקת את מחזור העבודה מכיבוי לדלוק במלואו וחזרה, ושוהה לרגע בכל שלב:

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_u16 אינה נראית כמו סריקה ליניארית של בהירות. לדעיכה חלקה יותר מבחינה תפיסתית, צעֵד את מחזור העבודה על עקומה.

טריק נוח מבוסס מספרים שלמים בלבד הוא לצעוד מונה 8 סיביות ולהשתמש בריבוע שלו כמחזור העבודה. 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)

הדעיכה כעת מרגישה אחידה בקירוב בבהירות הנראית מכיבוי עד למלא.