init: спецификация протокола WegaBox ↔ ponics.online
MQTT топики, REST API, поведение устройства, маппинг датчиков. Mermaid диаграммы: flow подключения, обработка сообщений, FSM устройства.
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
# Device Behavior
|
||||
|
||||
## Конечный автомат устройства
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Booting: Включение питания
|
||||
Booting --> WiFiConnect: Инициализация
|
||||
WiFiConnect --> MQTTConnect: WiFi OK
|
||||
WiFiConnect --> WiFiConnect: Retry (30s)
|
||||
MQTTConnect --> Connected: MQTT OK
|
||||
MQTTConnect --> MQTTConnect: Retry (10s)
|
||||
|
||||
Connected --> Publishing: Таймер сбора данных
|
||||
Publishing --> Connected: Данные отправлены
|
||||
|
||||
Connected --> ExecutingCmd: Получена команда
|
||||
ExecutingCmd --> Connected: Команда выполнена
|
||||
|
||||
Connected --> Disconnected: Потеря связи
|
||||
Disconnected --> MQTTConnect: Reconnect
|
||||
|
||||
Connected --> [*]: Команда reboot / WDT reset
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Последовательность запуска
|
||||
|
||||
1. **Boot** — инициализация I2C, SPI, OneWire периферии
|
||||
2. **WiFi** — подключение, получение IP
|
||||
3. **MQTT connect** — handshake с брокером
|
||||
4. **Publish `{UID}/status = "connected"`** — уведомление сервера
|
||||
5. **Получить preferences** — сервер отвечает `{UID}/set/preferences/all`
|
||||
6. **Применить калибровку** — записать коэффициенты в память
|
||||
7. **Запуск основного цикла** — периодический сбор и публикация данных
|
||||
|
||||
---
|
||||
|
||||
## Периодичность публикации данных
|
||||
|
||||
| Датчик | Интервал |
|
||||
|--------|----------|
|
||||
| pH, EC, Temp | ~10 сек |
|
||||
| AirTemp, AirHum | ~30 сек |
|
||||
| RSSI, uptime | ~60 сек |
|
||||
| MixerWeight | ~5 сек (если mixer_enabled) |
|
||||
| readGPIO | при изменении |
|
||||
|
||||
---
|
||||
|
||||
## Обработка команд
|
||||
|
||||
Все команды **fire-and-forget** — ответ не отправляется.
|
||||
|
||||
### `cmd/reboot`
|
||||
1. Завершить активные операции помп (стоп)
|
||||
2. `ESP.restart()`
|
||||
|
||||
### `cmd/gpio/{pin}`
|
||||
1. Проверить pin ∈ [0, 15]
|
||||
2. MCP23017 → setPin(pin, state)
|
||||
|
||||
### `set/pump/{id}/run`
|
||||
1. Проверить id ∈ [1, 8], time ∈ [1, 60000]
|
||||
2. Включить помпу
|
||||
3. Запустить таймер
|
||||
4. По истечении времени — выключить
|
||||
|
||||
### `set/pump/{id}/dispense`
|
||||
1. Проверить id ∈ [1, 8], grams ∈ [0.1, 1000]
|
||||
2. Рассчитать время через `ml/sec` калибровку помпы
|
||||
3. Включить → таймер → выключить
|
||||
4. Обновить счётчик `total_dispensed`
|
||||
|
||||
### `cmd/pump/{id}/stop`
|
||||
1. Немедленно выключить помпу
|
||||
2. Сбросить таймер
|
||||
|
||||
### `set/preferences/all`
|
||||
1. Разобрать JSON
|
||||
2. Обновить только пришедшие поля в NVS / RAM
|
||||
3. Применить новые коэффициенты калибровки без перезагрузки
|
||||
|
||||
---
|
||||
|
||||
## Reconnect логика
|
||||
|
||||
- WiFi: авто-реконнект встроенный в ESP-IDF
|
||||
- MQTT: переподключение каждые 10 секунд
|
||||
- При восстановлении MQTT: снова публикует `{UID}/status = "connected"`
|
||||
- Сервер снова отправляет preferences (идемпотентно)
|
||||
|
||||
---
|
||||
|
||||
## OTA обновления
|
||||
|
||||
URL прошивки: `preferences.updateUrl`
|
||||
По умолчанию: `https://ponics.online/static/wegabox/esp32-local/firmware.bin`
|
||||
|
||||
Триггер обновления: команда (TBD) или автоматически при запуске если новая версия.
|
||||
@@ -0,0 +1,226 @@
|
||||
# MQTT Protocol
|
||||
|
||||
## Общее
|
||||
|
||||
- **Брокер**: Mosquitto 2.x (порт 1883)
|
||||
- **Topic prefix**: `{UID}` — UUID токен устройства (из БД `GrowBox.token`)
|
||||
- **QoS**: 1 для команд, 0 для данных датчиков
|
||||
- **Subscribe**: сервер подписан на `#` (все топики)
|
||||
|
||||
---
|
||||
|
||||
## Flow: подключение устройства
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant ESP32 as WegaBox (ESP32)
|
||||
participant MQTT as MQTT Broker
|
||||
participant Django as ponics.online (Django)
|
||||
participant Redis
|
||||
|
||||
ESP32->>MQTT: publish {UID}/status = "connected"
|
||||
MQTT->>Django: forward
|
||||
Django->>Django: push_box_settings(box)
|
||||
Django->>MQTT: publish {UID}/set/preferences/all = {JSON}
|
||||
MQTT->>ESP32: apply calibration & config
|
||||
|
||||
loop Каждые N секунд
|
||||
ESP32->>MQTT: publish {UID}/data-timescale/EC = "1.85"
|
||||
ESP32->>MQTT: publish {UID}/data-timescale/ph = "6.2"
|
||||
ESP32->>MQTT: publish {UID}/data-timescale/wNTC = "22.5"
|
||||
MQTT->>Django: forward
|
||||
Django->>Redis: update live cache (boxconfig-{token})
|
||||
Django->>Django: batch → TimescaleDB (каждые 25с или 100 метрик)
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Flow: команда с веб-интерфейса
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as Браузер
|
||||
participant Django as ponics.online (Django)
|
||||
participant MQTT as MQTT Broker
|
||||
participant ESP32 as WegaBox (ESP32)
|
||||
|
||||
User->>Django: POST /api/box/{id}/pump/run/ {pump_id:1, time_ms:5000}
|
||||
Django->>MQTT: publish {UID}/set/pump/1/run = "5000"
|
||||
MQTT->>ESP32: execute pump 1 for 5000ms
|
||||
Django->>User: 200 {"success": true}
|
||||
Note over ESP32: Команды fire-and-forget, ответа нет
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Топики: устройство → сервер (Subscribe)
|
||||
|
||||
### `{UID}/data-timescale/{METRIC_NAME}`
|
||||
|
||||
Основной поток данных датчиков. Каждый датчик — отдельное сообщение.
|
||||
|
||||
**Payload**: строка с числом (например `"6.24"`, `"1.85"`, `"22.5"`)
|
||||
|
||||
```
|
||||
{UID}/data-timescale/EC → значение EC (мСм/см)
|
||||
{UID}/data-timescale/ph → значение pH
|
||||
{UID}/data-timescale/wNTC → температура воды (°C, откалиброванная)
|
||||
{UID}/data-timescale/AirTemp → температура воздуха (°C)
|
||||
{UID}/data-timescale/AirHum → влажность воздуха (%)
|
||||
{UID}/data-timescale/AirPress → давление (гПа)
|
||||
{UID}/data-timescale/RootTemp → температура субстрата/корней (°C, DS18B20)
|
||||
{UID}/data-timescale/calc_dist → уровень воды (см/%)
|
||||
{UID}/data-timescale/calc_pr → освещённость (%)
|
||||
{UID}/data-timescale/RSSI → уровень WiFi сигнала (dBm)
|
||||
{UID}/data-timescale/uptime → аптайм устройства (мс)
|
||||
{UID}/data-timescale/MixerWeight → вес миксера (г)
|
||||
{UID}/data-timescale/readGPIO → битовая маска GPIO MCP23017 (0-65535)
|
||||
```
|
||||
|
||||
### `{UID}/status`
|
||||
|
||||
Payload: строка `"connected"` — устройство подключилось к брокеру.
|
||||
Триггер: сервер отправляет настройки (`set/preferences/all`).
|
||||
|
||||
### `{UID}/status/sensors`
|
||||
|
||||
Ответ на запрос `{UID}/cmd/status/sensors`.
|
||||
|
||||
```json
|
||||
{
|
||||
"ph": 6.24,
|
||||
"ec": 1.85,
|
||||
"temp_cal": 22.5,
|
||||
"calc_dist": 45.2,
|
||||
"airTemp": 24.1,
|
||||
"airHumidity": 65.0,
|
||||
"RSSI": -65,
|
||||
"uptime": 3600000
|
||||
}
|
||||
```
|
||||
|
||||
### `{UID}/status/mixer`
|
||||
|
||||
Ответ на запрос `{UID}/cmd/status/mixer`.
|
||||
|
||||
```json
|
||||
{
|
||||
"pumps": [
|
||||
{"index": 0, "name": "CaNO3", "total_dispensed": 480.5},
|
||||
{"index": 1, "name": "KNO3", "total_dispensed": 320.0},
|
||||
{"index": 2, "name": "MgSO4", "total_dispensed": 150.0}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `{UID}/main` (legacy)
|
||||
|
||||
Устаревший формат, поддерживается для обратной совместимости. Новые устройства не используют.
|
||||
|
||||
```json
|
||||
{
|
||||
"sensors": {
|
||||
"ph": "6.5",
|
||||
"ec": "1.8",
|
||||
"temp_cal": "22.5"
|
||||
},
|
||||
"system": {
|
||||
"uptime": "3600000",
|
||||
"RSSI": "-65"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Топики: сервер → устройство (Publish)
|
||||
|
||||
### Команды (`cmd/`)
|
||||
|
||||
| Топик | Payload | Описание |
|
||||
|-------|---------|----------|
|
||||
| `{UID}/cmd/reboot` | `"1"` | Перезагрузка устройства |
|
||||
| `{UID}/cmd/gpio/{pin}` | `"1"` / `"0"` | GPIO HIGH/LOW (MCP23017, pin 0–15) |
|
||||
| `{UID}/cmd/pump/{id}/stop` | `"1"` | Стоп помпы (id 1–8) |
|
||||
| `{UID}/cmd/status` | `"1"` | Запрос полного статуса |
|
||||
| `{UID}/cmd/status/sensors` | `"1"` | Запрос данных датчиков |
|
||||
| `{UID}/cmd/status/actuators` | `"1"` | Запрос статуса актуаторов |
|
||||
| `{UID}/cmd/status/mixer` | `"1"` | Запрос статуса миксера |
|
||||
|
||||
### Управление помпами (`set/pump/`)
|
||||
|
||||
| Топик | Payload | Ограничения |
|
||||
|-------|---------|------------|
|
||||
| `{UID}/set/pump/{id}/run` | `"5000"` (мс) | id: 1–8, время: 1–60000 мс |
|
||||
| `{UID}/set/pump/{id}/dispense` | `"50.5"` (граммы) | id: 1–8, граммы: 0.1–1000 |
|
||||
|
||||
### Настройки (`set/preferences/all`)
|
||||
|
||||
Полная конфигурация устройства. Отправляется при подключении или изменении настроек.
|
||||
|
||||
```json
|
||||
{
|
||||
"ntcDAC": 4095,
|
||||
"ntcB": 3950,
|
||||
"ntcValKorr": 0.0,
|
||||
"ntcType": "NTC3950",
|
||||
"R1": 10000,
|
||||
"Rx1": 1000,
|
||||
"Rx2": 1000,
|
||||
"Dr": 1.0,
|
||||
"ec1": 1.41,
|
||||
"ec2": 12.88,
|
||||
"ex1": 0.5,
|
||||
"ex2": 0.9,
|
||||
"kt": 0.019,
|
||||
"ecKorr": 1.0,
|
||||
"px1": 100,
|
||||
"px2": 580,
|
||||
"px3": 1023,
|
||||
"py1": 0.0,
|
||||
"py2": 7.0,
|
||||
"py3": 14.0,
|
||||
"pHlKorr": 0.0,
|
||||
"maxLLevel": 30.0,
|
||||
"maxLRaw": 100,
|
||||
"minLLevel": 10.0,
|
||||
"minLRaw": 500,
|
||||
"hostname": "wega-box-1",
|
||||
"updateUrl": "https://ponics.online/static/wegabox/esp32-local/firmware.bin",
|
||||
"ds18b20_enabled": true,
|
||||
"bme280_enabled": true,
|
||||
"ec_enabled": true,
|
||||
"mixer_enabled": false,
|
||||
"mixer_pumpCount": 8,
|
||||
"hx711_calibrationA": 1000.0,
|
||||
"hx711_calibrationB": 500.0,
|
||||
"ecDoser_enabled": false,
|
||||
"ecDoser_intervalSec": 3600,
|
||||
"ecDoser_limitEC": 3.0
|
||||
}
|
||||
```
|
||||
|
||||
**Все поля опциональны** — устройство применяет только те, что пришли.
|
||||
|
||||
---
|
||||
|
||||
## Обработка сообщений на сервере
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
MSG[MQTT сообщение] --> CHECK{Суффикс топика}
|
||||
CHECK -->|"main"| REDIS[Redis hash-store]
|
||||
CHECK -->|"status/mixer"| MIXER[Обновить статус миксера]
|
||||
CHECK -->|"status/sensors"| SENS[Обновить кеш датчиков]
|
||||
CHECK -->|"status" + "connected"| SYNC[push_box_settings → отправить преференции]
|
||||
CHECK -->|"data-timescale/{METRIC}"| PROC[MessageProcessor]
|
||||
|
||||
PROC --> PARSE[Парсинг значения]
|
||||
PARSE --> MAP[Маппинг имени поля]
|
||||
MAP --> BATCH[Batcher<br/>100 метрик / 25 сек]
|
||||
BATCH --> TSDB[(TimescaleDB)]
|
||||
MAP --> CACHE[Redis live cache<br/>boxconfig-{token}]
|
||||
CACHE --> COND{Проверка условий}
|
||||
COND -->|Сработало| TG[Telegram уведомление]
|
||||
```
|
||||
@@ -0,0 +1,37 @@
|
||||
# ponics-protocol
|
||||
|
||||
Единый источник истины для коммуникации между **ponics.online** (сервер) и **WegaBox** (ESP32 устройство).
|
||||
|
||||
## Репозитории
|
||||
|
||||
| Репо | Описание |
|
||||
|------|----------|
|
||||
| [web-calc](https://gitea.progl.su/progl/web-calc) | Django backend + frontend (ponics.online) |
|
||||
| [wega-box](https://gitea.progl.su/progl/wega-box) | Прошивка ESP32 |
|
||||
| **ponics-protocol** (этот репо) | Спецификация протокола |
|
||||
|
||||
## Документация
|
||||
|
||||
- [MQTT.md](MQTT.md) — Топики, payload схемы, flow диаграммы
|
||||
- [REST_API.md](REST_API.md) — HTTP API эндпоинты
|
||||
- [DEVICE_BEHAVIOR.md](DEVICE_BEHAVIOR.md) — Конечный автомат устройства
|
||||
- [SENSORS.md](SENSORS.md) — Поля датчиков, маппинг имён
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
```
|
||||
Device UID = token устройства (UUID формат)
|
||||
MQTT Broker = ponics.online:1883
|
||||
Аутентификация = username/password (в настройках устройства)
|
||||
```
|
||||
|
||||
### Ключевые топики
|
||||
|
||||
```
|
||||
{UID}/data-timescale/{METRIC} ← устройство шлёт данные датчиков
|
||||
{UID}/status ← устройство шлёт "connected"
|
||||
{UID}/cmd/reboot → сервер перезагружает устройство
|
||||
{UID}/set/pump/{id}/run → сервер запускает помпу (мс)
|
||||
{UID}/set/pump/{id}/dispense → сервер наливает граммы
|
||||
{UID}/set/preferences/all → сервер синхронизирует настройки
|
||||
```
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
# REST API
|
||||
|
||||
Base URL: `https://ponics.online/api/box/`
|
||||
|
||||
Аутентификация: сессия Django (cookie) или токен.
|
||||
|
||||
---
|
||||
|
||||
## Эндпоинты
|
||||
|
||||
### GET `/api/box/`
|
||||
Список боксов текущего пользователя.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 23,
|
||||
"name": "Бокс №1",
|
||||
"token": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"online": true,
|
||||
"last_seen": "2026-05-03T08:00:00Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### GET `/api/box/{id}/`
|
||||
Детали бокса с конфигурацией.
|
||||
|
||||
---
|
||||
|
||||
### GET `/api/box/{id}/live/`
|
||||
Живые данные датчиков из Redis-кеша.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"ph": 6.24,
|
||||
"ec": 1.85,
|
||||
"tankTemp": 22.5,
|
||||
"rootTemp": 21.0,
|
||||
"airTemp": 24.1,
|
||||
"airHumidity": 65.0,
|
||||
"waterLevel": 45.2,
|
||||
"light": 80.0,
|
||||
"online": true,
|
||||
"last_seen": "2026-05-03T08:01:23Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### POST `/api/box/{id}/reboot/`
|
||||
Перезагрузка устройства.
|
||||
|
||||
**Request:** `{}` (пустой body)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{"success": true, "message": "Команда reboot отправлена", "command": "reboot"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### POST `/api/box/{id}/gpio/`
|
||||
Управление GPIO (MCP23017).
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{"pin": 5, "state": true}
|
||||
```
|
||||
- `pin`: 0–15
|
||||
- `state`: `true` (HIGH) / `false` (LOW)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{"success": true, "command": "gpio", "pin": 5, "state": true}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### POST `/api/box/{id}/pump/run/`
|
||||
Запуск помпы на заданное время.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{"pump_id": 1, "time_ms": 5000}
|
||||
```
|
||||
- `pump_id`: 1–8
|
||||
- `time_ms`: 1–60000
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{"success": true, "command": "pump_run", "pump_id": 1, "time_ms": 5000}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### POST `/api/box/{id}/pump/dispense/`
|
||||
Налить определённое количество граммов.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{"pump_id": 2, "grams": 50.5}
|
||||
```
|
||||
- `pump_id`: 1–8
|
||||
- `grams`: 0.1–1000
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{"success": true, "command": "pump_dispense", "pump_id": 2, "grams": 50.5}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### POST `/api/box/{id}/pump/stop/`
|
||||
Остановить помпу.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{"pump_id": 1}
|
||||
```
|
||||
- `pump_id`: 1–8
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{"success": true, "command": "pump_stop", "pump_id": 1}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### POST `/api/box/{id}/preferences/`
|
||||
Обновить настройки и калибровку устройства.
|
||||
|
||||
**Request:** JSON с любыми полями из [MQTT.md → set/preferences/all](MQTT.md#настройки-setpreferencesall)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Настройки отправлены (3 полей)",
|
||||
"fields": ["ecKorr", "pHlKorr", "ntcValKorr"]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Коды ошибок
|
||||
|
||||
| HTTP | Описание |
|
||||
|------|----------|
|
||||
| 400 | Неверные параметры (pin/pump_id/time вне диапазона) |
|
||||
| 503 | MQTT недоступен |
|
||||
| 404 | Бокс не найден / нет доступа |
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
# Sensors & Field Mapping
|
||||
|
||||
## Основные поля (live data)
|
||||
|
||||
Эти поля публикуются в `{UID}/data-timescale/{FIELD}` и доступны через `/api/box/{id}/live/`.
|
||||
|
||||
| API поле | MQTT имена (синонимы) | Единица | Описание |
|
||||
|----------|----------------------|---------|----------|
|
||||
| `ph` | `ph`, `wpH`, `pH` | 0–14 | pH раствора (откалиброванный) |
|
||||
| `ec` | `ec`, `wEC`, `EC` | мСм/см | EC раствора (откалиброванный) |
|
||||
| `tankTemp` | `temp_cal`, `wNTC`, `waterTemp` | °C | Температура воды (NTC, откалиброванная) |
|
||||
| `rootTemp` | `rootTemp`, `RootTemp` | °C | Температура субстрата (DS18B20) |
|
||||
| `airTemp` | `airTemp`, `AirTemp` | °C | Температура воздуха (BME280) |
|
||||
| `airHumidity` | `airHumidity`, `AirHum` | % | Влажность воздуха (BME280) |
|
||||
| `waterLevel` | `calc_dist`, `Dist`, `wLevel` | % или см | Уровень воды (HC-SR04) |
|
||||
| `light` | `calc_pr`, `PR` | % | Освещённость (фоторезистор) |
|
||||
|
||||
## Системные поля
|
||||
|
||||
| MQTT поле | Единица | Описание |
|
||||
|-----------|---------|----------|
|
||||
| `RSSI` | dBm | Уровень WiFi сигнала |
|
||||
| `uptime` | мс | Аптайм устройства |
|
||||
| `CPUTemp` | °C | Температура процессора ESP32 |
|
||||
| `freeHeap` | байт | Свободная RAM |
|
||||
| `MixerWeight` | г | Вес в миксере (HX711) |
|
||||
| `readGPIO` | 0–65535 | Битовая маска GPIO MCP23017 |
|
||||
|
||||
## Сырые / отладочные поля
|
||||
|
||||
| MQTT поле | Описание |
|
||||
|-----------|----------|
|
||||
| `NTC` | Сырое значение АЦП NTC |
|
||||
| `pHmV` | pH в милливольтах |
|
||||
| `pHraw` | Сырое значение АЦП pH |
|
||||
| `ec_no_termo` | EC без температурной компенсации |
|
||||
| `AirPress` | Атмосферное давление (гПа) |
|
||||
| `Vcc` | Напряжение питания (мВ) |
|
||||
| `hall` | Датчик Холла ESP32 |
|
||||
| `CO2` | CO2 (ppm) |
|
||||
| `tVOC` | Летучие вещества |
|
||||
| `PumpA_SUM`, `PumpB_SUM` | Суммарный объём помп |
|
||||
|
||||
## Калибровка
|
||||
|
||||
### pH
|
||||
|
||||
```
|
||||
Точки: (px1, py1), (px2, py2), (px3, py3)
|
||||
ADC → pH = кусочно-линейная интерполяция
|
||||
Корректировка: pH_final = pH + pHlKorr
|
||||
```
|
||||
|
||||
### EC
|
||||
|
||||
```
|
||||
Точки калибровки: ec1 (1.41 мСм/см), ec2 (12.88 мСм/см)
|
||||
Соответствующие ADC значения: ex1, ex2
|
||||
Температурная компенсация: EC_25 = EC_T / (1 + kt * (T - 25))
|
||||
Корректировка: ecKorr (множитель, default = 1.0)
|
||||
```
|
||||
|
||||
### Температура воды (NTC)
|
||||
|
||||
```
|
||||
Тип: NTC3950 (ntcType)
|
||||
B-коэффициент: ntcB = 3950
|
||||
R1 = 10000 Ом
|
||||
Корректировка: ntcValKorr (offset °C, default = 0.0)
|
||||
```
|
||||
|
||||
### Уровень воды (HC-SR04)
|
||||
|
||||
```
|
||||
maxLLevel → maxLRaw (100% → ADC значение)
|
||||
minLLevel → minLRaw (0% → ADC значение)
|
||||
Линейная интерполяция
|
||||
```
|
||||
Reference in New Issue
Block a user