
Подробное руководство по сборке радара для мониторинга присутствия в помещении человека и даже просто его дыхания.
Общий механизм выглядит так: ESP32-S3 измеряет параметры канала Wi-Fi 100 раз/сек, а Raspberry Pi их анализирует, в реальном времени выводя результат в браузере. Эта система обнаруживает абсолютно неподвижно сидящего человека по одному только движению его грудной клетки во время дыхания — без каких-либо камер, датчиков PIR или носимых устройств.
Содержание
1. Что умеет система
|
Движение |
Регистрирует ходьбу, жестикулирование, приседание. При движении всплеск сигнала на ~28 дБ выше фонового шума — такое пропустить невозможно. |
|
Присутствие |
Отличает пустую комнату от той, где неподвижно сидит человек. Это уже сложный процесс, на котором ИК-датчики движения (PIR) постоянно ошибаются. |
|
Частота дыхания |
От 8 до 36 вдохов/мин. Точность проверена по эталону и составляет погрешность в рамках 0,1 вдоха/мин. |
|
Сканирование сквозь стены |
Сигнал с частотой 2,4 ГГц проходит сквозь гипсокартон, дерево и стекло. Кирпич и бетон его сильно ослабляют, а фольгированная изоляция полностью блокирует. |
|
Классы активности |
Пусто / неподвижно / едва заметно / активно / интенсивно. |
|
Данные окружающей среды |
Измерение температуры, влажности, давления и качества воздуха (при подключении дополнительных датчиков). |
|
Отчёт о сне |
Регистрирует время в постели, неподвижность или беспокойность во сне, его нарушения, частоту дыхания в течение ночи. |
2. Чего она не умеет
Этот раздел важнее списка возможностей, так как в большинстве тех заявлений о технологии Wi-Fi-sensing, которые можно встретить в сети, описываются совсем другие приборы.
|
Распространённые заявления |
Что имеем в данном случае |
|
Увидеть силуэт или скелет человека |
С помощью Wi-Fi это нереально. Ширина полосы 20 МГц даёт разрешение по дальности |
|
Определить местоположение человека в комнате |
Один передатчик и один приёмник измеряют только один путь сигнала. То есть вы узнаёте о том, что что-то изменилось, а не где оно изменилось. Для определения местоположения требуется как минимум 3 отдельных узла. |
|
Подсчитать людей |
Два человека вызывают больше возмущений в канале, чем один, но не настолько, чтобы можно было надёжно их посчитать. |
|
Определить неподвижного человека, который задерживает дыхание |
Измерять нечего. Простая физика, а не отсутствие фичи. |
|
Идентифицировать человека |
Невозможно |
|
Фиксировать фазы сна (REM / глубокий / поверхностный) |
Фазы сна определяются по активности мозга и глаз, а этой информации в сигнале нет. Этот прибор детектирует неподвижность, оставляя её интерпретацию вам. |
К тому же, это не медицинский прибор. Это инструмент для спальни на базе микроконтроллера за $5.
3. Принцип работы
Общее описание:
Wi-Fi-сигнал приходит на приёмник сразу несколькими путями — как напрямую, так и в виде отражений от стен, мебели и людей. Все эти копии сигнала накладываются друг на друга с разными задержками, в результате чего некоторые частоты усиливаются, а некоторые друг друга гасят. Такая картина взаимодействия частот называется информацией о состоянии канала (Channel State Information, CSI), и её могут сообщать большинство микросхем Wi-Fi. Поместите что-либо в комнату, и длина пути сигнала изменится. Тело человека состоит преимущественно из воды и хорошо отражает волны на частоте 2,4 ГГц, что и делает людей видимыми. Длина волны на 2,4 ГГц составляет 12,5 см, так что смещение грудной клетки в диапазоне 6 мм при дыхании изменяет путь сигнала достаточно, чтобы это можно было измерить.
Путь данных

Поскольку мы сканируем пространство между роутером и ESP32, эти устройства нужно расположить в противоположных частях комнаты так, чтобы человек находился между ними.
Необходимость генерировать трафик
CSI существует только в момент получения пакетов. Сам по себе пустой канал не генерирует никаких данных, какое бы качественное оборудование вы ни использовали.
|
Подход |
Частота получения CSI |
|
Пассивное прослушивание фоновых сигналов Wi-Fi |
~1 Гц, нерегулярно |
|
ESP32 отправляет данные и фиксирует CSI из ответов роутера (ACK-пакетов) |
~1 Гц (не работает) |
|
Pi отправляет UDP-пакеты на ESP32 |
1:1, вплоть до 200 Гц |
В данном проекте использован конкретно третий вариант, в связи с чем плату ESP32 необходимо полноценно подключать к Wi-Fi-сети. Благодаря этому, частота опроса задаётся программно, а не определяется случайно, и замеры происходят через равные промежутки времени, что нам и нужно для точного анализа дыхания.
Роль Pi

Две важные детали, от которых зависит, будет ли вообще работать эта схема:
-
Оба частотных диапазона представляют доплеровские частоты, а не демонстрируют скорость движения человека. Отражатель, движущийся со скоростью
v, сдвигает сигнал на величинуv / длина волны. Таким образом, ходьба со скоростью 1 м/с ведёт к появлению всплеска в районе 8 Гц — но никак не на частоте шагов. Дыхание же остаётся в пределах всего 0,13—0,7 Гц, и это единственная причина, почему его удаётся разделить с движением. -
Все показания измеряются в дБ относительно собственного шума приёмника, поэтому для пустой комнаты они всегда будут равны 0 дБ — в любом помещении, на любом расстоянии и при любой мощности передатчика. Здесь нет этапа калибровки или заранее измеренного эталона, который мог бы со временем сбиваться. Собственный шум прибора определяется путём разложения ковариационной матрицы поднесущих частот. Суть в том, что внутри радиомодуля шум на каждой из этих частот является независимым в то время, как происходящие в комнате действия вызывают синхронное изменение всех поднесущих сразу.
4. Что нужно купить
Минимальная конфигурация (регистрация движения, присутствия, дыхания).
|
# |
Компонент |
Примечание |
|
1 |
ESP32-S3-WROOM-1, N16R8 |
Датчик. По возможности берите именно такой. Главное, ознакомьтесь с предупреждением по распиновке в разделе «Подключение». Проще всего использовать отладочную плату с мостом USB-UART (CP2102) (CP2102). |
|
1 |
Raspberry Pi 4 |
Вполне хватит версии с 2 ГБ памяти, плюс задействуется всего ~20% мощности одного ядра. Если же вы будете подключаться только через USB, то вполне подойдёт любой ПК под управлением Linux. |
|
1 |
USB-кабель для передачи данных |
Micro-USB или USB-C — в зависимости от разъёма на плате. Кабели только для зарядки здесь не подойдут — с ними плата просто не появится в списке подключенных устройств. |
|
1 |
Любой Wi-Fi-роутер с частотой 2,4 ГГц |
У вас наверняка такой есть. Версии на 5 ГГц не подойдут, так как ESP32-S3 эту частоту не видит. |
Вот и весь список покупок. Если малинка у вас уже есть, то общая стоимость практически сводится к цене ESP32.
По желанию: беспроводное подключение (установка узла в любом месте)
|
# |
Компонент |
Примечание |
|
2 |
nRF24L01+ PA/LNA |
Один для Raspberry Pi, один для ESP32. Один модуль — это лишь половина канала связи. Необходимы развязывающие конденсаторы — см. раздел «Питание». |
|
2 |
Адаптер для nRF24 с регулятором AMS1117 |
Однозначно лучше голого модуля. Этот адаптер исключит большинство проблем с питанием. |
|
2 |
CC1101 433 MHz (альтернатива) |
Работает вне диапазона Wi-Fi, поэтому не может создавать помехи измерениям на 2,4 ГГц. На этом программная часть полностью готова, но сборка упирается в согласование антенн. Здесь потребуются согласованные антенны на 433 МГц. |
По желанию: мониторинг окружающей среды
|
# |
Компонент |
Примечание |
|
1 |
BMP280 (или BME280) |
Определение давления и температуры по данным SPI. Лучший термометр из трех. |
|
1 |
DHT22 / AM2302 |
Влажность и температура. Берите 3-пиновый модуль сопряжения, на котором уже есть подтягивающий резистор. |
|
1 |
Датчик газа MQ135 |
Качество воздуха. Датчик аналоговый, поэтому обязательно ознакомьтесь с предупреждением о делителе напряжения в разделе «Подключение» ниже. |
|
2 |
Резисторы на 10 kΩ |
Делитель напряжения для MQ135, если вы питаете его от 5 В. |
Также пригодятся: макетная плата, соединительные провода Dupont и отдельный от Pi источник питания на 5 В, если вы планируете добавить MQ135 (его нагревательный элемент непрерывно потребляет ток ~150 мА).
5. Необходимое ПО
|
Для Pi |
Зачем |
|
Raspberry Pi OS / любой дистрибутив Linux на базе Debian |
Проект разработан на Debian 13 (Trixie) с помощью Python 3.13. |
|
python3, python3-venv, python3-pip |
Debian блокирует прямую установку пакетов в системный Python (PEP 668) через |
|
numpy, scipy |
Нужны для цифровой обработки сигналов (DSP). Можете установить через |
|
git |
Для клонирования этого репозитория. |
|
Веб-браузер |
Для запуска дашборда не нужны ни сборка, ни какие-либо зависимости. |
|
PlatformIO (только для самостоятельной сборки прошивки) |
Устанавливается командой |
|
Активный SPI (только для радиомодулей) |
|
Установка пакетов ОС:
sudo apt update
sudo apt install -y git python3-venv python3-pip python3-numpy python3-scipy
6. Подключение
Простейший вариант сборки с одним кабелем
Raspberry Pi 4 ──── USB-кабель ──── макетка ESP32-S3
Собственно, и всё. По кабелю передаётся питание и поток данных CSI. Ниже перечислены возможные дополнительные радиомодули и датчики.
Прочтите, прежде чем подключать что-либо к ESP32
Модуль N16R8 оснащён 16 МБ флэш-памяти Quad SPI и 8 МБ Octal PSRAM. При этом Octal PSRAM занимает выводы (GPIO) с 33 по 37. Если подключить периферию к неправильному выводу, плата просто не будет загружаться без какой-либо информативной ошибки. Именно так чаще всего этот модуль превращают в кирпич.
|
Выводы |
Назначение |
Комментарий |
|
GPIO 26—32 |
Внутренняя флэш-память для SPI |
НЕ ИСПОЛЬЗОВАТЬ |
|
GPIO 33—37 |
Octal PSRAM (на N16R8) |
НЕ ИСПОЛЬЗОВАТЬ |
|
GPIO 0, 3, 45, 46 |
Выбор режима загрузки |
Лучше избегать |
|
GPIO 19, 20 |
Аппаратный USB, линии D-/D+ |
Лучше избегать |
|
GPIO 43, 44 |
Консоль UART0, уже используется |
Лучше избегать |
|
1, 2, 4—18, 21, 38—42, 47, 48 |
|
Безопасны |
Что происходит на каждой шине

На одной шине SPI висит три устройства, каждое из которых имеет свою линию для выбора микросхемы. Датчик DHT22 работает по собственному однопроводному протоколу, а MQ135 является аналоговым.
Общая распиновка ESP32-S3
|
GPIO |
Подключается к |
|
4 |
MQ135 |
|
9 |
nRF24 |
|
10 |
nRF24 |
|
11 |
SPI MOSI — общий: nRF24 + CC1101 + BMP280 |
|
12 |
SPI |
|
13 |
SPI |
|
14 |
nRF24 |
|
15 |
BMP280 |
|
16 |
DHT22 |
|
17 |
CC1101 |
|
18 |
CC1101 |
|
21 |
CC1101 |
Сторона Raspberry Pi 4 (только при добавлении радиомодулей)
Общая шина SPI0 — подключается к обоим модулям:
|
Сигнал |
BCM |
Физический контакт |
|
SCLK |
11 |
23 |
|
MOSI |
10 |
19 |
|
MISO |
9 |
21 |
nRF24L01+ → /dev/spidev0.0:
|
Контакт модуля |
BCM |
Физический контакт |
Примечание |
|
GND |
— |
20 |
|
|
VCC |
— |
17 |
Строго 3,3 В; 5 В модуль не выдержит. |
|
CE |
25 |
22 |
Контакт выбора режима, а не микросхемы. |
|
CSN |
8 |
24 |
CE0 |
|
IRQ |
24 |
18 |
Подключение не обязательно, но желательно. |
CC1101 → /dev/spidev0.1:
|
Контакт модуля |
BCM |
Физический контакт |
|
GND |
— |
9 |
|
VCC |
— |
1 (строго 3,3 В; 5 В модуль не выдержит). |
|
CSN / SS |
7 |
26 (CE1) |
|
GDO0 |
23 |
16 |
|
GDO2 |
27 |
13 |
Расположение контактов на модулях CC1101 зависит от конкретной платы. Существует как минимум три популярных варианта разводки, и позиции пинов на них отличаются. Ориентируйтесь только по маркировкам на самой плате, а не по очерёдности выводов.
Датчики состояния окружающей среды (на ESP32)
BMP280 (SPI — использует общую шину и требует только собственной линии выбора микросхемы):
|
Контакт модуля |
ESP32-S3 |
|
VCC |
3V3 |
|
GND |
GND |
|
SCL / SCK |
GPIO12 |
|
SDA / SDI / MOSI |
GPIO11 |
|
SDO / MISO |
GPIO13 |
|
CSB / CS |
GPIO15 |
В режиме SPI линия SDA работает как вход, а SDO — как выход. То есть здесь не тот механизм, который предполагают маркировки для интерфейса I2C. Так что, если считать ID чипа не удаётся, первым делом поменяйте эти два провода местами.
Подключение DHT22 — VCC→3V3, DATA→GPIO16, GND→GND. Если у вас голый 4-контактный датчик, то потребуется добавить подтягивающий резистор на 10 kΩ между линиями DATA и 3V3; на 3-контактных модулях он уже присутствует.
Подключение MQ135 — VCC→5V, GND→GND, AO→GPIO4 через делитель напряжения:
MQ135 AO ────[ 10k ]────┬────[ 10k ]──── GND
│
└──────► ESP32 GPIO4 (2.5 V max)
Нагреватель рассчитан на 5 В, а питаемый от 5 В контакт AO может выдавать напряжение до 5 В, что сожжёт АЦП ESP32, рассчитанный на 3,3 В. Здесь сгодится любая пара одинаковых резисторов — важно только соотношение их сопротивлений.
Альтернатива без резисторов: запитайте модуль от 3,3 В и подключите контакт AO напрямую (напряжение на нём физически не сможет превысить уровень питания датчика), а затем один раз укажите плате следующую настройку:
python tools/node.py mq135 supply 3v3
Выбор
GPIO 4не случаен: это должен быть один из выводов между GPIO 1 и 10, которые относятся к первому блоку АЦП (ADC1). Второй блок — ADC2 (выводы GPIO 11—20) — физически невозможно использовать во время работы Wi-Fi, так как радиомодуль полностью забирает этот преобразователь под свои нужды. Поскольку работа Wi-Fi — это главная цель данного проекта, использование блоков ADC2 исключено в принципе.
Питание — слабые места этой конфигурации
-
Самый проблемный элемент — это модуль nRF24L01+ PA/LNA. В моменты всплесков на мощности +20 дБм скачки тока здесь достигают 115 мА, и шина питания 3,3 В малинки просто с ними не справляется. Симптом этой проблемы очень характерный: прибор успевает передать несколько пакетов, а затем замолкает. Чтобы решить проблему, припаяйте электролитический конденсатор на 10—100 мкФ вместе с керамическим на 100 нФ прямо к контактам VCC и GND радиомодуля — именно на плате модуля, а не на шине макетной платы. А ещё лучше — запитайте его от отдельного стабилизатора AMS1117-3.3, подключённого к 5 В.
-
Подключайте антенны до включения питания. Передача сигнала в открытый порт может привести к повреждению усилителя.
-
Подбирайте антенну для CC1101 строго под его частотный диапазон. Антенны на 433 и 868 МГц не взаимозаменяемы, и со стороны это их различие выглядит так, будто сгорел радиомодуль.
-
Нагреватель MQ135 непрерывно потребляет ток около 150 мА. Если после его добавления ESP32 начинает уходить в перезагрузку из-за просадки питания, либо частота опроса CSI становится нестабильной — организуйте для датчика отдельное питание 5 В с общей землёй.
Вся логика процесса, вместе с пятью багами nRF24, которые пришлось исправлять для обеспечения надёжной связи, описана в разделе 4 файла PROJECT.txt.
7. Поэтапная сборка
Шаг 1 — скачайте код
git clone https://github.com/The-Masked-Bear/wifisense-pi.git
cd wifisense-pi
Шаг 2 — настройте окружение Python
Флаг --system-site-packages позволяет повторно использовать установленные через apt пакеты numpy и scipy, исключая необходимость их долгой компиляции на Pi.
python3 -m venv --system-site-packages .venv
./.venv/bin/pip install -r requirements.txt
Шаг 3 — протестируйте без подключения устройств
Синтетический канал связи — это не просто рандомная имитация, а полноценный симулятор, основанный на законах физики. Он запускает реальную цепочку детекторов, поэтому веб-панель ведёт себя точно так же, как и при подключении настоящего железа. Выполните этот тест в первую очередь. Так вы проверите корректность установки ПО до того, как начнёте разбираться, что и куда подключать.
cd pi
../.venv/bin/python -m wifisense --link synthetic
Откройте http://localhost:8080. Вы должны увидеть бегущий график “водопад” и изменение статусов. Остановить визуализацию можно комбинацией Ctrl-C.
Шаг 4 — прошейте ESP32
Скачайте готовый бинарник, или скомпилируйте его сами:
pip install platformio
cd firmware
pio run -t upload --upload-port /dev/ttyUSB0
Не обнаруживается подключение через USB? Выполните ls /dev/ttyUSB* и lsusb | grep -i "silicon labs". Если ничего не появится, сначала попробуйте использовать другой USB-кабель.
Шаг 5 — укажите узлу, к какому WiFi подключаться
Нужна сеть строго на 2,4 ГГц. Учётные данные сохраняются во флэш-памяти ESP32 и при отключении питания не стираются. Так что это разовый шаг, который не требует повторной компиляции.
cd pi
../.venv/bin/python tools/node.py wifi "YourSSID" "YourPassword"
../.venv/bin/python tools/node.py info # Ищите assoc=yes и IP.
При открытии последовательного порта плата перезагружается, поэтому в течение нескольких первых секунд она будет недоступна. Скрипт tools/node.py дожидается её готовности, но при прямом подключении через терминал такого автоматического ожидания не будет.
Шаг 6 — полноценный запуск
cd pi
cp config.example.json config.json # Не обязательно; вполне сгодятся и базовые установки.
../.venv/bin/python -m wifisense --link serial
Шаг 7 — правильное расположение устройств
Это самый важный этап:
Роутер ──────────── Человек ──────────── Узел ESP32
Расстояние между ними от 2 до 8 метров. Узел и роутер должны находиться в противоположных концах области, которую вы планируете сканировать.
Проверьте показания RSSI в дашборде: пригодный диапазон от -40 до -60 dBm.
Шаг 8 — Автозапуск при загрузке
./install.sh # Только сервер.
./install.sh --kiosk # Плюс полноэкранный браузер на дисплее Pi.
./install.sh --uninstall # Удаление.
8. Запуск
systemctl status wifisense # Проверка работоспособности системы.
journalctl -u wifisense -f # Логи в реальном времени.
sudo systemctl restart wifisense
|
URL-адрес |
Что отображает |
|
http://<pi-address>:8080 |
Дашборд в реальном времени |
|
http://<pi-address>:8080/history |
Историю + отчёт о сне |
Запуск вручную (сначала остановите службу):
cd pi
../.venv/bin/python -m wifisense --link serial # USB-кабель.
../.venv/bin/python -m wifisense --link synthetic # Без подключения оборудования.
../.venv/bin/python -m wifisense --link nrf24 # Радиомодуль на 2,4 ГГц.
9. Показания дашборда
|
Панель |
О чём говорит |
|
Big word |
CLEAR / PRESENT / MOVEMENT / ACTIVE / VIGOROUS. PRESENT означает, что человек присутствует, но не движется. Это обнаруживается по дыханию. |
|
MOTION (dB) |
Общее движение. 0 дБ — пустая комната, значения выше ~6 дБ означают реальное движение, при ходьбе показания колеблются в районе 20—30 дБ. |
|
VITALS (dB) |
Энергия в диапазоне регистрации дыхания. По этим показаниям фиксируется неподвижный человек. |
|
CHANNEL RESPONSE |
Водопадный график. Горизонтальные полосы отражают постоянную картину многолучевого распространения сигнала в комнате, а вертикальные штрихи означают, что что-то в ней движется. |
|
ACTIVITY |
Оба графика показаний в дБ за последнюю минуту. Пунктирные линии отмечают пороговые значения, на основе которых система принимает решения в данный момент. |
|
RESPIRATION |
Количество вдохов в минуту, отфильтрованная форма волны и спектр с отмеченным выбранным пиком. Пустой экран с ровной линией — это нормально. Системе требуется неподвижный объект и около 30 секунд для расчёта. |
|
ENVIRONMENT |
Появляется только после прибытия пакета данных, поэтому сборка без дополнительных датчиков выглядит завершённой, а не сломанной. |
|
PACKETS |
Сгруппированные счётчики всех типов кадров данных. Потери вычисляются по порядковым номерам пакетов, которые присваивает сам узел, поэтому пропуск — это кадр, который гарантированно ушёл с платы, но до Pi так и не долетел. |
|
DIAGNOSTICS |
Частота опроса должна быть около 100 Гц. При этом ошибки, отброшенные и отклонённые пакеты должны быть на 0. |
На калибровку детекции движения уходит 6 секунд, а на детекцию дыхания 30.
О показателе качества воздуха. При его вычислении используются стандартная шкала AQI (индекс качества воздуха) от 0 до 500, стандартные категории и та же кусочно-линейная интерполяция, что и в настоящем AQI. Отличие в том, что вычисляются эти данные исключительно на основе показаний эквивалента CO2 от датчика MQ135. При расчёте нормативного AQI преобладают твёрдые микрочастицы PM2.5, которые этот датчик вообще не умеет измерять, поэтому даже в задымлённом помещении прибор может сообщать статус «Good». Так что ориентируйтесь на динамику изменения этого значения, а не на саму абсолютную цифру. Подробно этот принцип и работа самокорректирующегося базового уровня объясняются в разделе 6d файла
PROJECT.TXT.
10. Как получить качественные результаты
-
Плата и роутер должны находиться на противоположных сторонах сканируемого пространства. Вы фиксируете то, что происходит между ними, а не вокруг самой платы.
-
Разнесите их на расстояние от 2 до 8 метров.
-
Если сигнал сильнее, это не значит, что он лучше. При очень близком расположении начинает преобладать сигнал по прямому пути, и отражения просто теряются в нём. Уровень RSSI должен быть в диапазоне от -40 до -60 дБм.
-
Усядьтесь где-нибудь посередине, в идеале строго по центру — но не рядом с платой.
-
Для регистрации дыхания требуется неподвижность. Ориентируйтесь по показаниям MOTION, а не собственному ощущению неподвижности: система фиксирует как движение рук при использовании клавиатуры, так и шевеления на стуле. Дыхание начинает обнаруживаться чуть ниже +5 дБ. Если вы двигаетесь, дашборд просто покажет «subject moving» и никаких показаний не выведет, что вполне корректно.
-
Хороший захват сигнала выглядит так: движение (Motion) ниже +5 дБ, жизненные показатели (Vitals) выше +20 дБ, частота плавно меняется на десятые доли, а уровень достоверности (confidence) выше 0,4.
-
Система регистрирует движение вентиляторов, занавесок и животных. Всё это не относится к ложным положительным, так как здесь действительно происходит движение.
11. Все команды в одном месте
Выполните эти команды из каталога pi/.
Сервер
|
Команда |
Действие |
|
|
Запуск через USB-кабель |
|
|
Запуск без оборудования |
|
|
Запуск по радиоканалу 2,4 ГГц |
|
|
Воспроизведение записанного сеанса |
Взаимодействие с платой
|
Команда |
Действие |
|
|
Статус: подключение к сети (ассоциирование), IP-адрес, состояние CSI, частота опроса. |
|
|
Измерение реальной частоты поступления кадров CSI. |
|
|
Конфигурирование параметров WiFi (сохраняются во флэш-памяти). |
|
|
Режим ассоциирования (association) или режим прослушивания (promiscuous). |
|
|
Переключение режима передачи данных (настройка сохраняется во флэш-памяти). |
|
|
Перезапуск узла. |
|
|
Сканирование задокументированных контактов подключения радиомодулей. |
|
|
Поиск радиомодулей на всех доступных GPIO (~20 с). |
Датчики окружающей среды
|
Команда |
Действие |
|
|
Считывание показаний со всех трёх датчиков. |
|
|
Установка базового уровня качества воздуха (выполняйте возле открытого окна). |
|
|
Указание плате, что аналоговый выход ( |
|
|
Указание плате, что |
Проверка корректности
|
Команда |
Действие |
|
tools/validate_dsp.py |
Тестирование всей цепочки детекторов с помощью синтетических данных CSI при заданной частоте дыхания — 81 проверка. Это единственное место, где пайплайн обработки данных можно проверить на ошибочность. Именно этот скрипт запускается системой непрерывной интеграции при каждом обновлении (push) кода. |
REST API
|
Конечная точка |
Возвращает |
|
|
Полный снимок данных в реальном времени. |
|
|
200, если по каналу передаются данные; 503, если нет. |
|
|
Архивированные временные ряды. |
|
|
Отчёт по сну за одну ночь (по умолчанию прошлую). |
|
|
По каким ночам есть данные. |
|
|
Количество сохранённых строк, временной охват и ошибки записи. |
12. Решение типичных проблем
|
Симптом |
Причина и исправление |
|
Нет устройства |
Почти всегда дело в USB-кабеле, который предназначен только для зарядки. Если не он, то выполните команду |
|
Частота опроса ~1Гц вместо ~100 Гц |
Плата не подключена к роутеру, поэтому UDP-запрос от Pi не может до неё дойти. Выполните |
|
Частота опроса равна 0 |
Проверьте статус |
|
Все показатели молчат (CLEAR), хотя в комнате кто-то есть. |
Человек находится не между платой и роутером. Проверьте уровень RSSI: он должен быть в диапазоне от -40 до -60 дБм. |
|
Все показатели активны (ACTIVE) в пустой комнате. |
Значит, движение всё же есть: вентилятор, открытое окно, какое-то животное. Также убедитесь, что плата лежит неподвижно — если она будет висеть на кабеле, будет регистрироваться движение. |
|
Дыхание не распознаётся |
Объект наблюдения должен быть неподвижен в течение 30+ секунд, а частота опроса составлять более ~20 Гц. Сообщение «subject moving» указывает на то, что детектор движения блокирует распознавание дыхания, что абсолютно правильно. |
|
Растёт число ошибок подключения |
Помехи в последовательном порту. Используйте более короткий или более качественный USB-кабель. Имейте в виду, что механизм CRC перехватывает каждый повреждённый кадр, поэтому рост ошибок снижает лишь частоту опроса, но на корректность не влияет. |
|
Панель мониторинга окружающей среды не отображается |
Кадр с данными об окружающей среде не поступал. Обратитесь к плате напрямую: |
|
BMP280 = ABSENT |
Провода |
|
DHT22 = NO-REPLY |
Отсутствует подтягивающий резистор на 10 кОм для отдельного 4-контактного датчика; либо линия DATA не подключена к |
|
MQ135 = OUT-OF-RANGE |
Напряжение около 0 мВ: |
|
Показания качества воздуха застыли на “WARMING UP” |
Для автоматической калибровки прибор должен быть включен как минимум три минуты и выдавать корректные показания. |
|
Служба не запускается |
|
Более подробные объяснения даны в разделе 9 файла PROJECT.txt.
13. Готовая прошивка и образы контейнеров
Прошивка без установки PlatformIO
Каждый релиз сопровождается готовыми для прошивки бинарниками — ищите их на странице Releases. Едины комбинированный образ заливается с нулевого адреса (0x0):
pip install esptool
esptool.py --chip esp32s3 --port /dev/ttyUSB0 --baud 921600
write_flash 0x0 wifisense-firmware-v1.0.0.bin
Сначала проверьте, что именно скачали:
sha256sum -c SHA256SUMS
В бинарном файле содержится временный радиоключ, состоящий из одних нулей. Это абсолютно нормально для работы через USB-кабель, так как данные по нему всё равно передаются без шифрования. Но если вы используете радиоканал, вам потребуется задать собственный ключ и пересобрать проект вручную — готовый бинарный файл не может содержать в себе приватный ключ. См. раздел «Безопасность радиоканала».
Запуск сервера в контейнере
Готовые образы публикуются в GitHub Container Registry для архитектур linux/amd64 и linux/arm64:
# Только дашборд, без оборудования, по адресу http://localhost:8080
docker run --rm -p 8080:8080 ghcr.io/the-masked-bear/wifisense-pi:latest
# С платой, подключенной по USB.
docker run --rm -p 8080:8080 --device /dev/ttyUSB0
ghcr.io/the-masked-bear/wifisense-pi:latest python -m wifisense --link serial
Безопасность радиоканала
Данные CSI позволяют узнать, когда в комнате кто-то есть, когда люди двигаются и когда они спят. Если передавать их в открытом виде, любой человек в радиусе действия радиосигнала, имеющий такой же радиомодуль на том же канале, сможет их перехватить. Поэтому все данные, отправляемые по радиоканалу, шифруются алгоритмом AES-128 в режиме счётчика с генерацией нового случайного идентификатора сессии при каждой загрузке платы и защитой от повтора пакетов.
Сгенерируйте ключ и укажите одно и то же значение на обоих сторонах канала:
python3 -c "import secrets;print(secrets.token_hex(16))"
|
Куда прописывать |
Как |
|
|
|
|
|
32 шестнадцатеричных символа |
При несовпадении ключей счётчик cobs_errors начинает стремительно расти, в то время как показатель frames_ok застывает на нуле. Это обеспечивает конфиденциальность, но не аутентификацию: наличие CRC-16 внутри зашифрованной полезной нагрузки означает, что случайная подделка пакета сработает с вероятностью всего 1/65536. Для домашнего датчика такой защиты вполне достаточно, но полноценным кодом аутентификации сообщения (MAC) это не является.
14. Структура репозитория
PROJECT.txt документация: вся в одном файле
requirements.txt зависимости Python
Dockerfile образ контейнера для сервера на Pi
install.sh установщик автозапуска
systemd/ шаблон службы
firmware/ прошивка ESP32-S3 (PlatformIO)
platformio.ini конфигурация платы. Для N15R8 обязателен режим qio_opi.
src/config.h настраиваемые параметры: режим, контакты, частоты, выключатели датчиков
src/main.cpp захват данных CSI, формирование кадров, обработка команд
src/radio_tx.* передача данных по радиоканалу через nRF24/CC1101, арбитраж шины SPI
src/cc1101_driver.* внутренний драйвер регистров CC1101
src/bmp280.* внутренний SPI-драйвер для BMP280/BME280
src/sensors.* DHT22, MQ135 и фоновая задача для опроса датчиков
src/link_crypto.* алгоритм AES-128-CTR для защиты радиоканала
pi/
wifisense/
protocol.py формат передачи данных: формирование кадров методом COBS, проверка CRC-16, карта поднесущих частот
stimulus.py UDP-генератор запросов, задающий частоту опроса
archive.py долгосрочное хранилище в SQLite + отчёт о сне
spectrum.py мониторинг субгигагерцевого диапазона радиомодуля CC1101
dsp/ csi -> фильтры -> движение / дыхание -> пайплайн вычислений
link/ последовательный порт, nrf24, cc1101, воспроизведение (replay), симулятор
api/server.py FastAPI, WebSocket, REST
web/ дашборб + страница истории. Никакой сборки и зависимостей
tools/node.py утилита для управления ESP32 через командную строку
tools/validate_dsp.py проверка корректности по заданному эталону
Документация
PROJECT.txt — это основной документ, написанный так, чтобы его было удобно читать прямо за рабочим столом вдали от терминала. В нём есть всё: полная схема разводки проводов, настройка, калибровка, поиск неисправностей и обоснование каждой константы в коде. Там же описаны исправленные баги и симптомы, которыми они проявлялись — включая случай, когда из-за нестандартного дыхания человека мощность седьмой гармоники сигнала оказалась на 2,4 дБ выше основной частоты, и алгоритм выбора пиков уверенно выдал частоту дыхания, завышенную в семь раз.
Показатели системы
|
Частота опроса CSI |
100 Гц, 1:1 с частотой UDP-запросов (работает и на 200 Гц) |
|
Пропускная способность кабеля |
149 байтов/кадр, 119 кбит/с (~16% от пропускной способности канала) |
|
Pi CPU |
~20% одного ядра |
|
Пустая комната |
Движение регистрируется на уровне +1,1 дБ, а дыхание на уровне +0.0 дБ |
|
При ходьбе |
Движение регистрируется на уровне +27,8 дБ |
|
Дыхание неподвижного человека |
Дыхание регистрируется на уровне +33,6 дБ |
|
Точность дыхания |
14,1 вдохов/мин против 14.0 эталонных; 22,0 против 22,0 |
|
Зашифрованный канал nRF24 |
Доставлено 108,1 Гц из 113,6 Гц захваченных (95,1% эффективности) |
|
Ошибки последовательного порта |
0 CRC, 0 ошибок фрейминга за всё время длительных испытаний |
|
Проверка DSP |
Пройдено проверок: 81/81 |
Автор: Bright_Translate


