MicroPython:Библиотеки/machine/Класс Signal
Класс Signal – управление и считывание данных с внешних I/O-устройств[1]
Класс Signal – это просто расширение класса Pin. В отличие от Pin, в котором могут быть только «абсолютные» единица или ноль, в объекте Signal, во-первых, может быть активный (вкл) или неактивный статус (выкл), а во-вторых, логика в нем может быть инвертированной (т.е. будет использоваться сигнал с активным нижнем уровнем) или обычной (сигнал с активным верхнем уровнем). Другими словами, классу Signal, помимо функционала Pin, добавлена логическая инверсия. На первый взгляд, это незначительное дополнение, но оно позволяет самым разным платам работать с большим диапазоном цифровых устройств, что является одной из главных целей проекта MicroPython. То есть независимо от того, каким светодиодом оснащено устройство (с активным нижним или верхним уровнем) и какое у него реле (нормально замкнутое или нормально разомкнутое) – вам всегда остаточно разработать всего одно приложение, которое будет работать во всех этих условиях, уделив различиям в аппаратных компонентах лишь пару строк в файле конфигурации своего приложения.
Пример:
from machine import Pin, Signal
# Предположим, к контакту 0 подключен светодиод,
# работающий по принципу активного верхнего уровня:
led1_pin = Pin(0, Pin.OUT)
# ... а к контакту 1 – светодиод,
# работающий по принципу активного нижнего уровня:
led2_pin = Pin(1, Pin.OUT)
# Чтобы зажечь оба этих светодиода при помощи класса «Pin»,
# нам нужно воспользоваться разными значениями:
led1_pin.value(1)
led2_pin.value(0)
# Но функционал класса «Signal» позволяет устранить различие
# между логиками активного верхнего и активного нижнего уровней:
led1 = Signal(led1_pin, invert=False)
led2 = Signal(led2_pin, invert=True)
# Теперь включение обоих светодиодов происходит одинаково:
led1.value(1)
led2.value(1)
# Или еще лучше:
led1.on()
led2.on()
Ниже небольшая памятка о том, когда нужно использовать Pin, а когда – Signal:
- Используйте Signal, если управляете простыми устройствами, работающими по принципу «вкл/выкл» (включая программную ШИМ), вроде светодиодов, многосегментных индикаторов, реле, зуммеров или простых бинарных датчиков вроде (нормально замкнутых и нормально разомкнутых) кнопок, притянутых к HIGH или LOW, герконов, датчиков огня/влаги и т.д. Другими словами, если вы работаете с физическим устройством/датчиком, которому требуется GPIO-доступ, то вам скорее всего понадобится Signal.
- Используйте Pin, если реализуете высокоуровневый протокол или шину для коммуникации с более сложными устройствами.
Различия между Signal и Pin обусловлены не только областями применения (см. выше), но и архитектурой MicroPython: Pin тратит меньше вычислительных ресурсов, что может быть полезно при работе с протоколами с bit-banging. Signal же добавляет функционалу Pin гибкости, но ценой чуть более высокой нагрузки на вычислительные ресурсы (которая все равно гораздо меньше, чем если бы вы вручную реализовали в Python различие между логиками активного верхнего и нижнего уровней!). Кроме того, Pin – это низкоуровневый объект, который нужно отдельно реализовывать для каждой платы, тогда как Signal – это высокоуровневый объект, и если Pin уже реализован, Signal реализовывать будет не нужно. Если сомневаетесь, просто дайте Signal шанс! Опять же, цель этого класса – просто избавить разработчиков от неинтересной необходимости устранять различия между логикой активного верхнего и нижней уровней, а также позволить другим пользователям просто делиться и спокойно пользоваться вашим приложением, а не кусать локти по той причине, что оно не работает лишь из-за того, что их светодиод или реле подключено немного по-другому.
Конструкторы
- Классы machine.Signal(pin_obj, invert=False) и machine.Signal(pin_arguments..., *, invert=False) – создают объект Signal. Есть два способа создать его:
- Обернув существующий объект Pin – это универсальный способ, который работает на всех платах.
- Передать необходимые аргументы объекта Pin напрямую в конструктор Signal, не создавая промежуточный объект Pin. Этот способ работает на многих, но не на всех платах.
Аргументы:
- pin_obj – существующий объект Pin.
- pin_arguments – те же аргументы, что можно передать конструктору Pin.
- invert – если здесь будет true, сигнал будет инвертирован (то есть будет использоваться сигнал с активным нижним уровнем).
Методы
- Signal.value([x]) – задает и считывает значение сигнала (в зависимости от того, задан ли аргумент x или нет).
Если аргумента не задано, то метод будет считывать значение сигнала. Если метод вернет значение «1», то это значит, что сигнал активен, а если «0», то неактивен. Если аргумент задан, то метод задаст значение сигнала. Значением в x может быть что угодно, что можно преобразовать в булево значение. Если это значение конвертируется в True, то сигнал активен, а если в False, то неактивен. Соответствие между этими активностью/неактивностью и логикой работы контакта зависит от того, инвертирована ли логика (то есть является ли она логикой активного нижнего уровня) или нет. Для обычной (без инверсии) логики активный статус будет соответствовать логической единице, а неактивный – логическому нулю. Для инвертированной логики (т.е. логики активного нижнего уровня) активный статус будет соответствовать логическому нулю, а неактивный – логической единице.
- Signal.on() – задает активный сигнал.
- Signal.off() – задает неактивный сигнал.