334 lines
12 KiB
Markdown
334 lines
12 KiB
Markdown
# 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 <board_name> -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}
|
||
+<examples/companion_radio/>
|
||
|
||
[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}
|
||
+<examples/companion_radio/>
|
||
```
|
||
|
||
Значения по умолчанию в `[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. Ответ тоже шифрованный, идёт по обратному пути
|