Let it Glow Адвент-календарь День #5: Переключи DIP!
Сегодня день #5 адвент-календаря Let it Glow!
Сегодня мы используем новый управляющий компонент — то, с чем мы или окружающая среда можем взаимодействовать, чтобы запускать наш код, который затем заставляет светодиоды и другие мигающие элементы светиться.
Забавный красный блок в сегодняшней коробке — это 5-позиционный DIP ( D ual I nline P ackage) переключатель. Похожий на столбиковый индикатор из вчерашней коробки, этот компактный компонент — как пять переключателей ВКЛ/ВЫКЛ в одном крошечном корпусе.
Мы можем использовать их с нашими GPIO-пинами, чтобы выбирать, какая часть программы выполняется, включая цвет, скорость и другие параметры. Или использовать их в самом простом виде — как обычный разрыв в цепи.
Приступим!
Содержимое коробки #5
В этой коробке вы найдёте:
1x 5-позиционный DIP-переключатель
5x провода «папа–папа»
Задания дня
Сегодня мы научимся работать с этим DIP-переключателем, включая его подключение к GPIO-пинам.
Мы используем пять крошечных переключателей, чтобы переводить разные GPIO-пины в HIGH и LOW, и покажем, как запускать код в зависимости от положения нескольких переключателей.
Но сначала расскажем немного подробнее о сегодняшнем компоненте…
Как работает DIP-переключатель?
Как и большинство простых переключателей, этот DIP-переключатель работает, замыкая или размыкая соединение — однако в нём сразу пять таких соединений.
DIP-переключатель имеет десять ножек, по пять с каждой стороны. Они выполнены в форме Dual-Inline Package (DIP), что позволяет использовать его на макетной плате с ножками по обеим сторонам центрального разрыва — отлично подходит для прототипирования, особенно когда нужно много переключателей, а места на макетной плате мало!
Каждый рычажок переключателя имеет ножку с каждой стороны. Когда вы включаете переключатель, он соединяет эти две ножки — всё просто.
Хотя кнопки из коробки #3 были моментальными (замыкают цепь только в момент нажатия), эти переключатели имеют маленькие рычажки, которые фиксируют состояние ВКЛ или ВЫКЛ (как выключатель света) и остаются в этом положении.
Сборка схемы
Как всегда, убедитесь, что Pico отключён от USB-кабеля перед работой со схемой.
Подготовка макетной платы
Начальная точка для нашей макетной платы — то состояние, в котором мы её оставили вчера, но мы уберём две кнопки и их провода, а красный провод питания 3.3В оставим на месте.
Если нужно что-то пересобрать, вернитесь к инструкциям предыдущих дней и приведите схему в нужное состояние.
Ваша начальная точка должна выглядеть так:
Установка DIP-переключателя и проводов GPIO
Мы установим DIP-переключатель туда, где раньше были кнопки.
Осторожно вставьте его в крайний правый набор отверстий, чтобы середина переключателя находилась над центральным разрывом. Ножки этих переключателей не такие толстые, как у некоторых других компонентов, поэтому не применяйте чрезмерную силу.
Затем подключим нижние ножки к нашим GPIO-пинам. Всего пять пронумерованных переключателей, поэтому используем следующие пины для каждого (сверьтесь с картой выводов Pico):
Переключатель 1 = GPIO6 (физический пин 9)
Переключатель 2 = GPIO5 (физический пин 7)
Переключатель 3 = GPIO4 (физический пин 6)
Переключатель 4 = GPIO3 (физический пин 5)
Переключатель 5 = GPIO2 (физический пин 4)
Примечание: на схемах ниже показан синий DIP-переключатель, но в вашей коробке будет красный.
Подключение пинов 3.3В
Все верхние ножки DIP-переключателя будут подключены к пину 3.3В, так как именно это установит наши GPIO-пины в HIGH при включении переключателей.
Верхний красный рельс уже должен быть подключён к 3.3В, поэтому теперь нужно только соединить каждую из верхних ножек с этим рельсом. Используйте свободные провода из предыдущих коробок, которые сейчас не задействованы:
Запутались в проводах?
Поздравляем, это ваше первое «птичье гнездо»! Именно так мы, мейкеры, называем много проводов, сбившихся в кучу. Этого бывает сложно избежать в насыщенных проектах.
На нашей макетной плате теперь очень много проводов, поэтому последнее, что вы, возможно, захотите сделать — немного поправить кабели, чтобы они не мешали DIP-переключателю, так как нам нужно будет им пользоваться в ходе заданий.
Задание 1: Тест включения DIP-переключателя
Наша первая тестовая программа проверит правильность подключений. Запустим небольшую программу, которая каждые пять секунд выводит информацию о том, какие переключатели включены.
Здесь используется всё, что вы уже изучили: входы, подтяжка к земле, операторы if и вывод данных. Скопируйте код и попробуйте — меняйте положения переключателей.
Это может быть непросто нашими толстыми человеческими пальцами, поэтому придерживая корпус переключателя одной рукой, используйте зубочистку, деревянную шпажку или похожий острый, но не опасный предмет, чтобы менять положения переключателей (желательно не металлический!).
Если некоторые переключатели не реагируют при изменении положения рычажка, скорее всего, провод отошёл или подключён неправильно:
from machine import Pin
import time
# Set up switch input pins
dip1 = Pin(6, Pin.IN, Pin.PULL_DOWN)
dip2 = Pin(5, Pin.IN, Pin.PULL_DOWN)
dip3 = Pin(4, Pin.IN, Pin.PULL_DOWN)
dip4 = Pin(3, Pin.IN, Pin.PULL_DOWN)
dip5 = Pin(2, Pin.IN, Pin.PULL_DOWN)
while True:
if dip1.value() == 1:
print("Switch 1: ON")
if dip2.value() == 1:
print("Switch 2: ON")
if dip3.value() == 1:
print("Switch 3: ON")
if dip4.value() == 1:
print("Switch 4: ON")
if dip5.value() == 1:
print("Switch 5: ON")
print("-------------") # Print a divider
time.sleep(5) # 5 second delay
Задание #2: Тест DIP-переключателя «ВКЛ или ВЫКЛ»
Приведённый выше тестовый скрипт справляется с задачей, но неудобно, что строки просто исчезают, если переключатель выключен.
Мы можем сделать вывод тестовой программы более полезным, просто добавив операторы else после каждого оператора if, чтобы программа выводила что-то другое, если переключатель не включён.
Попробуйте эту обновлённую версию кода. Вы уже изучили операторы else вчера, поэтому всё должно быть понятно.
Примечание: возможно, есть более эффективные (с точки зрения кода) способы добиться того же результата, но мы стараемся сохранять всё максимально простым и понятным, пока продолжаем учиться.
from machine import Pin
import time
# Set up switch input pins
dip1 = Pin(6, Pin.IN, Pin.PULL_DOWN)
dip2 = Pin(5, Pin.IN, Pin.PULL_DOWN)
dip3 = Pin(4, Pin.IN, Pin.PULL_DOWN)
dip4 = Pin(3, Pin.IN, Pin.PULL_DOWN)
dip5 = Pin(2, Pin.IN, Pin.PULL_DOWN)
while True:
# Switch 1
if dip1.value() == 1:
print("Switch 1: ON")
else:
print("Switch 1: OFF")
# Switch 2
if dip2.value() == 1:
print("Switch 2: ON")
else:
print("Switch 2: OFF")
# Switch 3
if dip3.value() == 1:
print("Switch 3: ON")
else:
print("Switch 3: OFF")
# Switch 4
if dip4.value() == 1:
print("Switch 4: ON")
else:
print("Switch 4: OFF")
# Switch 5
if dip5.value() == 1:
print("Switch 5: ON")
else:
print("Switch 5: OFF")
# For each loop...
print("-------------") # Print a divider
time.sleep(5) # 5 second delay
Задание #3: Тест «ВКЛ или ВЫКЛ» — со светодиодами
Давайте вернём в код столбиковый индикатор, чтобы зажигать светодиод на дисплее для каждого переключателя, установленного в положение ВКЛ.
Нам нужно вернуть в программу блок настройки пинов светодиодов, а затем устанавливать каждый сегмент светодиода в HIGH (1) или LOW (0) внутри каждого оператора if.
Вы уже знакомы со светодиодами и значениями HIGH/LOW, поэтому ничего пугающего здесь нет. Мы также убрали строки с print, так как теперь используем светодиоды для обратной связи о состоянии переключателей (при желании можете вернуть их!).
Попробуйте код ниже и убедитесь сами:
from machine import Pin
import time
# Set up switch input pins
dip1 = Pin(6, Pin.IN, Pin.PULL_DOWN)
dip2 = Pin(5, Pin.IN, Pin.PULL_DOWN)
dip3 = Pin(4, Pin.IN, Pin.PULL_DOWN)
dip4 = Pin(3, Pin.IN, Pin.PULL_DOWN)
dip5 = Pin(2, Pin.IN, Pin.PULL_DOWN)
# Set up LED pins
seg1 = Pin(13, Pin.OUT)
seg2 = Pin(12, Pin.OUT)
seg3 = Pin(11, Pin.OUT)
seg4 = Pin(10, Pin.OUT)
seg5 = Pin(9, Pin.OUT)
while True:
# Switch 1
if dip1.value() == 1:
seg1.value(1)
else:
seg1.value(0)
# Switch 2
if dip2.value() == 1:
seg2.value(1)
else:
seg2.value(0)
# Switch 3
if dip3.value() == 1:
seg3.value(1)
else:
seg3.value(0)
# Switch 4
if dip4.value() == 1:
seg4.value(1)
else:
seg4.value(0)
# Switch 5
if dip5.value() == 1:
seg5.value(1)
else:
seg5.value(0)
# For each loop...
time.sleep(0.5) # half second delay
Задание #4: Выбор программы с помощью DIP-переключателя
Мы используем наш DIP-переключатель, чтобы выбирать программу световых паттернов для запуска на столбиковом индикаторе.
Наш код будет содержать отдельные блоки кода, которые заставляют дисплей показывать разные паттерны. Какой световой паттерн отображается — зависит от положения переключателей на DIP-переключателе.
Для этого мы создадим собственные функции, поэтому сначала объясним, что это такое…
Что такое функции?
Функции — это блоки кода, которые вы создаёте и можете вызвать (использовать) в любой момент вашей программы. Они отлично подходят для таких проектов, как этот, где мы хотим позволить программе выбирать, какой паттерн (блок кода) запускать.
Мы также можем использовать функции для запуска повторяющихся блоков кода и уменьшения размера и сложности наших программ, но к этому мы вернёмся в другом задании.
Давайте объясним, как работают функции, прежде чем продолжим…
Написание функции
Ниже приведён пример простой функции, которая выводит 3 строки. Мы создаём функцию, записывая „def“ с последующим пробелом и именем, которое хотим дать нашей функции (пробелы в имени функции не допускаются).
Мы назвали нашу „myfunction1“. Затем добавляем круглые скобки (parentheses) в конце, которые могут включать любые аргументы, если требуется (в этом примере мы не используем ни одного), и двоеточие (:).
Отступы снова важны здесь — всё, что находится под строкой „def“, должно иметь отступ, чтобы обозначить принадлежность к функции:
def myfunction1():
print("This")
print("is a")
print("function")
Использование функций
Итак, теперь, когда у нас есть функция, как её использовать?
Мы можем вызвать (использовать) функцию, просто написав имя функции с круглыми скобками, вот так:
myfunction1()
Для нашего проекта с DIP-переключателем мы можем создать несколько функций с разным кодом (световыми паттернами) и использовать DIP-переключатель с операторами if, чтобы сообщать программе, какую из них запускать.
Ограничение операторов if
Цель этой конкретной программы — всегда запускать только один из наших световых паттернов в цикле. Мы не хотим, чтобы она последовательно запускала несколько операторов if (световых паттернов) один за другим, как наш тестовый код выше.
В примере ниже используются операторы if для проверки, включён ли один из первых двух переключателей. Если первый переключатель включён, будет выполнена функция, которую мы разместили под этим конкретным оператором.
Он не будет продолжать проверять другой оператор в этом цикле, потому что мы использовали оператор elif для этого. Да, это ещё одна новинка! Давайте быстро разберём elif…
Оператор elif
Оператор elif — это сокращение от „else if“. Если ваш первый оператор if не выполняется, ваш код проверит каждый оператор elif по порядку, чтобы увидеть, выполняется ли какой-либо из них.
Однако если один из операторов elif срабатывает, он выполнит блок кода только для этого оператора и затем прекратит проверку остальных (в отличие от обычных операторов if, которые продолжают проверку каждого последующего независимо от того, что происходит).
Это полезно для нашей программы, потому что мы хотим, чтобы она возвращалась к началу цикла после срабатывания оператора if. Это также означает, что если оба переключателя включены, всегда будет выполняться первый.
Код
Пример ниже включает всё, что мы только что рассмотрели. Мы настроили номера пинов столбикового индикатора и создали для них список, как делали это вчера. Затем мы определяем наши две функции program1 и program2, каждая из которых содержит световую последовательность — мы повторно используем последовательность сканирования светодиодов из вчерашнего дня для простоты.
Затем начинается наш цикл while, который проверяет состояние кнопки и запускает функцию для этой кнопки, если она установлена в ВКЛ. Вторая кнопка использует оператор elif, поэтому она не выполнится, если первая кнопка включена.
Скопируйте код ниже в Thonny и попробуйте!
from machine import Pin
import time
# Set up switch input pins
dip1 = Pin(6, Pin.IN, Pin.PULL_DOWN)
dip2 = Pin(5, Pin.IN, Pin.PULL_DOWN)
dip3 = Pin(4, Pin.IN, Pin.PULL_DOWN)
dip4 = Pin(3, Pin.IN, Pin.PULL_DOWN)
dip5 = Pin(2, Pin.IN, Pin.PULL_DOWN)
# Set up LED pins
seg1 = Pin(13, Pin.OUT)
seg2 = Pin(12, Pin.OUT)
seg3 = Pin(11, Pin.OUT)
seg4 = Pin(10, Pin.OUT)
seg5 = Pin(9, Pin.OUT)
# Create a list of our LEDs
segments = [seg1, seg2, seg3, seg4, seg5]
# Create our first function
def program1():
for led in segments:
led.value(1)
time.sleep(0.1)
led.value(0)
# Create our second function
def program2():
for led in reversed (segments):
led.value(1)
time.sleep(0.1)
led.value(0)
# Start the main program loop
while True:
# Switch 1
if dip1.value() == 1:
print("Program #1 running...")
program1()
# Switch 2
elif dip2.value() == 1:
print("Program #2 running...")
program2()
Задание #5: Проверка нескольких положений DIP-переключателя
Мы можем внести несколько небольших изменений в наш код, чтобы программа показывала определённую последовательность только в том случае, если установлено несколько переключателей в положение ВКЛ.
Для этого мы можем использовать and или or в наших операторах if. Давайте сразу перейдём к примеру, так как они очень понятны.
Использование „and“ в операторах if
Ниже — изменённая версия нашего последнего примера кода. Мы изменили его так, что program1 запускается только если переключатели 1 и 2 включены, а program2 — только если переключатели 3 и 4 включены.
Всё, что нам нужно — использовать and между двумя условиями, проверяя переключатели 1 и 2 одновременно, вот так:
if dip1.value() == 1 and dip2.value() == 1:
Вот изменённая версия — скопируйте её в Thonny и попробуйте:
from machine import Pin
import time
# Set up switch input pins
dip1 = Pin(6, Pin.IN, Pin.PULL_DOWN)
dip2 = Pin(5, Pin.IN, Pin.PULL_DOWN)
dip3 = Pin(4, Pin.IN, Pin.PULL_DOWN)
dip4 = Pin(3, Pin.IN, Pin.PULL_DOWN)
dip5 = Pin(2, Pin.IN, Pin.PULL_DOWN)
# Set up LED pins
seg1 = Pin(13, Pin.OUT)
seg2 = Pin(12, Pin.OUT)
seg3 = Pin(11, Pin.OUT)
seg4 = Pin(10, Pin.OUT)
seg5 = Pin(9, Pin.OUT)
# Create a list of our LEDs
segments = [seg1, seg2, seg3, seg4, seg5]
# Create our first function
def program1():
for led in segments:
led.value(1)
time.sleep(0.1)
led.value(0)
# Create our second function
def program2():
for led in reversed (segments):
led.value(1)
time.sleep(0.1)
led.value(0)
# Start the main program loop
while True:
# Switch 1
if dip1.value() == 1 and dip2.value() == 1:
print("Program #1 running...")
program1()
# Switch 2
elif dip3.value() == 1 and dip4.value() == 1:
print("Program #2 running...")
program2()
Использование „or“ в операторах if
Аналогично описанному выше, мы можем просто заменить and на or, чтобы указать нашему коду проверять, включён ли один из переключателей, а не оба одновременно, вот так:
if dip1.value() == 1 or dip2.value() == 1:
Вот изменённая версия — скопируйте её в Thonny и попробуйте:
from machine import Pin
import time
# Set up switch input pins
dip1 = Pin(6, Pin.IN, Pin.PULL_DOWN)
dip2 = Pin(5, Pin.IN, Pin.PULL_DOWN)
dip3 = Pin(4, Pin.IN, Pin.PULL_DOWN)
dip4 = Pin(3, Pin.IN, Pin.PULL_DOWN)
dip5 = Pin(2, Pin.IN, Pin.PULL_DOWN)
# Set up LED pins
seg1 = Pin(13, Pin.OUT)
seg2 = Pin(12, Pin.OUT)
seg3 = Pin(11, Pin.OUT)
seg4 = Pin(10, Pin.OUT)
seg5 = Pin(9, Pin.OUT)
# Create a list of our LEDs
segments = [seg1, seg2, seg3, seg4, seg5]
# Create our first function
def program1():
for led in segments:
led.value(1)
time.sleep(0.1)
led.value(0)
# Create our second function
def program2():
for led in reversed (segments):
led.value(1)
time.sleep(0.1)
led.value(0)
# Start the main program loop
while True:
# Switch 1
if dip1.value() == 1 or dip2.value() == 1:
print("Program #1 running...")
program1()
# Switch 2
elif dip3.value() == 1 or dip4.value() == 1:
print("Program #2 running...")
program2()
День #5 завершён!
Теперь в нашем арсенале есть несколько новых трюков для управления и запуска программ с помощью переключателей — очень удобно, когда вы начнёте проектировать собственные проекты и вам понадобится физический интерфейс и управление.
Возможность управлять завершённой программой/проектом с помощью кнопок и переключателей удобна, но использование функций для выбора какую программу запускать открывает множество возможностей.
Вы даже можете использовать положения переключателей как код доступа для запуска программы… о, возможности!
Итоги дня — ещё одна похвала себе, потому что сегодня мы:
Узнали о DIP-переключателях (и разнице между ними и «моментальными» кнопками)
Собрали схему с DIP-переключателем
Узнали о функциях
Расширили знания об операторах if:
elif операторы
and и or
Сегодня был ещё один «управляющий» компонент, а значит, завтра нас ждёт мигающий день. Что же это будет…? Пока оставьте схему как есть — утром мы расскажем, что оставить, а что убрать.
До встречи после хорошего отдыха, друзья!
—
Для создания схем подключения на макетной плате использовался `Fritzing <https://fritzing.org/>`_.