Главная chevron_right Наши уроки chevron_right Raspberry Pi Pico: управление ШИМ на python

Raspberry Pi Pico: управление ШИМ на python

Разбираемся с ШИМ на Raspberry Pi Pico и MicroPython: управляем яркостью светодиода через широту и частоту импульса, собираем простой диммер с кнопкой.

Общие сведения

В этом уроке мы разберёмся что такое ШИМ.

Каждый вывод Raspberry Pi Pico в режиме Pin.OUT может принимать значение логического нуля или логической единицы. Полного напряжения питания (+3.3 вольта относительно GND) или отсутствие этого напряжения (ноль вольт относительно GND). Соответственно мы можем зажечь светодиод или выключить светодиод, если он подключён к выводу Pi Pico. Но что если нам надо получить среднюю яркость светодиода? У данной проблемы есть не один способ решения (источник постоянного тока, ЦАП), но мы рассмотрим самый простой - ШИМ.

ШИМ - Широтно-Импульсная Модуляция.

Для управления яркостью светодиода мы можем включать и выключать его так быстро, что для человеческого глаза это будет выглядеть как изменение яркости. По своей сути быстрое включение и выключение (изменение логического уровня вывода) и есть ШИМ, но помимо изменения уровня у ШИМ есть ещё два важных параметра:

  • Частота импульса (frequency) - как быстро мы переключаем уровни
  • Широта импульса (duty) - процентное отношение уровней (в каком состоянии вывод проводит большую часть времени)

Собственно при помощи широты импульса мы и будем менять яркость светодиода. Широта импульса в MicroPython задаётся следующим образом:

pwm.duty_u16( ШЕСТНАДЦАТИБИТНОЕ_ЧИСЛО_БЕЗ_ЗНАКА )

ШЕСТНАДЦАТИБИТНОЕ_ЧИСЛО_БЕЗ_ЗНАКА - число с максимальным значением 65535 и минимальным - 0.

Если задать широту числом 65535 - это будет всё равно что отключить ШИМ и подать логическую единицу на вывод, светодиод будет гореть с максимальной яркостью. Ноль, соответственно, выключит светодиод.

Для этого урока нам понадобится:

Подключение

Подключим Trema-модуль Светодиод согласно таблице

Вывод модуляВывод Pi Pico
Vcc3V3(OUT)
GNDGND
SGP15

Подключим Trema-модуль Кнопку согласно таблице

Вывод модуляВывод Pi Pico
Vcc3V3(OUT)
GNDGND
SGP2

Управляем яркостью

Попробуем создать объект ШИМ и вручную управлять яркостью.

Во вкладке интерактивной оболочки введём:

>>> from machine import Pin, PWM

Затем создадим объект ШИМ:

>>> pwm = PWM(Pin("GP15"))

Зададим широту импульса в 50% (65535/2 ≈ 32000)

>>> pwm.duty_u16(32000)

Установим частоту ШИМ. Начиная с 200 Гц - мерцание будет незаметно для глаза, но мы выберем частоту ещё выше:

>>> pwm.freq(1000)

После последней команды светодиод должен загореться в половину яркости относительно того, если бы мы включили вывод при помощи Pin.on()

Попробуйте управлять яркостью и частотой из оболочки при помощи команд pwm.freq() и pwm.duty_u16()...

Диммер

При нажатии и удержании кнопки светодиод начнёт менять свою яркость. Если отпустить кнопку и зажать снова - направление изменения яркости поменяется (нажали и удерживаем первый раз - светодиод становится ярче, отпустили и нажали снова - светодиод начинает гаснуть).

Обратите внимание на директиву global в функции fadeLED(). Если её не поставить, то переменная будет локальная для этой функции.

# Подключаем модуль для работы с выводами
from machine import Pin, PWM, Timer
# Подключаем функцию сна (задержки)
from time import sleep

# Создаём объект кнопки, передавая в конструктор номер вывода и режим работы
button = Pin("GP2", Pin.IN)

# Создаём объект ШИМ, передавая в конструктор объект вывода, к которому подключён светодиод
led = PWM(Pin("GP15"))
# Указываем частоту ШИМ
led.freq(1000)
# Инициируем ШИМ
led.init()

# Сохраняем состояние кнопки
last_state = button.value()
# Указываем среднюю точку ШИМ (для 16-битного ШИМ это примерно 65535/2)
duty = 32000
# Создаём переменную направления изменения яркости светодиода
direction = True

# Функция изменения яркости светодиода
def fadeLED():
    global duty
    global direction

    # True направление - увеличиваем ШИМ
    if direction:
        duty += 1000
    else:
        duty -= 1000
    # Удерживаем ШИМ на максимальном или минимальном уровне (при переполнении переменной)
    if duty > 65000:
        duty = 65000
    if duty < 1000:
        duty = 0
    # Устанавливаем ШИМ на выводе светодиода
    led.duty_u16(duty)

# Бесконечный цикл
while True:
    # Записываем состояние кнопки
    button_state = button.value()

    # Если состояние изменилось и кнопка зажата - меняем направление диммера
    if button_state != last_state:
        last_state = button_state
        if button_state:
            direction = not direction

    # Если кнопка зажата - меняем яркость светодиода
    if button_state:
        fadeLED()

    sleep(.05)

Ссылки

Комплект для повторения проекта

Что понадобится

Это быстрый ориентир по основным модулям и деталям. Полный список для повторения проекта смотрите в самой статье.

3 позиции
Все уроки