
Все знают Arduino, Raspberry Pi, ну или Flipper на худой конец. Это экосистемы вокруг аппаратных платформ. Мой светильник из прошлой статьи тоже в некоем роде аппаратная платформа. И я решил тоже сделать вокруг него экосистему.
Экосистему я назвал Lumeward.
Пока в неё входят:
процессорный модуль (открытый проект KiCad);
плата расширения (открытый проект KiCad);
многоуровневый программный фреймворк (открытый код, сборка LLVM/Clang);
начальный загрузчик (открытый код, сборка LLVM/Clang);
инструменты настройки, диагностики, программирования и развёртывания флота таких устройств (открытые утилиты на Python);
облачная инфраструктура (открытые скрипты развёртывания на Azure IoT);
А примеры приложений я публикую как коллекцию. Платы проектировались так, чтобы быть минимальными по размеру и встраиваться во всякие бытовые гаджеты. Светильник не единственный вариант, куда их можно встроить.
Что умеет автоответчик
Реагирование на посетителя радаром и ИК-сенсором. Система отличает человека, который стоит у двери, от того, кто прошёл мимо по коридору. Сценарий стартует, когда человек простоял у двери положенное время. Это время задаётся параметром.
Освещение может включаться по звуку, по перепаду давления при открывании дверей, по вибрации, по присутствию, по движению. Границы детекции регулируются. Яркость регулируется. Скорость гашения регулируется.
Приглашение. Голосовое приглашение звучит на одном из пяти языков: английском, русском, норвежском, немецком или шведском. Ну так вышло. Языки легко поменять.
Записывает сообщение. После разрешающего тона можно говорить. Запись завершается по тишине, по предельной длине или если посетитель так и не заговорил.
Присылает запись письмом. Каждый визит вызывает отсылку письма. Сама аудиозапись хранится в облаке, а в письме приходит ссылка на неё. Если посетитель постоял и ушёл молча, письмо всё равно придёт, но ссылка будет вести не на запись, а на заметку о визите: хозяин в любом случае узнает, что кто-то приходил. По умолчанию письма отправляются через Gmail. Открыть запись по ссылке сможет только пользователь, вошедший в свою учётную запись на портале. Старая добрая почта не подведёт. Это вам не мессенджеры.
Ничего не теряет. Очередь доставки хранится на SD-карте, переживает перезагрузку и пропажу сети и сохраняет задания для повторной отправки. Недоставленная запись не удаляется никогда.
Не срабатывает дважды подряд. После ответа выдерживается пауза, по умолчанию полминуты, чтобы один и тот же человек не запустил сценарий снова.
Настраивается через Wi-Fi и BLE. Для Wi-Fi есть веб-интерфейс, для BLE есть приложение.
Обновляется по USB или сети. Новую прошивку устройство принимает и ставит само через загрузчик.
Без камеры. Не смущает соседей.
Сценарий работы автоответчика
Задача такая: кто-то приходил, а дома никого не было. Камеру соседи не поймут, и записка не вариант, потому что не приватно. Значит, светильник должен сам поговорить с пришедшим.
Сценарий в прошивке выглядит так:
Радар видит цель в заданной зоне. Цель должна пробыть в ней непрерывно, по умолчанию полторы секунды (регулируется). Короткого появления перед дверью недостаточно.
Устройство молча готовится: проверяет место на карте, захватывает рекордер, настраивает кодек, открывает файл. Всё, что может отказать, делается до того, как посетитель услышит первый звук. Если подготовка не удалась, приглашение не звучит.
Включается свет, звучит голосовое приглашение на выбранном языке.
После разрешающего тона открывается запись. Приглашение и сам тон в сообщение не попадают.
Человек говорит. Запись закрывается по тишине или по предельной длине.
Звучат завершающий тон и фраза результата. Файл уходит в очередь доставки: сначала в облако, следом письмо со ссылкой на него.
Устройство выдерживает паузу и ждёт подтверждённого ухода посетителя. Только после этого разрешается следующий визит.
Каждое письмо означает один конкретный визит и ссылается на аудиозапись. Очередь хранится на карте и сохраняется после перезагрузки. При ошибке попытка повторяется с заданным интервалом. После исчерпания лимита попыток задание переходит в отложенные и остаётся на карте.
Устройство хранит несколько профилей подключения к Wi-Fi, по очереди проверяет доступные сети и выбирает сеть с самым сильным сигналом среди тех, через которые есть выход в интернет. Если подключиться не удалось, оно снова перебирает все профили и продолжает попытки до установления связи. Например, в доме может быть роутер и расшаренный интернет с двух телефонов. Дивайс перепробует их все, чтобы добиться наилучшего качества связи.
Как прослушать запись

Письмо содержит ссылку на защищённую страницу портала. Для прослушивания нужно войти в свою учётную запись; после первого входа авторизация на телефоне сохраняется на тридцать дней. Если письмо случайно попадёт постороннему, он увидит только страницу входа и не получит доступ к записи.
Выгрузку записей в Azure Blob Storage можно отключить. Тогда, если включена отправка почтовых уведомлений через настроенный на устройстве SMTP-сервер (по умолчанию Gmail), запись придёт вложением. Если файл превышает заданный лимит, письмо придёт без записи. Записи детектора шума отправляются тем же способом, но сообщения посетителей имеют приоритет.
Формат и качество звука
Устройство сохраняет монофонический звук в контейнере WAV. Способ кодирования выбирается параметром audio_rec_format. В аудиорекордере реализованы три формата:
Формат | WAV tag | Представление отсчёта | Битрейт при 8 кГц | Объём за минуту |
|---|---|---|---|---|
PCM16 без сжатия |
| 16 бит | 128 кбит/с | 0.96 МБ |
IMA ADPCM |
| 4 бита | около 32.4 кбит/с | около 0.24 МБ |
G.711 uLaw |
| 8 бит | 64 кбит/с | 0.48 МБ |
IMA ADPCM уменьшает файл примерно в четыре раза относительно PCM16, G.711 uLaw примерно в два раза. Для ADPCM прошивка пишет блоки по 256 байт, в каждом помещается 505 отсчётов. Четыре байта блока заняты начальным значением и индексом кодера, поэтому фактический битрейт немного выше четырёх бит на отсчёт. Последний неполный блок дополняется до 256 байт. Из-за этого совсем короткая запись получается чуть больше расчётного значения.
Частота дискретизации настраивается отдельно. Доступны 8, 16, 22.05, 32, 44.1 и 48 кГц. Битрейт растёт пропорционально частоте:
Частота | PCM16 | IMA ADPCM | G.711 uLaw |
|---|---|---|---|
8 кГц | 128 кбит/с | около 32.4 кбит/с | 64 кбит/с |
16 кГц | 256 кбит/с | около 64.9 кбит/с | 128 кбит/с |
22.05 кГц | 352.8 кбит/с | около 89.4 кбит/с | 176.4 кбит/с |
32 кГц | 512 кбит/с | около 129.8 кбит/с | 256 кбит/с |
44.1 кГц | 705.6 кбит/с | около 178.8 кбит/с | 352.8 кбит/с |
48 кГц | 768 кбит/с | около 194.7 кбит/с | 384 кбит/с |
По умолчанию запись идёт в PCM16 с частотой 8 кГц, с расчётом на последующую транскрибацию. Сжатую запись иногда приходится декодировать перед распознаванием, а потери при сжатии могут снизить его точность. Стоимость облачной транскрибации обычно зависит от длительности записи, а не от размера файла. Формат и частоту можно изменить в настройках.
По умолчанию прибор хранит до 100 записей. Лимит можно изменить в настройках, где отдельно учитываются количество файлов, общий объём и срок хранения. Если запись выгружается в Azure Blob Storage, место на SD-карте всё равно нужно до момента успешной доставки и подтверждения задания. Недоставленная запись не удаляется. При отправке вложением действует дополнительное ограничение почтового сервера: при превышении заданного лимита письмо отправляется без аудиофайла, но ссылка на облачную запись остаётся обычным вариантом доставки.
Как определяется присутствие
Для включения света подходят несколько датчиков, но автоответчик начинает визит только по радару. Хлопок, удар по корпусу или перепад давления могут включить свет, но не должны сами по себе вызывать голосовое приглашение.
Радар и зона ответа
BGT60TR13C даёт расстояние до цели. Основной алгоритм Infineon различает крупное движение (Macro), микродвижения остановившегося человека (Micro) и отсутствие цели. Поэтому человек не обязан всё время махать руками: обнаружение может удерживаться и по небольшим движениям, в том числе при дыхании. Чувствительность этих двух каналов настраивается отдельно.
Зона ответа задаётся двумя расстояниями от радара: ближней и дальней границей. Заводские значения: от 30 до 400 см. Это интервал дальности, а не нарисованный на плане прямоугольник. Оценка угла у радара есть, но в условии запуска автоответчика она не используется.
Кроме расстояния, сценарий проверяет, что радар работает и его данные не устарели. Затем отсчитывается время непрерывного присутствия. Если до конца отсчёта цель пропала из зоны, подтверждение начинается заново. После визита должны выполниться оба условия: закончилась пауза и зона достаточно долго оставалась пустой по данным радара. Стоящего у двери человека автоответчик не приветствует каждые тридцать секунд. При этом потеря цели во время записи сама по себе не обрывает запись.
На панели радара видны профиль дальности, движение относительно фона и история кадров в виде waterfall. Границы зоны можно перетаскивать мышью или задавать ползунками Zone from и Zone to. Рядом находятся энергии крупных и мелких движений и их пороги Macro threshold и Micro threshold. Отдельный Zone threshold относится к резервному детектору, который сравнивает движение с фоном; поле Detector показывает, какой алгоритм сейчас выдаёт результат.

После установки пользователь должен настроить границы зоны срабатывания с учётом конкретного места и подобрать чувствительность радара отдельно для макро- и микродвижений.
Остальные датчики
У света свой набор причин для включения. Их можно разрешать по отдельности и наблюдать на панели основного освещения.
Датчик | На что реагирует | Что настраивается |
|---|---|---|
Тепловое присутствие и движение | Пороги присутствия и движения, гистерезисы и фильтры | |
Звук выше установленного уровня или текущего фона | Порог и время подтверждения акустического события | |
Удар или вибрация корпуса | Порог удара | |
Перепад давления, например при открытии двери | Порог перепада и время удержания события |
У STHS34PF80 нет измерения дальности. Его удобно смотреть отдельно: на графике видны сигналы присутствия и движения вместе с порогами, прочитанными из самого датчика. Параметры меняются в группе APP_IR_Sensor, затем кнопка применения на панели отправляет их в датчик и перечитывает регистры.

Чем управлять автоответчиком
Для настройки не требуется пересобирать прошивку. Есть три интерфейса:
Инструмент | Подключение | Для чего нужен |
|---|---|---|
Браузер на компьютере, USB или сеть | Панели автоответчика и датчиков, графики, настройки, журнал и работа с записями | |
Браузер по IP-адресу устройства в сети | Просмотр состояния и редактирование параметров | |
Приложение на телефоне, BLE | Настройки приложения и модуля, управление светом и просмотр журнала |
WebDevLink открывается локально из репозитория. Для USB нужен Chrome или Edge с Web Serial; по сети клиент соединяется с устройством через WebSocket. Это отдельный инструмент, а не страница, которую отдаёт встроенный веб-сервер. При переходе с телефона на WebDevLink соединение на телефоне нужно закрыть: канал DevLink обслуживает одного клиента.
Панель автоответчика
В меню Application находится Door answering machine. На одной панели собраны:
переключатель автоответчика, текущий шаг визита, расстояние до цели и оставшееся время подтверждения;
состояние рекордера, фактическая длительность записи, уровень микрофона и измеренный фон;
имя и размер последнего сообщения, причина завершения и последняя ошибка;
очередь доставки, что она делает сейчас - грузит файл в облако или шлёт письмо, - исход каждой стадии, время до следующей попытки и счётчик отложенных заданий.
Кнопка Run a test visit запускает весь сценарий без радара, даже когда автоматический ответ выключен. Нажимать её можно в состоянии Idle. Это полноценный прогон с записью и, если доставка включена, с выгрузкой в облако и письмом. Кнопка Abort прерывает текущий визит. Сохранённые записи можно посмотреть и скачать через панель Files on the card.
Ниже идут два графика: шаг сценария вместе с состоянием рекордера, а также уровень микрофона на фоне шума. По ним видно, началась ли запись и был ли голос выше фона. В устройство не заложено распознавание текста: посетитель оставляет звуковой файл.
Расписание работы
Прибор умеет по расписанию полностью выключаться и включаться обратно сам. До семи строк - на каждый день, по дням недели или на одну дату в году - лежат на карте в CONFIG/power_schedule.json и правятся с панели Working hours. Выключение настоящее: вход зарядника в HiZ, ключ BATFET разомкнут, от аккумулятора остаётся только утечка. Будит плату будильник часов AB1815 через вход QON зарядника. USB имеет приоритет над расписанием, а без файла прибор просто остаётся включённым.
Автокалибровка часов
Расписание держится на часах, и они калибруются сами, в два приёма. При загрузке прошивка измеряет частоту часового кварца таймером процессора и записывает в AB1815 цифровую подстройку с шагом 1.9 ppm; точность здесь ограничена кварцем модуля, десятки ppm. Дальше каждое получение времени по SNTP сравнивается с часами, и уход, накопленный за шесть и более часов, возвращается в ту же подстройку. В итоге ход сходится к ошибке порядка 1 ppm, около 0.1 с в сутки.
Что и как настраивается
У автоответчика 21 настраиваемый параметр. Они задают режим работы и тайминги сценария, условия записи, язык и голосовые подсказки, доставку и повторные попытки, а также ограничения на количество, объём и срок хранения записей. Отдельно настраиваются зона и чувствительность радара, яркость освещения, громкость динамика и чувствительность микрофона.
Две платы, из которых всё состоит
Обе платы имеют одинаковый контур 56.97 × 25.91 мм. Они складываются одна на другую и соединяются тремя межплатными разъёмами Hirose DF12 с шагом 0.5 мм, на 60 и на 20 контактов.
MODULE_R7FS7v2 представляет собой сам вычислитель, а в файлах называется R7FS7MOD. Шесть слоёв меди, толщина 0.72 мм. На нём размещено всё, что не зависит от конкретного применения:
Что | Чем |
|---|---|
Процессор | Renesas Synergy S7G2, |
Оперативная память | SDRAM |
Внешняя флеш | NOR |
Карта | microSD на отдельном интерфейсе SDHI |
Звук | кодек |
Движение | IMU |
Wi-Fi и BLE | модуль Laird Sterling LWB5+ |
LoRa |
|
Питание от аккумулятора | зарядник |
Часы |
|
Измерения | 12-битный АЦП |
USB | 2.0 HS с защитой |
RADADPTR01 представляет собой несущую плату, которую я заказывал на JLCPCB. Четыре слоя, толщина 1.02 мм. Она проще, и вся её работа в том, чтобы развести мелкий шаг модуля по реальной периферии светильника: усилитель класса D IS31AP4991A на динамик, ключ питания STMPS2171 на радар, полевой транзистор IRLML6344 на светодиодную матрицу, и дальше контактные площадки под плату радара, плату IR-сенсора, выносной микрофон, динамик, белые светодиоды, RGB-светодиод, аккумулятор и внешнее питание.
На рендере ниже модуль MODULE_R7FS7v2 уже установлен под несущей платой RADADPTR01 и соединён с ней разъёмами DF12.






У адаптера лист один.

Энергосбережение и измерение потребления
В модуле предусмотрены специальные средства для экономии энергии: управляемые ключи и стабилизаторы позволяют отключать питание периферии, а прошивка - переводить отдельные узлы в режим ожидания, останавливать неиспользуемые блоки процессора, снижать частоту и напряжение питания. Для пауз в работе есть Software Standby с пробуждением по часам.
Встроенный измеритель MAX17262 позволяет достаточно точно измерять ток потребления от аккумулятора и самостоятельно вести учёт его заряда, без участия процессора: тот лишь читает из регистров чипа напряжение, ток, остаток и проценты. В самом экономном режиме модуль может полностью отключить питание системы от аккумулятора ключом в BQ25619: тогда остаётся только ток утечки в пределах 10 мкА.
Учёт заряда точный: через MAX17262 идёт весь ток изделия, включая светодиодную матрицу. Прошивка настраивает измеритель по методике производителя только после его сброса, то есть после снятия батареи, а выученные параметры ёмкости сохраняет во флеш-памяти и возвращает в чип; кнопка New battery на панели сообщает ему о замене аккумулятора. Замер на аккумуляторе 5000 мА·ч: плата с Wi-Fi берёт 150-200 мА, с матрицей на полной яркости - около 1.0 А, то есть матрица стоит примерно 850 мА. Яркость задаётся в процентах по квадратичной шкале с компенсацией напряжения питания, и это же ручка потребления: половина яркости стоит четверть тока матрицы, около 210 мА.
Вклад каждого из средств экономии измерен тем же MAX17262: встроенный в прошивку тест потребления выключает узлы один за другим и в каждом достигнутом состоянии снимает средний ток всей сборки. Отключения в таблице накапливаются: всё выключенное выше остаётся выключенным ниже, несколько промежуточных стадий объединены.
Ток потребления сборки по мере отключения узлов
Условия измерения | Частота ядра | Средний ток, мА | Погрешность среднего, мА |
|---|---|---|---|
Исходное состояние, потребители включены | 240 МГц | 200.43 | ±4.75 |
Остановлена служба Wi-Fi | 240 МГц | 141.59 | ±2.89 |
Дополнительно отключены радар, барометр, ИК-датчик и их стабилизатор | 240 МГц | 115.55 | ±0.68 |
Отключён BLE и снято питание радиомодуля | 240 МГц | 96.72 | ±0.44 |
Усилитель и кодек переведены в standby, LoRa и SD-карта обесточены | 240 МГц | 84.55 | ±0.39 |
Отключены USB-контроллер и его физический уровень | 240 МГц | 40.24 | ±0.38 |
Остановлены фоновые задачи перед отключением SDRAM, снято питание SDRAM | 240 МГц | 22.60 | ±0.50 |
Остановлены неиспользуемые блоки периферии процессора | 240 МГц | 20.53 | ±0.35 |
Software Standby, пробуждение раз в секунду | Ядро остановлено; после пробуждения - 240 МГц | 1.54 | ±0.20 |
Процессор выведен из сна, частота снижена | 1 МГц | 3.43 | ±0.18 |
Напряжение системного питания снижено до 2.8 В | 1 МГц | 2.88 | ±0.18 |
Software Standby при питании 2.8 В, пробуждение на MOCO | Ядро остановлено; после пробуждения - 1 МГц | 1.32 | ±0.19 |
Тест можно запустить на любом экземпляре устройства и получить собственный отчёт. Кабель USB при этом выдёргивать не нужно: тест сам переводит вход зарядника в HiZ и питает плату от аккумулятора, пока хост остаётся на связи.
MOCO (Middle-Speed On-Chip Oscillator) - встроенный RC-генератор процессора на 8 МГц, которому не нужны ни кварц, ни ФАПЧ. В строках на 1 МГц ядро тактируется от него через делитель на 8, а кварц 24 МГц и ФАПЧ выключены.
В Software Standby останавливаются ядро, кварц 24 МГц, ФАПЧ и вся периферия; работает только субчасовой кварц 32.768 кГц, и от него внутренний RTC процессора раз в секунду будит ядро. Проснувшись, процессор первым делом читает у измерителя регистр тока - тот хранит среднее за последние 175 мс, целиком проведённые во сне, - и засыпает снова. Поэтому числа в строках сна относятся к спящей плате, а не к пробуждению.
Цена пробуждения считается отдельно: на кварце и ФАПЧ плата бодрствует 1.4 мс, на MOCO при 1 МГц - 101 мс за ту же работу, и медленный такт обходится примерно в шесть раз дороже за одно пробуждение. Вывод для изделия: просыпаться на быстром такте, делать работу и засыпать.
Минимальный средний ток в тесте - 1.3-1.5 мА в Software Standby с отключёнными радаром, барометром и ИК-датчиком: две строки сна дали 1.54 ± 0.20 и 1.32 ± 0.19 мА, и ни напряжение 2.8 В, ни способ пробуждения на спящий ток не влияют. Если бы ИК-датчик оставался включённым, сон стоил бы около 4.1 мА: сам датчик берёт примерно 0.5 мА, но на этой плате его нельзя оставить одного - барометр на той же шине I2C0 должен оставаться под питанием, а его стабилизатор питает ещё и генератор 80 МГц платы радара, и вместе это около 2.5 мА сверх спящей платы.
Архитектура софта
Весь код разделён на два слоя:
framework_src: общая платформа. Здесь ThreadX, FileX, NetX Duo, USBX, аудиотракт, параметры, журнал, веб-сервер, DevLink и клиент Azure IoT.src: приложение. Здесь сценарий автоответчика, очередь доставки, управление светом и работа с конкретными датчиками. Сам автоответчик находится вsrc/Door_answer/.
Благодаря такой архитектуре для следующего устройства я смогу взять готовые подсистемы звука, сети и хранения вместе с инструментами настройки. Скорректировать понадобится только сценарий работы.
У параметров один источник: ParamsDB.txt. Генератор создаёт из него C-таблицы, описания переменных DevLink и схему настроек. Поэтому диапазоны и названия в клиентах соответствуют прошивке, а не отдельному вручную составленному списку. Сохранённые значения лежат в DataFlash.
Отладочно-диагностический протокол DevLink даёт клиентам доступ к переменным и командам работающего устройства. Отсюда берутся показанные выше графики: сценарий, звук и сеть продолжают работать во время наблюдения.
Сборка и обслуживание
Прошивка собирается LLVM/clang for Embedded через CMake и Ninja. Инструкция по сборке содержит версии инструментов, настройку среды и готовые команды. Разработка и отладка идут в Visual Studio Code: clangd отвечает за навигацию и анализ C/C++, CMake Tools за сборку, Cortex-Debug за отладку через J-Link по SWD.
Почта и встроенный веб-интерфейс используют TLS. BLE поддерживает Secure Connections.
В устройстве предусмотрена защита прошивки: каждый образ шифруется и подписывается, а загрузчик проверяет его перед установкой. Специальный сервис провизионирования подготавливает ключи в завёрнутом виде, после чего криптографический блок микроконтроллера привязывает их к конкретному чипу. Скопировать такой ключ на другое устройство бесполезно.
Этот же сервис выполняет облачное провизионирование: регистрирует устройство в Azure и выдаёт ему собственный сертификат и настройки подключения. Таким образом, при подготовке платы одновременно настраиваются защищённые обновления прошивки и доступ к облаку.
Лицензионные ограничения
Из-за лицензионных ограничений исходники Renesas SSP и FileX с exFAT не выложены. Стек BLE Infineon BTSTACK и библиотеку XENSIV Radar Presence сами поставщики распространяют только в двоичном виде. Так же поставляются прошивки радиомодуля CYW4373 и драйвер криптоблока Renesas SCE7. Все нужные бинарные компоненты уже лежат в репозитории: публичная сборка LLVM/Clang получает функциональность SSP и FileX из libssp_lib.a и libfx_lib.a. Исходники SSP и FileX можно бесплатно получить в составе Renesas Synergy Software Package после регистрации и принятия лицензии.
Что дальше
Как вы, наверно, уже поняли, в этом фреймворке много внимания уделено киберзащите. Вот о ней и будет дальше.

