День #2: Подключаем светодиоды!

День 2 адвент-календаря Let it Glow — подключаем светодиоды

Сегодня день #2 адвент-календаря «Let it Glow»!

Вчера мы познакомились с Pico и изучили его основные возможности: посмотрели примеры кода и поработали со встроенным светодиодом. Сегодня мы пойдём дальше и перейдём к физическим компонентам — реальным вещам, которыми можно управлять с помощью кода, изученного за эти 12 дней!

Начнём с нарядного объёмного светодиода, который работает так же, как обычный LED — только в более красивом корпусе!

По мере прохождения календаря мы будем использовать всё более сложные компоненты, но простые светодиоды — это отличное начало.

Поехали!

Содержимое коробки #2

В этой коробке вы найдёте:

  • 1x диффузный «объёмный» светодиод 15 мм

  • 1x резистор

  • 2x провода папа-папа (jumper wires)

Содержимое коробки день 2

Сегодняшние задания

Сегодня мы научимся собирать простую схему и программировать наш объёмный светодиод: зажигать его, заставлять мигать и многое другое.

Мы также освоим несколько новых приёмов в MicroPython, которые пополнят вашу копилку знаний.

Те, кто проходил наш 12-дневный календарь Codemas в прошлом году, уже знакомы со светодиодами — они традиционно используются при первых шагах в программировании. Именно поэтому в этот год мы включили диффузный/объёмный LED другого стиля, но не волнуйтесь: впереди много новых интересных компонентов!

Что такое светодиод?

Светодиод — это с**вето**д**иод (или LED — **L ight E mitting D iode). Эти компоненты излучают свет, когда через них проходит электрический ток.

Полярность светодиода

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

Когда выводы разной длины, длинный — это Анод (+), короткий — Катод (-). Ток всегда течёт от анода к катоду.

У нашего объёмного светодиода выводы одинаковой длины. Вместо этого мы ориентируемся по тексту на корпусе. Вывод со стороны, на которой написан текст, — это анод (+). Обязательно внимательно прочитайте инструкцию по подключению, чтобы не ошибиться.

Полярность выводов объёмного светодиода

Что такое резистор?

При работе со светодиодами и микроконтроллерами обычно требуется токоограничивающий резистор.

Резисторы ограничивают количество тока, проходящего через цепь. Это защищает светодиод от слишком высокого тока и не позволяет ему потреблять больше, чем могут безопасно обеспечить GPIO-пины Pico.

Не важно, с какой стороны от светодиода стоит резистор, главное — чтобы он присутствовал в цепи и ограничивал ток.

Мы любим сравнивать ток с водой в трубе. Представьте широкую трубу, по которой течёт вода от одного конца к другому, но в середине есть узкий участок (это наш резистор) — именно он определяет, сколько воды может пройти через всю систему.

Карта пинов Raspberry Pi Pico

Ниже представлена упрощённая карта пинов Pico (так называемая распиновка), которая поможет вам на следующих шагах и в оставшихся днях календаря.

Цифры в серых квадратах — это физические номера пинов, пронумерованные по порядку вокруг платы. Номера GPIO-пинов, которые мы используем в коде, выделены зелёным (или начинаются с «GP», если цвета неудобны). Вы также можете скачать полную PDF-версию по ссылке в оригинальной документации к Pico.

Упрощённая распиновка Raspberry Pi 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.