3.14. Регулирование яркости светодиода с помощью ШИМ

На странице Генерация аналогового сигнала с помощью PWM и RC-фильтра использовался RC-фильтр нижних частот для извлечения постоянного напряжения из сигнала ШИМ. Для светодиода фильтр не нужен – усреднение выполняет сам человеческий глаз.

Когда светодиод включается и выключается быстрее примерно 60 Гц, зрительная система перестаёт различать отдельные импульсы и воспринимает постоянную яркость, равную среднему световому потоку. Коэффициент заполнения 50 % воспринимается примерно как половина яркости; 25 % – как четверть; 10 % – как тусклый.

Подключение такое же, как для статичного внешнего светодиода на Вывод GPIO – токоограничивающий резистор последовательно со светодиодом, рассчитанный по правилам из Основы электроники. Изменение только в программе: вывод работает как выход PWM вместо обычного Pin.OUT.

3.14.1. Выбор частоты

Для регулирования яркости светодиода частота ШИМ должна лишь преодолеть порог мерцания глаза:

  • Ниже ~60 Гц глаз видит импульсы напрямую.

  • Ниже ~200 Гц периферийное зрение и быстрые движения глаз всё ещё могут выявить мерцание.

  • 1 кГц комфортно выше всего этого и является типичным значением по умолчанию.

Для маленького светодиода на GPIO нет значимой верхней границы; что угодно от 1 кГц до 10 кГц ведёт себя для глаза одинаково.

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)

При ШИМ 1 кГц и шагах по 5 мс глаз видит плавное затухание в обоих направлениях, при этом видимая яркость следует за значением коэффициента заполнения.

Воспринимаемая яркость не строго линейна по коэффициенту заполнения – отклик глаза следует примерно квадратичному или кубическому закону – поэтому линейное изменение 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)

Теперь затухание ощущается примерно равномерным по видимой яркости от выключенного состояния до максимума.