Цель: создать автономную систему охраны периметра лагеря с питанием от прикуривателя. Используем 10 шт. REDMOND RSM-41S — BLE-датчики движения с питанием от CR123A. Центр — ESP32 как BLE-сканер и хаб. При срабатывании — уведомление на телефон.
Датчики REDMOND RSM-41S не подключаются к ESP32 как периферия. Они работают в режиме BLE-рекламы (advertising) и периодически шлют пакеты: «Я — датчик движения, и я сработал!».
ESP32 находится в режиме BLE-сканера. Он ловит рекламные пакеты, фильтрует по MAC-адресу и содержимому, и при обнаружении события движения — отправляет уведомление.
У каждого датчика — уникальный BLE MAC-адрес. Чтобы не путать 10 штук, нужно:
Пример: MAC a4:c1:38:12:34:56 → датчик у палатки.
Используем библиотеку NimBLE-Arduino — она легче и стабильнее стандартной BLE-библиотеки.
#include <NimBLEDevice.h>
// Сопоставление MAC → название
struct Sensor {
uint8_t mac[6];
const char* name;
};
Sensor sensors[] = {
{{0xA4, 0xC1, 0x38, 0x12, 0x34, 0x56}, "Север"},
{{0xA4, 0xC1, 0x38, 0xAB, 0xCD, 0xEF}, "Юг"},
// ... добавь остальные 8
};
const int sensorCount = sizeof(sensors) / sizeof(Sensor);
void scanCallback(NimBLEScanResults results) {
for (int i = 0; i < results.getCount(); i++) {
NimBLEAdvertisedDevice device = results.getDevice(i);
const uint8_t* mac = device.getAddress().getNative();
// Ищем совпадение по MAC
for (int s = 0; s < sensorCount; s++) {
if (memcmp(mac, sensors[s].mac, 6) == 0) {
// Анализируем advertising-данные
std::string data = device.getManufacturerData();
if (!data.empty()) {
// REDMOND кладёт флаг движения в байт [4] (пример!)
// Нужно исследовать: включи датчик и посмотри hex-дамп
if (data.length() > 4 && (data[4] & 0x01)) {
Serial.printf("🚨 Сработал датчик: %s (%s)\n", sensors[s].name, device.getAddress().toString().c_str());
sendNotification(sensors[s].name);
}
}
break;
}
}
}
}
void sendNotification(const char* sensorName) {
// Варианты:
// 1. Включить светодиод или зуммер
// 2. Отправить BLE-уведомление на телефон
// 3. Сохранить в лог на microSD
// 4. Отправить по Bluetooth Serial (если телефон подключён)
}
void setup() {
Serial.begin(115200);
BLEDevice::init("");
NimBLEScan* pScan = BLEDevice::getScan();
pScan->setActiveScan(false); // пассивный скан — меньше энергии
pScan->setInterval(97); // интервал сканирования (ms)
pScan->setWindow(30); // окно (должно быть <= interval)
pScan->setAdvertisedDeviceCallbacks(new NimBLEAdvertisedDeviceCallbacks() {
void onResult(NimBLEAdvertisedDevice* device) override {
// Не используем — обрабатываем пачкой в scanCallback
}
});
pScan->start(0, scanCallback, false); // бесконечный скан
}
void loop() {
delay(1000);
}
Варианты:
ALERT:Север, а телефон читает как COM-порт.Рекомендую начать с BLE UART — это проще всего.
Удачи в реализации! Когда появятся силы — система уже будет почти готова 😉
Блог только запустил, все статьи генерирую через нейросеть т.к. лень, возможны ошибки. Просто чтобы вы знали и не запускали ядерный реактор по моим статьям ))
Если у вас есть вопросы, или Нашли неточность? пишите в коментах — вместе поправим и сделаем статью более качественной. Я лично объясню нюансы из практики.
Комментарии
Пока нет комментариев. Будьте первым!