День #8: Кольцо радуги!
Это день #8 адвент-календаря «Let it Glow»!
Сегодня мы снова поиграем с адресуемыми светодиодами, но на этот раз в формате RGB-кольца — ещё одного фаворита нашей команды!
Кольца из светодиодов — очень популярный формат, ведь с их помощью можно создавать по-настоящему интересные узоры и эффекты, а также встраивать их в проекты как многоцветный источник света.
Хватит слов — давайте сразу к мигающим огням!
Предупреждение
Некоторые из сегодняшних активностей содержат быстро мигающие огни, которые могут не подходить для людей с фотосенситивной эпилепсией.
Содержимое коробки #8
В этой коробке вы найдёте:
1x RGB-кольцо на 12 светодиодов
3x соединительных провода «папа-папа»
Сегодняшние активности
Сегодня мы подробнее познакомимся с адресуемыми светодиодами и узнаем, как соединять их в цепочку для создания по-настоящему весёлых световых эффектов.
Мы уже знаем, как настроить и использовать одиночный адресуемый светодиод (из дня #6), поэтому расширим эти знания и повторно используем некоторые функции и приёмы, которые уже изучили.
Но сначала — краткое введение в RGB-кольцо из сегодняшней коробки…
Что такое RGB-кольцо?
Эти светодиодные кольца — попросту двенадцать адресуемых светодиодов в ряд, расположенных на удобной круглой печатной плате (PCB). Каждый светодиод подключён к предыдущему благодаря контактам IN и OUT для передачи данных.
Это означает, что мы можем управлять всеми двенадцатью светодиодами по отдельности, используя всего один контакт GPIO нашего Pico.
Вы уже знаете про RGB из дня #6 — это кольцо стандартного формата RGB, а не GRB — так что давайте сразу перейдём к тому, как управлять вашим новым светодиодным кольцом!
Сборка схемы
Как всегда, убедитесь, что ваш Pico отключён от USB-кабеля при работе со схемой.
Подготовка макетной платы
Сегодня мы не используем никаких других компонентов (кольцо требует нашего полного внимания!), но оставим слайдер с вчерашнего дня на месте — возможно, вы захотите поиграть с ним позже…
Вот ваша отправная точка:
Подключение RGB-кольца
Этот компонент очень легко подключить: у него фиксированные ножки и всего три провода.
Сначала нам нужно установить кольцо лицевой стороной вперёд в правом верхнем углу макетной платы. Просто вставьте его — легко!
Затем подключаем только первые три контакта (мы не подключаем четвёртый контакт, так как это Data OUT для последовательного соединения с другими адресуемыми светодиодами):
Первый (левый) контакт — это Data IN. Подключаем его к GPIO 2 (физический контакт 4)
Второй контакт — это 5V. Подключаем его к VBUS (физический контакт 40)
Третий контакт — это GND. Подключаем его к любому контакту GND (мы использовали физический контакт 3)
У вас должно получиться примерно вот так:
Совет
Посмотрите на обратную сторону RGB-кольца — на плате удобно подписаны все контакты! Не все компоненты могут похвастаться такой роскошью…
Активность 1: Управление одним светодиодом
Быстрая первая активность, чтобы показать небольшое отличие в коде для кольца по сравнению с одиночным RGB-светодиодом из дня #6.
Мы по-прежнему импортируем библиотеку neopixel и настраиваем кольцо так же, как раньше, однако строка инициализации теперь должна отражать количество светодиодов в цепочке. Мы будем использовать ring = NeoPixel(Pin(2), 12) — это указывает GPIO2 для входа данных и 12 светодиодов в кольце. Просто!
Затем, чтобы указать коду, какой светодиод в кольце мы хотим зажечь, просто пишем ring[0] = (10,0,0). Это зажжёт первый светодиод, так как 0 задаёт первый элемент индекса (помните: индексы начинаются с нуля).
Примечание
Помните из дня #6, как значение RGB влияло на яркость света? Эти светодиодные кольца могут быть ОЧЕНЬ яркими, поэтому в большинстве примеров мы будем придерживаться низкой яркости (около 10), чтобы не перегружать ваши глаза!
Запустите пример кода ниже и попробуйте изменить число в ring[0] на другое значение (до 11):
# Imports
from machine import Pin
from neopixel import NeoPixel
# Define the ring pin number (2) and number of LEDs (12)
ring = NeoPixel(Pin(2), 12)
# Select the first LED (0)
# Set the RGB colour (red)
ring[0] = (10,0,0)
# Send the data to the ring
ring.write()
Если нужно выключить…
Если вы хотите выключить светодиоды на любом этапе, просто установите RGB-цвета в (0,0,0) для всего кольца с помощью ring.fill((0,0,0)), как в примере ниже.
Мы будем добавлять это в начало примеров программ, чтобы «сбрасывать» все светодиоды, оставшиеся включёнными после предыдущей программы:
from machine import Pin
from neopixel import NeoPixel
ring = NeoPixel(Pin(2), 12)
ring.fill((0,0,0)) # 'fill' addresses all LEDs
ring.write()
Активность 2: Несколько светодиодов
Зажечь несколько светодиодов тоже очень просто — просто добавьте ещё одну строку для каждого нужного светодиода.
В базовом примере ниже мы зажигаем светодиоды 1, 4, 7 и 10 синим цветом, что в нашем индексе, начинающемся с нуля, соответствует 0, 3, 6 и 9:
# Imports
from machine import Pin
from neopixel import NeoPixel
import time
# Define the ring pin number (2) and number of LEDs (12)
ring = NeoPixel(Pin(2), 12)
# Turn off all LEDs before program start
ring.fill((0,0,0))
ring.write()
time.sleep(1)
# Send data to four LEDs
ring[0] = (0,0,10)
ring[3] = (0,0,10)
ring[6] = (0,0,10)
ring[9] = (0,0,10)
ring.write()
…или используйте список!
Вы знаете, как работают списки — мы изучили их в день #4. Можно создать список конкретных светодиодов по индексу, которые хотим зажечь, а затем обращаться к этому списку в коде.
Пример ниже даёт тот же результат, что и предыдущий, но использует список и цикл for. Иногда один способ будет удобнее другого в зависимости от проекта/ситуации:
# Imports
from machine import Pin
from neopixel import NeoPixel
import time
# Define the ring pin number (2) and number of LEDs (12)
ring = NeoPixel(Pin(2), 12)
# Create a list of the LEDs to use
myleds = [0,3,6,9]
# Turn off all LEDs before program start
ring.fill((0,0,0))
ring.write()
time.sleep(1)
for i in myleds:
ring[i] = (0,0,10)
ring.write()
Активность 3: Небольшая задержка для эффектов
Простая короткая задержка может превратить ваш световой код из простого «включения» в целый паттерн!
Возьмём код выше в качестве примера — если добавить всего одну строку time.sleep(1) в конце кода внутри нашего цикла for, светодиоды будут зажигаться один за другим.
Это происходит потому, что цикл for выполняется для каждого элемента в нашем списке. Без задержки это происходит так быстро, что вы не замечаете и кажется, что они включаются все одновременно:
Попробуйте:
# Imports
from machine import Pin
from neopixel import NeoPixel
import time
# Define the ring pin number (2) and number of LEDs (12)
ring = NeoPixel(Pin(2), 12)
# Create a list of the LEDs to use
myleds = [0,3,6,9]
# Turn off all LEDs before program start
ring.fill((0,0,0))
ring.write()
time.sleep(1)
for i in myleds:
ring[i] = (0,0,10)
ring.write()
time.sleep(1)
Активность 4: Вращающиеся огни с циклом while
Что если добавить приведённый выше код в цикл while True, который работает бесконечно, немного уменьшить задержку и очищать кольцо после каждой итерации в цикле for?
Это создаст эффект светодиода, зажигающегося одного за другим в постоянном цикле! Каждый светодиод в списке горит столько времени, сколько задано задержкой, затем гасится, затем следующий делает то же самое — снова и снова (так как цикл while True перезапустит цикл for).
Вот код с дополнительными комментариями — попробуйте!
# Imports
from machine import Pin
from neopixel import NeoPixel
import time
# Define the strip pin number (2) and number of LEDs (12)
ring = NeoPixel(Pin(2), 12)
# Create a list of the LEDs to use
myleds = [0,3,6,9]
# Turn off all LEDs before program start
ring.fill((0,0,0))
ring.write()
time.sleep(1)
while True:
for i in myleds:
ring[i] = (0,0,10)
ring.write()
# Show the light for this long
time.sleep(0.3)
#Clear the ring at the end of each loop
ring.fill((0,0,0))
ring.write()
Активность 5: Отскакивающие огни
Вы уже несколько раз использовали метод reverse, но давайте применим его с кольцом — он помогает создавать действительно классные эффекты.
Наш свет будет отскакивать от одной стороны к другой, просто добавив второй цикл for с обратной последовательностью светодиодов.
Первый цикл for пройдёт по списку, поочерёдно зажигая каждый светодиод, затем после завершения цикла перейдёт к следующей части кода — нашему второму циклу for. Он практически идентичен, за исключением функции reversed, которая заставляет светодиоды работать в обратном порядке.
Так как всё это находится в цикле while True, свет будет продолжать отскакивать туда-обратно — круто! Попробуйте (мы также изменили цвет):
# Imports
from machine import Pin
from neopixel import NeoPixel
import time
# Define the strip pin number (2) and number of LEDs (12)
ring = NeoPixel(Pin(2), 12)
# Turn off all LEDs before program start
ring.fill((0,0,0))
ring.write()
time.sleep(1)
while True:
for i in range(12):
ring[i] = (5,0,5)
ring.write()
# Show the light for this long
time.sleep(0.09)
#Clear the ring at the end of each loop
ring.fill((0,0,0))
ring.write()
for i in reversed (range(12)):
ring[i] = (5,0,5)
ring.write()
# Show the light for this long
time.sleep(0.09)
#Clear the ring at the end of each loop
ring.fill((0,0,0))
ring.write()
Активность 6: Вращающееся колесо цвета!
Звучит уже интересно, правда?!
В этом примере используются те же концепции, что и выше, но мы оставляем светодиоды, непрерывно циклически вращающимися снова и снова, и каждый раз, когда доходим до первого светодиода, меняем цвет.
Мы используем метод random для цветов, потому что нам кажется, это веселее, чем заданный список. Мы также увеличили максимальную интенсивность RGB до 100 в этом примере, чтобы лучше показать цвета (до 255, если хотите!).
Код внутри цикла while сначала задаёт случайные числа (целые) для наших RGB-цветов (максимальный диапазон 100), затем переходит в цикл for, который поочерёдно зажигает светодиоды. Как только цикл for завершится, наш цикл while True начнёт всё заново.
Вот код:
# Imports
from machine import Pin
from neopixel import NeoPixel
import time
import random
# Define the strip pin number (2) and number of LEDs (12)
ring = NeoPixel(Pin(2), 12)
# Turn off all LEDs before program start
ring.fill((0,0,0))
ring.write()
time.sleep(1)
while True:
# Create random RGB values
r = random.randint(0,100)
g = random.randint(0,100)
b = random.randint(0,100)
for i in range(12):
# Light each LED a random colour
ring[i] = (r,g,b)
ring.write()
# Show the LED for this long
time.sleep(0.05)
#Clear the ring at the end of each loop
ring.fill((0,0,0))
ring.write()
…или полноцветная версия!
Вместо того чтобы один светодиод вращался по кругу, можно заполнить кольцо каждым цветом по очереди.
Всё, что нужно сделать — удалить последние три строки предыдущего примера. Попробуйте!
Если кольцо не очищается в конце каждого цикла, оно будет заполняться цветом. Легко!
Активность 7: Двойное случайное кольцо!
Ещё один аккуратный пример с небольшим количеством кода — программа, которая выбирает случайный светодиод из нашего кольца, отображает на нём случайный цвет, затем выбирает следующий и так далее. Если запустить это достаточно быстро — выглядит очень эффектно!
Лучшее в нём? Всё построено на знаниях и функциях, которые вы уже изучили — отлично для практики!
Наш цикл while использует функцию random для выбора светодиода из кольца по индексу (0-11), затем создаёт три случайные переменные RGB-цвета в диапазоне от 0 до 50.
Дальше мы просто подставляем эти переменные в обычный код управления светодиодным кольцом: ring[randomled] = (r,g,b). Попробуйте:
# Imports
from machine import Pin, ADC
from neopixel import NeoPixel
import time
import random
# Define the strip pin number (2) and number of LEDs (12)
ring = NeoPixel(Pin(2), 12)
# Turn off all LEDs before program start
ring.fill((0,0,0))
ring.write()
time.sleep(1)
while True:
# Select a random LED
randomled = random.randint(0,11)
# Create random RGB values
r = random.randint(0,50)
g = random.randint(0,50)
b = random.randint(0,50)
# Light the random LED in a random colour
ring[randomled] = (r,g,b)
ring.write()
# Show the light for this long
time.sleep(0.05)
#Clear the ring at the end of each loop
ring.fill((0,0,0))
ring.write()
День #8 завершён!
Уф! Много примеров, и с этими светодиодными кольцами можно сделать ещё гораздо больше в зависимости от того, насколько далеко вы захотите зайти в коде. Не стесняйтесь поднимать примеры до полной яркости RGB 255 для по-настоящему впечатляющего мигания!
Это был ещё один хороший день для повторного использования того, что вы уже выучили, и применения этого в новых, веселых направлениях. Мы ещё поработаем с нашими RGB-светодиодами до конца календаря.
Примечание
Мы не убрали слайдер из вчерашней коробки, так как думали, вам может захотеться попробовать написать для него код в качестве регулятора скорости, выбора цвета или… чего-то ещё! Все необходимые знания и примеры можно найти в статьях предыдущих коробок (или, может быть, мы покажем, как это сделать, в одной из будущих…)
Пришло время подвести итоги — что мы изучили сегодня?
Подключение RGB-кольца из светодиодов
Обращение к отдельным/нескольким адресуемым светодиодам в цепочке
Различные световые эффекты:
Простое адресование отдельных светодиодов
Преследующий свет (одиночный / полноцветный)
Вращающиеся огни
Отскакивающие огни
Случайные огни и цвета
Оставьте схему как есть — в начале завтрашней коробки мы дадим инструкции, что с ней делать. Скорее всего, вы захотите ещё поиграть с кольцом до тех пор…
До встречи утром!
Для создания схематических изображений разводки макетной платы использован `Fritzing <https://fritzing.org/>`_.