Перейти к содержанию
Своя световая анимация и звуки для ODNFC Выбрать ODNFC

Своя световая анимация и звуки для ODNFC

Как изменить световую и звуковую индикацию ODNFC: эффекты для встроенных светодиодов и адресной RGB-ленты, мелодии RTTTL и готовый набор одноголосных фрагментов.

В ODNFC можно заменить стандартные сигналы запуска, успешного чтения и ошибки: задать свои цвета, собрать анимацию из отдельных кадров и проиграть мелодию через встроенный звуковой излучатель. Для исполнения с адресными RGB-светодиодами вместо штатной подсветки можно подключить совместимую ленту.

Примеры ниже написаны для прошивки Lua и используют аппаратные настройки конкретной модели по умолчанию. Поэтому в коде не нужно указывать разные GPIO для ODNFC-LAN и ODNFC-RS485.

ИсполнениеЧто можно изменить
ODNFC на Lua с адресными RGB-светодиодамиЦвет, анимацию отдельных светодиодов, стандартные эффекты и мелодии
ODNFC-LAN-C на LuaПоследовательности красного и зелёного сигналов, стандартные эффекты и мелодии
ODNFC с контактами GND, OUT, +5 для подсветкиМожно заменить штатные адресные светодиоды RGB-лентой
Ранее выпущенные ODNFC на MicroPythonСветом и звуком управляет API установленной ветки MicroPython; примеры Lua напрямую не подходят
Пример RGB-анимации на ODNFC с адресными светодиодами. Цвета и последовательность кадров задаёт программа на Lua. Открыть видео отдельно.

Начните со стандартных сигналов

Класс indication.Leds сам выбирает RGB-индикатор или пару «красный-зелёный», настроенную в прошивке устройства. indication.Sound подключает встроенный звуковой излучатель.

local leds = indication.Leds.new()
local speaker = indication.Sound.new()

leds:start()
speaker:start()

-- Успешное чтение
leds:ok()
speaker:ok()

-- Отказ или ошибка
leds:err()
speaker:err()

Методы start(), ok() и err() синхронные: программа продолжит работу после завершения эффекта или мелодии. Это удобно для короткого подтверждения. Длинную анимацию или музыкальный фрагмент запускайте в отдельном потоке, если в это время основной цикл должен продолжать опрос карты и сети.

Замените стандартный эффект своим

Метод отдельного объекта можно заменить Lua-функцией. Следующий вариант показывает зелёный импульс на RGB-моделях и два коротких зелёных сигнала на ODNFC-LAN-C. Поле leds есть у RGB-индикатора, а gled — у двухцветного.

local sleepms = thread.sleepms
local leds = indication.Leds.new()

leds.ok = function(self)
    if self.leds then
        -- Плавно увеличить и уменьшить яркость зелёного.
        for level = 16, 128, 16 do
            self:set(0, level, 12)
            sleepms(25)
        end
        for level = 128, 0, -16 do
            self:set(0, level, 12)
            sleepms(25)
        end
        self:clear()
    else
        -- В ODNFC-LAN-C доступны только красный и зелёный.
        self:one(self.gled, 120)
        sleepms(70)
        self:one(self.gled, 120)
    end
end

leds:ok()

-- Восстановить встроенный вариант:
leds.ok = nil

Так же можно переопределить start(), err() или siren(). Изменение действует только на созданный объект и не перепрошивает системную библиотеку.

Соберите анимацию для RGB-ленты

У адресной ленты каждый светодиод — отдельный пиксель с компонентами красного, зелёного и синего от 0 до 255. В следующем примере один яркий пиксель и более тёмный «хвост» проходят по 16 светодиодам:

local sleepms = thread.sleepms
local pixels = 16

-- Используются штатные линия данных и тип светодиодов ODNFC.
local strip = indication.RGBLeds.new { ledCnt = pixels }

for position = 0, pixels - 1 do
    strip:clear()

    if position > 0 then
        strip:one(position - 1, 0, 16, 48)
    end
    strip:one(position, 0, 80, 255)

    sleepms(50)
end

strip:clear()

Создавайте один объект управления светодиодами: два объекта не должны одновременно занимать одну линию данных. Если меняете число пикселей, замените обычный indication.Leds.new() на indication.RGBLeds.new { ledCnt = ... }, а не создавайте оба объекта.

Для буферизованной отрисовки сложных кадров есть низкоуровневый модуль neopixel. Он умеет менять яркость, сдвигать пиксели, строить градиенты и преобразовывать HSV в RGB. При прямом вызове neopixel.attach() нужно указать GPIO конкретной модели, поэтому для переносимого между ODNFC кода удобнее начинать с indication.RGBLeds.

Подключение и питание ленты

Ленту можно подключить только к исполнению ODNFC с отдельной группой контактов GND, OUT, +5 для адресной подсветки:

  • +5 — питание ленты от внутреннего преобразователя;
  • OUT — линия данных, её подключают к DIN первого светодиода;
  • GND — общий провод.

Контакт OUT в этой группе — линия данных, а не силовой выход управления замком. Учитывайте направление данных на ленте и заранее рассчитайте ток по паспорту её светодиодов. Если нужен отдельный источник 5 В, объедините его землю с GND ODNFC, но не соединяйте параллельно его +5 В и выход питания считывателя.

Схема, расчёт тока и порядок проверки приведены в руководстве по подключению RGB-ленты.

Запишите мелодию телефонным кодом RTTTL

ODNFC понимает RTTTL — текстовый формат мелодий, который применялся для рингтонов кнопочных телефонов. В строке RTTTL записываются ноты, их длительность, октава и темп.

name:d=duration,o=octave,b=bpm:notes

Например:

local speaker = indication.Sound.new()

speaker:playrtttl("signal:d=8,o=4,b=96:e,g,4c5,p,g,4e")

Строка состоит из трёх частей:

  1. signal — имя мелодии. Оно помогает различать строки, но не влияет на звук.
  2. d=8,o=4,b=96 — длительность ноты по умолчанию, четвёртая октава и темп 96 ударов в минуту.
  3. e,g,4c5,p,g,4e — ноты через запятую.

В списке нот используются:

  • c, d, e, f, g, a, b — до, ре, ми, фа, соль, ля и си;
  • # и b после буквы — диез и бемоль, например f# и eb;
  • число перед нотой — её длительность: 4e означает четвертную ми, 16e — шестнадцатую;
  • число после ноты — октаву: c5;
  • p — паузу;
  • точка после ноты — длительность в полтора раза больше: e..

Допустимые длительности — 1, 2, 4, 8, 16, 32 и 64. Темп задаётся параметром b внутри каждой RTTTL-строки. Второй аргумент indication.Sound.new(pin, tempo) относится к старому способу проигрывания нот и не меняет скорость RTTTL-мелодии.

Встроенный излучатель — одноголосный генератор: он играет только одну ноту за раз, без аккордов, инструментальных тембров и отдельных дорожек. Начинайте с октав 3–4. Если звук кажется резким, перенесите все ноты на октаву ниже, сохранив интервалы между ними. Затем подберите b на самом считывателе: темп и восприятие высоты зависят от длины фрагмента и установленного излучателя.

Полное описание синтаксиса есть в документации модуля Sound.

19 RTTTL-фрагментов для проверки

Ниже — 14 узнаваемых мелодий и пять коротких музыкальных заготовок. Копируйте одну RTTTL-строку целиком и проверяйте её на считывателе. Все фрагменты одноголосные. Большинство нот находится в третьей и четвёртой октавах, самая высокая нота набора — d5. Используйте эти фрагменты для проверки темпа и высоты звука. Для повседневной индикации подберите короткие, различимые сигналы успеха, отказа и ожидания.

«К Элизе» — Людвиг ван Бетховен

fur_elise:d=16,o=4,b=72:e,d#,e,d#,e,b3,d,c,8a3,p,c3,e3,a3,8b3,p,e3,g#3,b3,8c,p

«Ода к радости» — Людвиг ван Бетховен

ode_to_joy:d=8,o=4,b=105:e,e,f,g,g,f,e,d,c,c,d,e,e.,16d,4d

«Мерцай, звезда» — традиционная мелодия

twinkle:d=8,o=4,b=100:c,c,g,g,a,a,4g,f,f,e,e,d,d,4c

«У Мэри был барашек» — детская мелодия

mary_lamb:d=8,o=4,b=105:e,d,c,d,e,e,4e,d,d,4d,e,g,4g

«Jingle Bells» — Джеймс Лорд Пирпонт

jingle_bells:d=8,o=4,b=115:e,e,4e,e,e,4e,e,g,c,d,2e

«Братец Жак» — традиционная мелодия

frere:d=8,o=4,b=105:c,d,e,c,c,d,e,c,e,f,4g,e,f,4g,16g,16a,16g,16f,e,c,16g,16a,16g,16f,e,c,c,g3,4c,c,g3,4c

«Лондонский мост» — традиционная мелодия

london_bridge:d=8,o=4,b=105:g,a,g,f,e,f,g,4d,e,f,4e,f,g,4g,g,a,g,f,e,f,g,4d,4g,e,c,4c

«Греби, греби, греби» — традиционная мелодия

rowboat:d=8,o=4,b=95:c.,16c,c.,16d,e.,16e,4e,d.,16e,f,e,d,c.,16c,4c,g,4c,c,4c,c,8c,16d,16e,16f,16g,2g

«Старый Макдональд» — традиционная мелодия

old_mac:d=8,o=4,b=110:c,c,c,g3,a3,a3,4g3,e,e,d,d,4c,g3,c,c,c,g3,a3,a3,4g3,e,e,d,d,2c

Тема Пятой симфонии — Людвиг ван Бетховен

fifth:d=16,o=4,b=96:g,g,g,4eb,8p,f,f,f,4d,8p,g,g,g,4eb,8p,g#,g#,g#,4g

Менуэт соль мажор — Кристиан Петцольд

minuet:d=8,o=4,b=96:d,g,a,b,c5,4d5,g,4g,e,c5,b,a,4b,g,f#,g,a,4d3,e,f#,g,4a,f#,g,a,b,4c5,b,a,g,f#,4g

«Маленькая ночная серенада» — Вольфганг Амадей Моцарт

nacht:d=8,o=3,b=115:g,4d4,g,4d4,g,d4,b,d4,4g4,8p,f#,4d4,f#,4d4,f#,d4,a,d4,4f#4

«Зелёные рукава» — традиционная мелодия

greensleeves:d=8,o=4,b=82:a3,c,d,4e.,f,e,d,4b3,g3,a3,4b3.,c,b3,a3,4g#3

«Скарборо-Фэйр» — традиционная мелодия

scarborough:d=8,o=4,b=88:a3,a3,e,e,b3,c,b3,4a3,e,g,a,4g,e,f,e,4d,c,b3,4a3

Мажорная гамма

major_scale:d=8,o=4,b=125:c,d,e,f,g,a,b,c5,p,c5,b,a,g,f,e,d,c

Минорное арпеджио

minor_arp:d=8,o=4,b=115:a3,c,e,a,c5,a,e,c,4a3

Низкий блюзовый ход

low_blues:d=8,o=4,b=105:c,eb,f,f#,g,bb,c5,bb,g,f#,f,eb,4c

Короткий вальс

low_waltz:d=8,o=3,b=96:c,e,g,4c4,g,e,d,f,a,4d4,a,f,e,g,b,4e4,b,g

Короткая фанфара

low_fanfare:d=16,o=4,b=120:c,g3,c,e,g,8c5,16p,g3,d,g,b,8d5,16p,4c5

Как проиграть выбранную строку

Вставьте одну строку из списка в переменную rtttl:

local speaker = indication.Sound.new()

local rtttl = "fur_elise:d=16,o=4,b=72:e,d#,e,d#,e,b3,d,c,8a3,p,c3,e3,a3,8b3,p,e3,g#3,b3,8c,p"
speaker:playrtttl(rtttl)

После завершения фрагмента замените значение rtttl следующей строкой и запустите код ещё раз. Не запускайте две проверки одновременно: все мелодии используют один встроенный излучатель.