# MeshCore — Relay + DS18B20 на базе Companion Radio ## 1. Что это Модификация прошивки `companion_radio` из MeshCore. Устройство получает по LoRa-мешу приватные команды и управляет реле, а также отвечает на запросы температуры с DS18B20. ## 2. Откуда брать проект ```bash git clone --depth 1 https://github.com/meshcore-dev/MeshCore.git cd MeshCore ``` ## 3. Что нужно установить ### PlatformIO - Установить Python 3 - Установить PlatformIO: `pip install platformio` - Или установить VS Code + расширение PlatformIO ### Зависимости (добавить в platformio.ini) В секцию `[arduino_base]`, в `lib_deps` добавить: ``` paulstoffregen/OneWire @ ^2.3.7 milesburton/DallasTemperature @ ^3.11.0 ``` ## 4. Какие файлы править Базовый проект — `examples/companion_radio/`. ### Файлы для изменения: | Файл | Что делать | |------|------------| | `platformio.ini` | Добавить OneWire и DallasTemperature в lib_deps; для nRF52 добавить env (раздел 7.3) | | `examples/companion_radio/MyMesh.h` | Добавить #include, пины, поле OneWire/DallasTemperature, метод `readTemperature()` | | `examples/companion_radio/MyMesh.cpp` | В конструктор — инициализация OneWire, в begin() — `_tempSensor.begin()`, реализовать `readTemperature()`, изменить `onMessageRecv()` | | `examples/companion_radio/main.cpp` | В `setup()` добавить `pinMode(RELAY_PIN, OUTPUT)` | ### Подключение железа (ESP32): | Пин | Назначение | |-----|------------| | GPIO 4 | Реле (RELAY_PIN) | | GPIO 5 | DS18B20 Data (ONE_WIRE_BUS) | | 3.3V | DS18B20 VCC (через 4.7k подтяжку к Data) | | GND | Общий | ### Параметры радио (ESP32) В `platformio.ini` в вашей env-секции (например `[env:esp32dev_companion_radio_usb]`) переопределить: ```ini build_flags = ${arduino_base.build_flags} -D LORA_FREQ=868.731018 -D LORA_BW=62.5 -D LORA_SF=7 -D LORA_CR=7 ``` Для хэша пути 1 байт в `MyMesh.cpp` в конструкторе указать: ```cpp _prefs.path_hash_mode = 0; ``` Для **nRF52840 (XIAO)** пины по умолчанию: `RELAY_PIN = D6 (P0.08)`, `ONE_WIRE_BUS = D7 (P0.09)` — смотрите раздел 7.2. ### Автоматическая отправка advertise каждые 30 минут В `MyMesh.h` добавить поле: ```cpp float readTemperature(); private: unsigned long _next_advert_ms; OneWire _oneWire; DallasTemperature _tempSensor; ``` В `MyMesh.cpp` в конструкторе инициализировать: ```cpp MyMesh::MyMesh(...) : BaseChatMesh(...), _oneWire(ONE_WIRE_BUS), _tempSensor(&_oneWire) { _next_advert_ms = 0; // ... остальной код ... } ``` В `MyMesh::loop()` (или в `main.cpp` в `loop()`) добавить проверку таймера: ```cpp void MyMesh::loop() { BaseChatMesh::loop(); // существующий вызов // advertise каждые 30 минут (1800000 мс) if (millisHasNowPassed(_next_advert_ms)) { advert(); _next_advert_ms = futureMillis(1800000); } } ``` Либо ещё проще — в `main.cpp`: ```cpp void loop() { static unsigned long next_advert = 0; the_mesh.loop(); sensors.loop(); // ... остальной код ... if (millisHasNowPassed(next_advert)) { the_mesh.advert(); next_advert = futureMillis(1800000); } } ``` ## 5. Команды (приватные сообщения узлу) | Команда | Ответ | Действие | |---------|-------|----------| | `on1234` | `relay on` | Реле включено | | `off1234` | `relay off` | Реле выключено | | `temp` | `temp: 23.5 C` | Температура с DS18B20 | | `state` | `temp: 23.5 C, relay: ON` | Температура + состояние реле | Цифра `1234` — код доступа к реле (можно сменить в `RELAY_CODE`). ## 6. Как залить ```bash cd MeshCore # для конкретной платы, например ESP32: pio run -e -t upload # или открыть в VS Code + PlatformIO и собрать через IDE ``` ## 7. Версия для nRF52840 + HT-RA62 (SX1262) ### 7.1 Что за связка **nRF52840** — популярный MCU с BLE. **HT-RA62** — LoRa-модуль на чипе SX1262 (аналог E22-900Mxx). Можно использовать любую плату на nRF52840 + внешний HT-RA62 по SPI. Самый популярный вариант — **Seeed XIAO nRF52840** + HT-RA62 на макетной плате. ### 7.2 Распиновка XIAO nRF52840 + HT-RA62 | Пин XIAO | GPIO nRF52 | HT-RA62 | Назначение | |----------|------------|---------|------------| | D0 | P0.02 | NSS | CS (SPI chip select) | | D1 | P0.03 | DIO1 | IRQ (прерывание) | | D2 | P0.04 | BUSY | Занятость модуля | | D3 | P0.05 | RESET | Сброс | | D4 | P0.06 | RXEN | Включение RX (если есть) | | D5 | P0.07 | TXEN | Включение TX (если есть) | | D6 | P0.08 | (свободен) | **Реле (RELAY_PIN)** | | D7 | P0.09 | (свободен) | **DS18B20 Data (ONE_WIRE_BUS)** | | D8 | P0.10 | SCK | SPI clock | | D9 | P0.28 | MO | SPI MOSI | | D10 | P0.02 | MI | SPI MISO | | 3.3V | — | VCC | 3.3V питание | | GND | — | GND | Общий | > **Важно:** У HT-RA62 DIO2 настроен как RF-переключатель, DIO3 — 1.8V для TCXO (задаётся в коде). **Свободные пины XIAO nRF52840 после подключения:** | Пин | Назначение | Можно | |-----|------------|-------| | D0 (P0.01) | GPIO | цифровой вход/выход | | D5 (P0.06) | RXEN (HT-RA62) | **да** — если RXEN не используется (у HT-RA62 коммутация RF уже через DIO2) | | A0 (P0.31) | ADC/GPIO | аналоговый или цифровой | | A1 (P0.29) | ADC/GPIO | аналоговый или цифровой | | A2 (P0.30) | ADC/GPIO | аналоговый или цифровой | **Занято:** D1(IRQ), D2(BUSY), D3(RESET), D4(NSS), D6(реле), D7(DS18B20), D8(SCK), D9(MOSI), D10(MISO) — 9 пинов. **Свободно:** 4–5 пинов (D0, D5, A0, A1, A2) для кнопок, светодиодов или доп. датчиков. ### 7.3 Что добавить в platformio.ini В конец файла `platformio.ini` дописать: ```ini ; ===== nRF52840 + HT-RA62 (SX1262) ===== [Xiao_nrf52] extends = nrf52_base board = seeed-xiao-afruitnrf52-nrf52840 board_build.ldscript = boards/nrf52840_s140_v7.ld build_flags = ${nrf52_base.build_flags} -D USE_SX1262 -D LORA_TX_POWER=22 -D ADVERT_NAME="Relay" -D LORA_FREQ=868.731018 -D LORA_BW=62.5 -D LORA_SF=7 -D LORA_CR=7 [env:Xiao_nrf52_companion_radio_usb] extends = Xiao_nrf52 build_src_filter = ${nrf52_base.build_src_filter} + [env:Xiao_nrf52_companion_radio_ble] extends = Xiao_nrf52 build_flags = ${Xiao_nrf52.build_flags} -D BLE_PIN_CODE=123456 build_src_filter = ${nrf52_base.build_src_filter} + ``` Значения по умолчанию в `[arduino_base]` переопределяются в `Xiao_nrf52`. ### 7.3.1 Хэш пути 1 байт В `MyMesh.h` перед классом `MyMesh` добавить: ```cpp #define ADVERT_NAME "Relay" // хэш пути — 1 байт (mode 0) ``` В конструкторе `MyMesh` (в `MyMesh.cpp`) явно установить `path_hash_mode`: ```cpp _prefs.path_hash_mode = 0; // 0 = 1 байт, 1 = 2 байта, 2 = 3 байта ``` Либо в `main.cpp` можно задать через define и использовать в `platformio.ini`: ```ini -D PATH_HASH_MODE=0 ``` а в `MyMesh.cpp`: ```cpp #ifndef PATH_HASH_MODE #define PATH_HASH_MODE 0 #endif ... _prefs.path_hash_mode = PATH_HASH_MODE; ``` ### 7.3.2 Итоговые параметры радио | Параметр | Значение | |----------|----------| | Частота | 868.731018 МГц | | Полоса (BW) | 62.5 кГц | | Spreading Factor | 7 | | Coding Rate | 7 | | Хэш пути | 1 байт | ### 7.4 Как собрать и прошить ```bash export FIRMWARE_VERSION=v1.0.0 # Собрать прошивку (USB Serial) pio run -e Xiao_nrf52_companion_radio_usb # Собрать прошивку (BLE) pio run -e Xiao_nrf52_companion_radio_ble # После сборки .uf2 файл будет здесь: # .pio/build/Xiao_nrf52_companion_radio_usb/firmware.uf2 ``` **Способы прошивки nRF52840:** | Метод | Описание | |-------|----------| | **UF2 (drag-and-drop)** | Подключить плату в режиме UF2 (двойной тап по кнопке reset), скопировать `.uf2` на появившийся диск | | **pio run -t upload** | Через PlatformIO (nrfutil) | | **через J-Link** | `pio run -e Xiao_nrf52_companion_radio_usb -t upload --upload-port jlink` | | **OTA по BLE** | Через приложение Adafruit Bluefruit (если собран `_ble` вариант) | ### 7.5 Если HT-RA62 подключен к другой плате Найдите в `variants/` свою плату или создайте свою. Для HT-RA62 везде одинаковые настройки SX1262: ```cpp #define SX126X_DIO2_AS_RF_SWITCH 1 #define SX126X_DIO3_TCXO_VOLTAGE 1.8 #define SX126X_CURRENT_LIMIT 140 #define SX126X_RX_BOOSTED_GAIN 1 ``` Пины SPI (SCK, MOSI, MISO) общие с остальной периферией. NSS, DIO1, BUSY, RESET — назначаются индивидуально. ### 7.6 Альтернативные платформы с nRF52840 Если HT-RA62 уже впаян в готовую плату — проверьте `variants/`, возможно ваша плата уже там: | Плата | Вариант | Пример env | |-------|---------|------------| | RAK4631 WisBlock | `rak4631` | `env:RAK_4631_companion_radio_ble` | | Nologo ProMicro nRF52840 | `promicro` | `env:ProMicro_repeater` | | Nano G2 Ultra | `nano_g2_ultra` | `env:Nano_G2_Ultra_companion_radio_ble` | | RAK3401 (1W) | `rak3401` | `env:RAK_3401_repeater` | Список всех nRF52-вариантов — в `variants/`. ## 8. Структура проекта (кратко) ``` MeshCore/ ├── src/ # ядро библиотеки │ ├── Mesh.h / .cpp # роутинг, диспетчеризация payload-типов │ ├── Packet.h / .cpp # формат пакета │ ├── Dispatcher.h / .cpp # планировщик радио │ └── helpers/ │ └── BaseChatMesh.h/.cpp # чат-абстракция (родительский класс) ├── examples/ │ └── companion_radio/ # ТО, ЧТО МЫ МОДИФИЦИРУЕМ │ ├── MyMesh.h / .cpp # основной класс │ ├── main.cpp # точка входа │ └── ... └── platformio.ini # конфиг сборки ``` ## 9. Как это работает (кратко) 1. Узел-отправитель знает публичный ключ устройства с реле (контакт добавлен через advertise) 2. Он отправляет `sendMessage(recipient, timestamp, 0, "on1234", ...)` 3. Пакет шифруется AES128+HMAC, летит по mesh (flood routing) 4. Устройство-исполнитель получает, расшифровывает, `BaseChatMesh` вызывает `onMessageRecv()` 5. Мы проверяем текст, управляем реле/читаем температуру и шлём ответ 6. Ответ тоже шифрованный, идёт по обратному пути