跳转至

第 06 步 — 用 PWM 取代 RMT

完成本步驟後,相同的入口網站命令流將驅動 PWM 輸出而不是 RMT。典型用例是通過 MOSFET 或 DC 調光器控制的加熱器。

工作原理

執行器是一個普通的回調函數。上一步的 RmtOutputAdapter 是一種實現。用 ledcWrite 代碼取代它 — 其他所有內容(MQTT、命令、狀態)保持不變。

步驟

1. 從 main.cpp 中移除 RmtOutputAdapter 包含和實例:

// 移除:
#include "controller/RmtOutputAdapter.h"
static iheaterlink::RmtOutputAdapter s_output{iheaterlink::RmtOutputConfig{}};

2. 在 setup() 中添加 PWM 初始化

#define PWM_PIN     0      // MOSFET 柵極的 GPIO
#define PWM_CHANNEL 0      // LEDC 通道 (0–15)
#define PWM_FREQ_HZ 25000  // 25 kHz — 對大多數加熱器不可聽
#define PWM_RES     8      // 8 位 → 佔空比 0–255

ledcSetup(PWM_CHANNEL, PWM_FREQ_HZ, PWM_RES);
ledcAttachPin(PWM_PIN, PWM_CHANNEL);
ledcWrite(PWM_CHANNEL, 0);  // 啟動時關閉

**3. 在命令處理程序中**用 ledcWrite 取代 s_output.apply(cmd)

device().onCommand("invoke", [](JsonObjectConst data) {
    const char* action   = data["action"] | "";
    JsonObjectConst args = data["args"];

    if (strcmp(action, "heat.start") == 0) {
        float power01 = args["power"] | 1.0f;  // 0.0–1.0
        uint8_t duty  = (uint8_t)(power01 * 255.0f);
        ledcWrite(PWM_CHANNEL, duty);

        device().status.mode[0]             = iDryer::UnitMode::Drying;
        device().telemetry.heaterPower01[0] = power01;
        device().publishStatusNow();

    } else if (strcmp(action, "heat.stop") == 0) {
        ledcWrite(PWM_CHANNEL, 0);

        device().status.mode[0]             = iDryer::UnitMode::Idle;
        device().telemetry.heaterPower01[0] = 0.0f;
        device().publishStatusNow();
    }
});

4. loop() 不會改變:

void loop() {
    device().loop();
}

Warning

ledcSetup / ledcAttachPin 是 3.x 之前版本的 Arduino ESP32 API。在 3.x 及以上版本中使用 ledcAttach(pin, freq, resolution)ledcWrite(pin, duty)。檢查 platformio.ini 中的版本(platform = espressif32@X.Y.Z)。

驗證

在入口網站上按下 Heat 按鈕。輸出引腳將攜帶 PWM 信號,佔空比與 power 參數成正比。用萬用表(平均電壓)或示波器驗證。

後續步驟