Raspberry Pi Pico: ШИМ (PWM) — плавное затухание светодиода (MicroPython)

Узнайте, как генерировать ШИМ-сигналы (PWM) на Raspberry Pi Pico с использованием прошивки MicroPython. В качестве примера мы покажем, как плавно изменять яркость светодиода, меняя скважность (duty cycle) со временем.

Raspberry Pi Pico PWM с MicroPython — плавное затухание светодиода

Установка и запуск MicroPython на Raspberry Pi Pico

Для выполнения этого руководства вам необходимо установить прошивку MicroPython на плату Raspberry Pi Pico. Также вам понадобится IDE для написания и загрузки кода на плату.

Рекомендуемая IDE для работы с MicroPython на Raspberry Pi Pico — Thonny IDE. Следуйте следующему руководству, чтобы узнать, как установить Thonny IDE, прошить MicroPython и загрузить код на плату.

Знакомство с ШИМ (широтно-импульсная модуляция)

ШИМ (широтно-импульсная модуляция), или PWM (Pulse Width Modulation), — это метод управления мощностью, подаваемой на устройства. Он работает за счёт очень быстрого включения и выключения питания.

Например, если чередовать напряжение на светодиоде между HIGH и LOW очень быстро, ваши глаза не успеют уловить скорость, с которой светодиод включается и выключается; вы просто увидите различные градации яркости.

Пример плавного затухания светодиода с помощью ШИМ (PWM)

Именно так работает ШИМ — генерируя выходной сигнал, который переключается между HIGH и LOW с очень высокой частотой.

Скважность (duty cycle) определяет процент времени, в течение которого питание включено, по сравнению с общим временем цикла включения-выключения — посмотрите на следующую диаграмму.

Как работает ШИМ — широтно-импульсная модуляция (PWM)

Регулируя скважность, мы можем управлять средней мощностью, подаваемой на устройство. Например, более высокая скважность означает, что устройство получает больше мощности, а более низкая скважность приводит к уменьшению мощности. Это позволяет нам управлять такими параметрами, как яркость светодиодов, скорость моторов или громкость динамиков.

Например, скважность 50 процентов даёт 50 процентов яркости светодиода, скважность 0 означает, что светодиод полностью выключен, а скважность 100 означает, что светодиод горит на полную мощность. Изменение скважности — это способ получения различных уровней яркости.

GPIO Raspberry Pi Pico

Raspberry Pi Pico имеет 40 выводов, 26 из которых — программируемые GPIO, которые можно использовать для подключения периферийных устройств. Все GPIO Raspberry Pi Pico могут выводить ШИМ-сигналы — они отмечены на диаграммах светло-зелёным цветом.

Вы можете использовать следующие распиновки в качестве справочника для определения и нахождения каждого GPIO на вашей плате. Распиновка немного отличается для Pico и Pico W.

На следующем изображении показана распиновка Raspberry Pi Pico (какие функции поддерживает каждый вывод).

Распиновка Raspberry Pi Pico

Источник изображения: raspberrypi.com

Распиновка Raspberry Pi Pico W

Выводы, отмеченные красным — это выводы питания, выдающие 3.3 В. Чёрные выводы — это выводы GND. Все выводы, отмеченные светло-зелёным, можно использовать как «обычные» GPIO (вход и выход).

Raspberry Pi Pico — каналы ШИМ

Raspberry Pi Pico имеет 8 независимых ШИМ-генераторов, называемых срезами (slices). Каждый срез имеет два канала, что в сумме даёт 16 каналов ШИМ.

Частота ШИМ-сигнала может варьироваться от 8 Гц до 62,5 МГц, при этом микроконтроллер работает на частоте 125 МГц.

Два канала одного среза работают на одной частоте, но могут иметь разную скважность.

Класс machine.PWM

Для работы с ШИМ-сигналами на Raspberry Pi Pico с использованием MicroPython применяется класс machine.PWM. После создания объекта PWM, например с именем led_pwm:

led_pwm = PWM(Pin(20))

Вы можете использовать следующие методы:

  • led_pwm.freq(FREQUENCY) — для установки частоты ШИМ-сигнала.

  • led_pwm.duty_u16(DUTY_CYCLE) — для установки скважности. Значение должно быть от 0 до 65535 (16 бит).

  • led_pwm.deinit() — для выключения ШИМ на срезе ШИМ, используемом светодиодом (в данном примере это GPIO 20, поэтому ШИМ также будет остановлен на GPIO 21, так как они принадлежат одному и тому же срезу ШИМ).

Схема подключения

Теперь давайте создадим пример, чтобы лучше понять концепции ШИМ. Мы создадим простой пример плавного затухания светодиода (плавное увеличение и уменьшение яркости).

Перед тем как продолжить, подключите светодиод к Raspberry Pi Pico. Мы подключаем к GPIO 20, но вы можете использовать любой другой GPIO.

Необходимые компоненты

Raspberry Pi Pico светодиод на макетной плате

Вот список компонентов, необходимых для сборки схемы:

  • Raspberry Pi Pico

  • Светодиод 5 мм

  • Резистор 330 Ом

  • Макетная плата

  • Соединительные провода

Схема — Raspberry Pi Pico

Вы можете использовать следующую диаграмму в качестве справочника для подключения светодиода к плате Raspberry Pi Pico.

Raspberry Pi Pico — светодиод подключён к GPIO 20, схема

Скрипт — плавное затухание светодиода на RPi Pico

Следующий код создаёт ШИМ-сигнал на GPIO 20 и увеличивает и уменьшает скважность со временем для плавного затухания светодиода.

from machine import Pin, PWM
from time import sleep

# Set up PWM Pin
led = machine.Pin(20)
led_pwm = PWM(led)
duty_step = 129  # Step size for changing the duty cycle

#Set PWM frequency
frequency = 5000
led_pwm.freq (frequency)

try:
    while True:
      # Increase the duty cycle gradually
      for duty_cycle in range(0, 65536, duty_step):
        led_pwm.duty_u16(duty_cycle)
        sleep(0.005)

      # Decrease the duty cycle gradually
      for duty_cycle in range(65536, 0, -duty_step):
        led_pwm.duty_u16(duty_cycle)
        sleep(0.005)

except KeyboardInterrupt:
    print("Keyboard interrupt")
    led_pwm.duty_u16(0)
    print(led_pwm)
    led_pwm.deinit()

Как работает код

Для создания ШИМ-вывода импортируйте класс PWM в дополнение к классу Pin из модуля machine.

from machine import Pin, PWM

Вам также нужно импортировать функцию sleep из модуля time для добавления задержек в код.

from time import sleep

Сначала создайте объект Pin на GPIO по вашему выбору. В данном случае мы используем GPIO 20.

led = machine.Pin(20)

Затем создайте объект PWM на этом выводе, с именем led_pwm, следующим образом:

led_pwm = PWM(led)

Установите шаг скважности — меньшие значения приводят к более плавным и медленным переходам, а большие значения — к более резким и быстрым изменениям. Мы используем значение 129, потому что это целочисленный делитель числа 65535.

duty_step = 129  # Step size for changing the duty cycle

Примечание

Скважность может принимать значения от 0 до 65535 (16 бит). При этом 65535 соответствует 100% скважности (полная яркость), а 0 соответствует 0% скважности (светодиод выключен).

Установите частоту сигнала. Мы используем частоту 5000 Гц, но вы можете выбрать другое значение. Частота может принимать значения от 0 до 62500.

#Set PWM frequency
frequency = 5000
led_pwm.freq (frequency)

Для установки скважности используйте метод duty_u16() объекта PWM и передайте скважность в качестве аргумента:

led.duty(duty_cycle)

Внутри цикла while мы создаём цикл for, который увеличивает скважность на 129 на каждой итерации с интервалом 5 мс между каждым изменением.

for duty_cycle in range(0, 65536, duty_step):
    led_pwm.duty_u16(duty_cycle)
    sleep(0.005)

Функция range() имеет следующий синтаксис:

range(start, stop, step)
  • Start: число, указывающее, с какой позиции начинать. Мы хотим начать со скважности 0;

  • Stop: число, указывающее, на какой позиции остановиться, не включая это значение. Максимальная скважность — 65535. Поэтому мы используем 65535 + 1, то есть 65536.

  • Step: целое число, указывающее шаг приращения. По умолчанию приращение равно 1.

В каждом цикле for мы устанавливаем скважность светодиода равной текущему значению duty_cycle:

led_pwm.duty_u16(duty_cycle)

После этого переменная duty_cycle увеличивается на указанный вами шаг.

Когда скважность достигает полной яркости, мы аналогичным образом плавно уменьшаем яркость.

# Decrease the duty cycle gradually
for duty_cycle in range(65536, 0, -duty_step):
    led_pwm.duty_u16(duty_cycle)
    sleep(0.005)

Обратите внимание, что в этом примере мы используем операторы try и except.

Блок try содержит код, который мы хотим выполнить.

Блок except выполняется, если в блоке try возникает определённая ошибка. В данном случае он перехватывает ошибку KeyboardInterrupt, которая возникает, когда пользователь прерывает программу, нажав Ctrl+C в терминале или остановив программу в IDE. Когда эта ошибка обнаруживается, выполняется код внутри блока except.

В блоке except мы устанавливаем скважность светодиода в 0 (полностью выключен) с помощью led.duty_u16(0) и вызываем led.deinit() для выключения ШИМ.

except KeyboardInterrupt:
    print("Keyboard interrupt")
    led_pwm.duty_u16(0)
    print(led_pwm)
    led_pwm.deinit()

Это гарантирует, что светодиод будет правильно выключен и выполнена необходимая очистка, даже если программа была прервана пользователем.

Демонстрация

Сохраните код на плату Raspberry Pi Pico с помощью Thonny IDE или любой другой MicroPython IDE по вашему выбору.

Следуйте приведённым ниже инструкциям, если вы используете Thonny IDE.

Скопируйте предоставленный код в безымянный файл Thonny IDE.

Thonny IDE ШИМ плавное затухание светодиода MicroPython Raspberry Pi Pico

После того как код скопирован в файл, нажмите на иконку Save (Сохранить). Затем выберите Raspberry Pi Pico.

Сохранение файла на Raspberry Pi Pico MicroPython IDE

Сохраните файл с именем: main.py. Перезапишите все существующие файлы с таким же именем.

micropython файл main.py

Примечание

Когда вы называете файл main.py, Raspberry Pi Pico будет запускать этот файл автоматически при загрузке. Если вы назовёте его по-другому, он всё равно будет сохранён в файловой системе платы, но не будет запускаться автоматически при загрузке.

Перезагрузите плату (отключите и снова подключите её к компьютеру). Нажмите маленькую зелёную кнопку «Run Current Script» (Запустить текущий скрипт) или нажмите F5.

micropython файл main.py — команда запуска скрипта

Обратите внимание, что светодиод, подключённый к GPIO 20, начнёт «дышать» — его яркость будет плавно увеличиваться и уменьшаться со временем.

Raspberry Pi Pico светодиод ШИМ — выключен

Raspberry Pi Pico светодиод ШИМ — средняя яркость

Raspberry Pi Pico светодиод ШИМ — полная яркость

Вы можете остановить выполнение программы, нажав CTRL + C или нажав кнопку STOP. Обратите внимание, что светодиод выключится, и в терминале будет выведено сообщение.

Заключение

Подведём итог: для вывода ШИМ-сигналов на GPIO Raspberry Pi Pico мы можем использовать класс machine.PWM. Сначала вы создаёте объект PWM на выбранном GPIO. После этого вы можете использовать методы freq(), duty_u16() и deinit() объекта PWM для установки частоты ШИМ, скважности и остановки ШИМ соответственно.