Вот обновленная и расширенная документация по MQTT-интерфейсу, включающая новую функциональность работы с датчиками расстояния **VL53L0X**, а также оптимизации, появившиеся в коде. --- # 📡 Документация по MQTT интерфейсу (ESP32 + TMC2209 + Servo + VL53L0X) ## 📌 Общая информация - **Архитектура**: ESP32 (FreeRTOS задача `mqttTask`). - **Период опроса телеметрии**: 500 мс. - **Оптимизация трафика**: 1. Публикация данных происходит **только при изменении значения** (строгое кэширование). 2. Используется статический буфер (`intToString`/`uintToString`) вместо динамического класса `String` для экономии памяти и предотвращения фрагментации кучи. - **Префиксы**: - `.../control/...` — топики для **отправки команд** устройству (подписка). - `.../feedback/...` — топики для **получения статуса/телеметрии** от устройства (публикация). --- ## ⚙️ 1. Управление шаговым двигателем (Motor Control) | Топик | Тип данных | Описание | Пример Payload | | :--- | :---: | :--- | :--- | | `motor/control/rpm` | Integer | Целевая скорость в об/мин (RPM). Отрицательные значения включают реверс. | `-150`, `0`, `300` | | `motor/control/driver` | String | Аппаратное вкл/выкл драйвера (пин `EN_PIN`). `on` = LOW (вкл), иначе = HIGH (выкл). | `on`, `off` | | `motor/control/totalsteps/reset`| Any | Сброс счетчика шагов в ноль. Устройство сразу опубликует `"0"` в feedback. | `1`, `reset` | ### Телеметрия двигателя (Motor Feedback) *(Публикуется только при изменении)* - `motor/feedback/rpm` (Integer): Текущая скорость. - `motor/feedback/totalsteps` (Integer): Общее количество шагов. - `motor/feedback/is_run` (String: `true`/`false`): Двигатель движется. - `motor/feedback/driver/status` (String: `on`/`off`): Общий статус драйвера. - `motor/feedback/tmc/status` (String: `on`/`off`): Статус программного включения TMC. #### Детальная телеметрия TMC2209 (`motor/feedback/tmc/...`) - `current_percent` (Integer): Текущий % рабочего тока. - `microsteps` (Integer): Текущий режим микрошага. - `sg_result` (Integer): Текущее значение StallGuard (нагрузка). - `interstep_duration` (Integer): Длительность между шагами. - `status/over_temp` (String: `true`/`false`): Перегрев. - `status/short_to_ground` (String: `true`/`false`): КЗ на землю. - `status/open_load` (String: `true`/`false`): Обрыв нагрузки. - `status/stealth_chop_active` (String: `true`/`false`): Активен ли StealthChop. - `status/standstill` (String: `true`/`false`): Двигатель в покое. - `status/current_scaling` (Integer): Внутренний масштабный коэффициент тока. --- ## 🦾 2. Управление сервоприводами (Servo Control) Поддержка нескольких каналов (`{channel}` от `0` до `MAX_SERVOS - 1`). ### Команды | Топик (пример для канала 0) | Тип данных | Описание | Пример Payload | | :--- | :---: | :--- | :--- | | `servo/control/0/angle` | Integer (0-180) | Установить угол поворота. | `90` | | `servo/control/0/enable` | String | Включить (`on`, `1`, `true`) или выключить. | `on` | ### Обратная связь - `servo/0/feedback/status` (String: `on`/`off`): Статус питания сервопривода. - `servo/0/feedback/angle` (Integer): Текущий установленный угол. --- ## 📏 3. Управление датчиками VL53L0X (Sensor Control) **(НОВОЕ)** Поддержка до 8 каналов (`VL53L0X_MAX_CHANNELS = 8`). Топики используют параметр `{channel}` (0–7). | Топик | Тип данных | Описание | Пример Payload | | :--- | :---: | :--- | :--- | | `sensor/control/mode` | Integer | Установка глобального режима измерения (0 до `MODE_COUNT - 1`). | `0`, `1` | | `sensor/control/mode_name` | String | *Заглушка/Логирование.* Принимает имя режима для отладки. | `LongRange` | | `sensor/control/calibrate/start/{ch}`| Integer | Начало калибровки: указать близкое расстояние в мм. | `50` | | `sensor/control/calibrate/finish/{ch}`| Integer | Завершение калибровки: указать дальнее расстояние в мм. | `500` | | `sensor/control/clear_cal/{ch}` | Any | Сбросить калибровку для указанного канала. | `1` | | `sensor/control/enable/{ch}` | String | Включить (`on`, `1`, `true`) или выключить конкретный канал. | `on` | | `sensor/control/publish_all` | Any | **Принудительный сброс кэша.** Заставляет устройство немедленно опубликовать текущие значения всех датчиков, даже если они не изменились. | `1` | --- ## 📊 4. Телеметрия датчиков VL53L0X (Sensor Feedback) **(НОВОЕ)** ### Глобальная информация о режиме Публикуется только при смене режима измерения: - `sensor/feedback/mode` (String): Человекочитаемое имя текущего режима (например, "Default", "LongRange"). - `sensor/feedback/mode_id` (Integer): Числовой ID текущего режима. - `sensor/feedback/max_range` (Integer): Максимальная дальность для текущего режима (в мм). ### Постатусная информация по каналам (`{channel}` = 0..7) *(Публикуется только при изменении состояния или значения)* | Топик (пример для канала 0) | Тип данных | Описание | | :--- | :---: | :--- | | `sensor/feedback/0/status` | String (`on`/`off`) | Включен ли логически данный канал. | | `sensor/feedback/0/calibrated` | String (`true`/`false`)| Была ли проведена калибровка для этого канала. | | `sensor/feedback/0/distance` | Integer или String | **Калиброванное** расстояние в мм. Если значение `65535` (ошибка/вне диапазона), публикуется строка `"out_of_range"`. | | `sensor/feedback/0/raw` | Integer | **Сырое** (некалиброванное) значение расстояния в мм. | *Примечание: Топики `distance` и `raw` публикуются только если канал активен (`vl53l0xIsChannelActive`).* --- ## 💡 Важные особенности реализации (Обновлено) 1. **Безопасная работа со строками**: В новом коде добавлены функции `intToString` и `uintToString`, использующие статические буферы. Это полностью устраняет риск фрагментации памяти (heap fragmentation) при частой публикации телеметрии, который был присущ использованию класса `String`. 2. **Принудительная публикация**: Топик `sensor/control/publish_all` сбрасывает кэш значений `distance` и `raw` на `65535`. При следующем цикле (через 500 мс) система "увидит" изменение и гарантированно отправит актуальные данные. Это полезно при подключении нового клиента, которому нужно получить текущее состояние без перезагрузки устройства. 3. **Обработка ошибок дальности**: Если датчик возвращает `65535` (стандартный код ошибки "вне диапазона" или сбоя измерения для VL53L0X), в топик `distance` публикуется понятная строка `"out_of_range"`, а не число, что упрощает обработку на стороне клиента. 4. **Изоляция каналов**: Цикл телеметрии VL53L0X предварительно проверяет `vl53l0xIsChannelPresent(ch)`, поэтому несуществующие или отключенные на аппаратном уровне каналы не создают лишнего трафика. --- ### 🛠️ Примеры использования (CLI / mosquitto) ```bash # --- Двигатель --- mosquitto_pub -t "motor/control/rpm" -m "100" mosquitto_pub -t "motor/control/tmc/stealthchop" -m "on" # --- Сервопривод (канал 0) --- mosquitto_pub -t "servo/control/0/enable" -m "on" mosquitto_pub -t "servo/control/0/angle" -m "90" # --- Датчики VL53L0X --- # Включить канал 1 mosquitto_pub -t "sensor/control/enable/1" -m "on" # Начать калибровку канала 1 (близкая точка 50 мм) mosquitto_pub -t "sensor/control/calibrate/start/1" -m "50" # ... передвинуть объект ... # Завершить калибровку канала 1 (дальняя точка 400 мм) mosquitto_pub -t "sensor/control/calibrate/finish/1" -m "400" # Принудительно запросить публикацию всех текущих показаний датчиков mosquitto_pub -t "sensor/control/publish_all" -m "1" # Подписаться на все события датчиков для отладки mosquitto_sub -t "sensor/feedback/#" -v ```