Шаг 05 — Команды от портала: RMT-выход¶
После этого шага нажатие кнопки «Старт» на портале будет генерировать RMT-импульс на выходной пин ESP32. На примере iHeater Link: пин подключён к STM32 нагревателя.
Принцип¶
Портал отправляет команду invoke через MQTT-топик idryer/{serial}/commands/invoke. Библиотека десериализует JSON и вызывает зарегистрированный обработчик. Обработчик передаёт команду в RmtOutputAdapter, который генерирует кадр импульсов на выбранный пин.
Команда не зависит от конкретного пина или протокола — это обычная функция-обработчик. RMT — одна из реализаций; другая — PWM, см. 06-pwm.md.
Что понадобится¶
- ESP32-C3 или ESP32 (RMT доступен на всех пинах GPIO)
- Нагрузка на выходном пине (в примере iHeater Link — STM32 через оптопару)
Шаги¶
1. Объявить RmtOutputAdapter в main.cpp. Основано на iHeater-link/src/main.cpp:
#include "controller/RmtOutputAdapter.h"
static iheaterlink::RmtOutputAdapter s_output{iheaterlink::RmtOutputConfig{}};
По умолчанию используется пин IHEATER_TRIGGER_OUTPUT_PIN. Задайте его через build_flags:
2. Инициализировать в setup():
begin() настраивает RMT-канал и запускает фоновую FreeRTOS-задачу отправки keepalive-кадров.
3. Зарегистрировать обработчик команды в setup():
device().onCommand("invoke", [](JsonObjectConst data) {
const char* action = data["action"] | "";
JsonObjectConst args = data["args"];
if (strcmp(action, "heat.start") == 0) {
float tempC = args["tempC"] | 0.0f;
uint32_t durMin = args["durationMin"] | 0u;
iheaterlink::ControllerOutputCommand cmd;
cmd.mode = iheaterlink::ControllerOutputMode::TargetTemperature;
cmd.targetTempC = tempC;
s_output.apply(cmd);
device().status.mode[0] = iDryer::UnitMode::Drying;
device().status.targetTempC[0] = tempC;
device().publishStatusNow();
} else if (strcmp(action, "heat.stop") == 0) {
iheaterlink::ControllerOutputCommand cmd;
cmd.mode = iheaterlink::ControllerOutputMode::Off;
cmd.targetTempC = 0.0f;
s_output.apply(cmd);
device().status.mode[0] = iDryer::UnitMode::Idle;
device().publishStatusNow();
}
});
4. В loop() — только вызов device().loop():
RMT-кадры отправляются из FreeRTOS-задачи внутри s_output независимо от loop().
Как портал отправляет команду¶
Портал публикует в MQTT-топик idryer/{serial}/commands/invoke:
Библиотека получает это сообщение, вызывает зарегистрированный callback с десериализованным JsonObjectConst data. Поле action определяет, что делать.
Список actions для конкретного типа устройства задаётся в contracts/mqtt_contract.yaml в секции invoke_actions.
Проверка¶
Откройте портал → страница устройства → кнопка Heat. В Serial Monitor:
На выходном пине RMT появятся импульсы (проверьте осциллографом или логическим анализатором).
Что дальше¶
- 06-pwm.md — заменить RMT на PWM (MOSFET, диммер).
- RmtOutputAdapter.h — конфигурация RMT: частота импульсов, код Off, диапазон температур.