День #2: Подключаем светодиоды!
Сегодня день #2 адвент-календаря «Let it Glow»!
Вчера мы познакомились с Pico и изучили его основные возможности: посмотрели примеры кода и поработали со встроенным светодиодом. Сегодня мы пойдём дальше и перейдём к физическим компонентам — реальным вещам, которыми можно управлять с помощью кода, изученного за эти 12 дней!
Начнём с нарядного объёмного светодиода, который работает так же, как обычный LED — только в более красивом корпусе!
По мере прохождения календаря мы будем использовать всё более сложные компоненты, но простые светодиоды — это отличное начало.
Поехали!
Содержимое коробки #2
В этой коробке вы найдёте:
1x диффузный «объёмный» светодиод 15 мм
1x резистор
2x провода папа-папа (jumper wires)
Сегодняшние задания
Сегодня мы научимся собирать простую схему и программировать наш объёмный светодиод: зажигать его, заставлять мигать и многое другое.
Мы также освоим несколько новых приёмов в MicroPython, которые пополнят вашу копилку знаний.
Те, кто проходил наш 12-дневный календарь Codemas в прошлом году, уже знакомы со светодиодами — они традиционно используются при первых шагах в программировании. Именно поэтому в этот год мы включили диффузный/объёмный LED другого стиля, но не волнуйтесь: впереди много новых интересных компонентов!
Что такое светодиод?
Светодиод — это с**вето**д**иод (или LED — **L ight E mitting D iode). Эти компоненты излучают свет, когда через них проходит электрический ток.
Полярность светодиода
У стандартных светодиодов обычно два вывода разной длины, поскольку у них есть строгая полярность — это значит, что ток может течь только в одном направлении (при нарушении светодиод может выйти из строя!).
Когда выводы разной длины, длинный — это Анод (+), короткий — Катод (-). Ток всегда течёт от анода к катоду.
У нашего объёмного светодиода выводы одинаковой длины. Вместо этого мы ориентируемся по тексту на корпусе. Вывод со стороны, на которой написан текст, — это анод (+). Обязательно внимательно прочитайте инструкцию по подключению, чтобы не ошибиться.
Что такое резистор?
При работе со светодиодами и микроконтроллерами обычно требуется токоограничивающий резистор.
Резисторы ограничивают количество тока, проходящего через цепь. Это защищает светодиод от слишком высокого тока и не позволяет ему потреблять больше, чем могут безопасно обеспечить GPIO-пины Pico.
Не важно, с какой стороны от светодиода стоит резистор, главное — чтобы он присутствовал в цепи и ограничивал ток.
Мы любим сравнивать ток с водой в трубе. Представьте широкую трубу, по которой течёт вода от одного конца к другому, но в середине есть узкий участок (это наш резистор) — именно он определяет, сколько воды может пройти через всю систему.
Карта пинов Raspberry Pi Pico
Ниже представлена упрощённая карта пинов Pico (так называемая распиновка), которая поможет вам на следующих шагах и в оставшихся днях календаря.
Цифры в серых квадратах — это физические номера пинов, пронумерованные по порядку вокруг платы. Номера GPIO-пинов, которые мы используем в коде, выделены зелёным (или начинаются с «GP», если цвета неудобны). Вы также можете скачать полную PDF-версию по ссылке в оригинальной документации к Pico.
Сборка схемы
Сначала убедитесь, что Pico отключён от USB-кабеля. Это нужно делать всегда при сборке или изменении схемы. Затем возьмите провода, резистор и светодиод.
Макетные платы (Breadboard)
Компоненты мы будем подключать к макетным платам. Breadboard позволяет соединять компоненты и прототипировать схемы без пайки — с помощью проводов с контактами на концах, которые называются джамперами (jumper wires, или DuPont-провода).
На каждой из таких плат с обеих сторон есть два набора горизонтальных каналов (красный/синий). Все красные пины соединены между собой, все синие — тоже (но каждая красная/синяя шина не соединена с другой). Они используются как «шины»: синяя — для земли (GND), красная — для питания 3.3V.
Отверстия в центре соединены вертикальными дорожками: с каждой стороны от разделителя по 5 связанных пинов. Разделитель в середине не даёт двум половинам платы соединяться.
Схема подключения
Для начала посмотрите на изображение ниже, чтобы понять общую картину, и только потом приступайте.
Установите светодиод в верхнем левом секторе макетной платы. Из-за расстояния между выводами LED между его ножками должна оставаться одна пустая дорожка.
Вывод анода(+) (со стороны текста на корпусе) должен быть слева. Ваша плата должна выглядеть примерно так:
Теперь нужно добавить резистор, чтобы ограничить ток, который светодиод потребляет от GPIO-пина.
Установите резистор между левым выводом (анод +) и дорожкой ниже центрального разделителя — смотрите изображение ниже для ориентира:
Теперь возьмите два провода. Один провод соедините правый вывод с пином земли (GND) на вашем Pico — рекомендуем использовать физический пин 18, как на схеме ниже (при необходимости обращайтесь к распиновке Pico).
Второй провод соедините левый вывод с GPIO-пином — это позволит управлять светодиодом через код. Используйте GPIO14 (физический пин 19), как на схеме ниже.
Несколько советов
Цвет провода не важен — все работают одинаково. В идеале принято использовать чёрный для земли и красный для питания, но для простых проектов это не обязательно (и вы всегда обнаруживаете, что нужного цвета в запасах не хватает!).
Если светодиод не загорается при выполнении заданий ниже — немного пошевелите компоненты: макетные платы не идеальны, и иногда ножки резистора или светодиода не обеспечивают нужного контакта.
Всегда проверяйте схему перед включением питания.
Всё готово к программированию — подключите Pico обратно к USB-кабелю и начнём!
Задание 1: Зажигаем светодиод
Начнём с простого — просто проверим, что всё работает.
Мы повторим код, который запускали для встроенного светодиода Pico вчера. Принцип тот же: устанавливаем пин в HIGH (включено), только нужно изменить номер GPIO на наш новый светодиод вместо встроенного.
Примечание: если вы выключали компьютер после вчерашнего задания, вам, возможно, потребуется снова открыть Thonny и выбрать Run > Configure interpreter, чтобы обнаружить Pico. Иногда помогает простое нажатие красной кнопки «Stop».
Код
Вспомним, как работают эти строки кода: мы импортируем Pin из machine, чтобы работать с GPIO-пинами, затем указываем номер пина ( 14), устанавливаем его как выход и устанавливаем значение пина в 1 (HIGH). Мы также добавили строку print, чтобы видеть в окне Shell, что происходит.
Вот код — скопируйте его в Thonny и запустите обычным способом, нажав зелёную кнопку. Попробуйте установить значение 0, чтобы выключить светодиод:
from machine import Pin
blockLED = Pin(14, Pin.OUT)
blockLED.value(1)
print("Block LED on!")
Задание 2: Включаем оба светодиода
Мы умеем включать каждый светодиод по отдельности, меняя номер пина — это несложно. Но что, если нам нужно включить оба светодиода (встроенный в Pico и наш объёмный) одновременно?
Это легко добавить в код: нужно продублировать несколько строк и изменить ссылку на пин. Вы будете делать это постоянно, когда будете создавать более сложные проекты с несколькими компонентами.
Код
Посмотрите на пример ниже — мы использовали имя «green» для встроенного светодиода, настроив его на GPIO25, и добавили строку для его включения. Имя объёмного светодиода мы изменили на «red».
Скопируйте этот пример в Thonny и нажмите зелёную кнопку:
from machine import Pin
green = Pin(25, Pin.OUT)
red = Pin(14, Pin.OUT)
green.value(1)
red.value(1)
print("Both LEDs ON!")
Задание 3: Мигающий светодиод — основы
Переходим на следующий уровень — заставим наши светодиоды мигать, как настоящие праздничные украшения!
Для того чтобы LED мигал, нам нужно познакомиться с модулем time.
Модуль time
Модуль time позволяет программировать задержки в коде, заставляя его ожидать секунды или доли секунды перед продолжением. Это фундаментальный модуль, который вы будете использовать в большинстве проектов — задержки нужны очень часто.
Код
Мы будем дополнять код из задания 2.
Нам нужно импортировать модуль time, чтобы использовать его — теперь он добавлен в блок импорта на второй строке.
Чтобы сделать светодиод мигающим (включать и выключать с задержкой), мы добавляем time.sleep(1) после включения (держим светодиод включённым 1 секунду), затем выключаем его, изменив последнее число на 0, снова добавляем задержку и повторяем эту схему несколько раз.
Изучите пример ниже и попробуйте его сами — скопируйте в Thonny и нажмите зелёную кнопку:
from machine import Pin
import time
red = Pin(14, Pin.OUT)
red.value(1)
time.sleep(1)
red.value(0)
time.sleep(1)
red.value(1)
time.sleep(1)
red.value(0)
time.sleep(1)
Задание 4: Мигающий светодиод — используем циклы
Пример выше показывает основы мигания, но это не лучший способ достичь нужного результата — для длительного мигания потребовалось бы ОЧЕНЬ много строк кода!
Мы можем заставить код повторяться снова и снова с помощью цикла while. Давайте познакомимся с этими удобными циклами, а также рассмотрим отступы и комментарии к коду.
Цикл while
Циклы while используются для повторного выполнения блока кода, пока условие остаётся истинным.
Представьте, что вы едете на машине по гоночной трассе. Ваше условие — «проехать 5 кругов». После 5 кругов вы останавливаетесь.
Мы можем указать циклу while выполнять блок кода до тех пор, пока условие выполнено, или просто сделать его бесконечным, используя «while True» — это удобно для проектов, которые должны работать постоянно.
Для этого первого примера цикла мы сделаем его бесконечным (пока не остановим программу вручную), используя while True.
Комментарии в коде
Начиная с этого момента мы будем добавлять комментарии во все примеры кода.
Вы можете добавлять комментарии в код MicroPython, поставив # перед текстом. MicroPython будет игнорировать такие строки, так что вы можете писать что угодно.
Комментарии помогают объяснить код другим людям или напомнить себе детали, когда вы вернётесь к проекту. Мы также любим разделять с их помощью разные части: импорты, настройку пинов и т.д. Это очень полезная привычка, позволяющая чётко объяснять каждую строку по мере усложнения заданий.
Иногда мы будем _перебарщивать_ с комментариями, чтобы всё было предельно понятно _(это может считаться плохой практикой, но мы считаем, что лучше убедиться в полном понимании!)_.
Отступы в коде
Отступ — это пробел в начале строки кода, обычно символ табуляции или несколько пробелов.
В MicroPython отступы очень важны: они указывают Thonny, что строки принадлежат определённому блоку кода (в нашем примере ниже строки внутри цикла while имеют отступ, так как они входят в этот цикл).
Код
Код ниже сначала импортирует необходимые компоненты и настраивает пины, как мы делали раньше.
Теперь вместо того, чтобы сразу переходить к управлению светодиодом, мы запускаем цикл while и помещаем код внутрь него. Мы используем while True:, что запускает блок кода на бесконечное выполнение. Всё, что должно входить в этот цикл, нужно разместить ниже с отступом.
Наш код с отступом включает светодиод, ждёт полсекунды (используя 0.5), выключает светодиод и снова ждёт полсекунды. Поскольку это цикл while true, он вернётся к началу кода с отступом и запустит его снова и снова, пока мы его не остановим.
Обратите внимание на «чрезмерно подробные» комментарии. Их можно добавлять как на отдельных строках, так и после кода — мы использовали оба варианта, чтобы показать вам обе возможности.
Скопируйте этот код в Thonny и запустите обычным способом, нажав зелёную кнопку. Чтобы остановить программу, нажмите красную кнопку:
# Импорты
from machine import Pin
import time
# Настройка пинов
red = Pin(14, Pin.OUT) # Установить GPIO 14 как выход
## Начало программы ##
while True: # Цикл бесконечный
red.value(1) # Светодиод включён
time.sleep(0.5) # Ждём полсекунды
red.value(0) # Светодиод выключен
time.sleep(0.5) # Ждём полсекунды
Задание 5: Мигание заданное количество раз
Пример выше даёт нам «вечно» мигающий светодиод, но что, если нужно, чтобы он мигнул только определённое количество раз?
Это можно сделать несколькими способами, и в этот раз мы воспользуемся функцией range.
Функция range
Функция range очень удобна, когда нужно повторить что-то определённое число раз.
Предположим, мы хотим, чтобы светодиод мигнул десять раз. Конечно, можно написать десять пар строк включения/выключения, но это неэффективно и сложно поддерживать. К тому же, это занимает много строк — а это важно при работе с микроконтроллерами, у которых объём памяти ограничен.
Лучший способ — использовать range. Вот как это выглядит:
## Импорты ##
from machine import Pin
import time
## Настройка пинов ##
red = Pin(14, Pin.OUT) # Установить GPIO 14 как выход
## Начало программы ##
for i in range(10): # Выполнить код ниже 10 раз
red.value(1) # Светодиод включён
time.sleep(0.5) # Ждём полсекунды
red.value(0) # Светодиод выключен
time.sleep(0.5) # Ждём полсекунды
print("Программа завершена")
Не зацикливайтесь на том, почему используется именно «i» — попробуйте заменить его на «t» или «v» и посмотрите, что произойдёт: результат будет тем же! Традиционно используется «i», поэтому большинство программистов придерживаются этого. Считайте, что «i» означает iteration (итерация) или index (индекс) — тогда становится понятнее: «for каждой i*терации *in пределах range из 10»… Понятно?
Пока всё, что вам нужно знать — число в скобках (10) — это сколько раз будет выполнен код с отступом. Счёт начинается с нуля и продолжается столько раз, сколько указано в скобках (10). Мы ещё вернёмся к функции range, так что не переживайте, если сейчас она кажется сложной.
Скопируйте приведённый выше код в Thonny и попробуйте! Обратите внимание, что последняя строка print не имеет отступа. Это потому, что после завершения цикла range программа «выходит» из него и продолжает выполняться дальше.
День #2 завершён!
За сегодняшний день мы освоили очень много нового в программировании — всё это пригодится в следующих днях, где мы будем комбинировать эти функции и навыки, добавляя новые, для создания интересных проектов.
Это только второй день, поэтому не волнуйтесь, если вы не до конца уверены в том, что мы разобрали — мы будем возвращаться к этим темам с новыми примерами в предстоящих коробках.
Давайте подведём итог — что мы изучили сегодня?
Что такое светодиоды и резисторы
Аноды и катоды
Как работают макетные платы (breadboard)
Сборка схемы с LED
Программирование с несколькими компонентами/пинами
Модуль time
Циклы while
Комментарии в коде
Отступы в коде
Функция range
Сохраните свою схему до завтра (пока ничего не разбирайте), и увидимся после завтрака!
—
Для создания схем подключения использована программа Fritzing.