smart-home/diagnose_ir_system.md
2026-02-26 09:16:34 +08:00

9.8 KiB
Raw Blame History

红外系统诊断指南

🔍 快速诊断

你们的代码已经是正确的!如果还不准确,按以下步骤诊断:


第1步确认APP端发送的数据

修改APP端代码

文件: smart-home-app/pages/control/ac-pair.vue

sendTiqiaaCode函数中添加日志:

async sendTiqiaaCode(idx) {
    const rid = this.tiqiaaRemoteIds[idx]
    this.currentCodeIndex = idx
    try {
        const ir = await getPowerIRByRemoteId(rid)
        
        // ✅ 添加这段诊断日志
        console.log('========== APP端发送数据 ==========')
        console.log('遥控器ID:', rid)
        console.log('频率:', ir.freq)
        console.log('脉冲数量:', ir.timings.length)
        console.log('前20个脉冲:', ir.timings.slice(0, 20))
        console.log('=====================================')
        
        await uni.request({
            url: `http://${this.esp32IP}:${this.apiPort}/api/ir/raw`,
            method: 'POST',
            data: {
                freq: ir.freq,
                timings: ir.timings,
                channel: 0
            },
            timeout: 8000
        })
        return true
    } catch (e) {
        console.error('发送Tiqiaa红外失败:', e)
        return false
    }
}

预期输出

========== APP端发送数据 ==========
遥控器ID: 1234567890
频率: 38000
脉冲数量: 199
前20个脉冲: [4500, 4400, 500, 1100, 500, 1100, 500, 1100, 500, 1100, 500, 1100, 500, 1100, 500, 1100, 500, 1100, 500, 1100]
=====================================

如果看到这样的输出说明APP端正确


第2步确认ESP32端收到的数据

修改ESP32端代码

文件: firefly_esp32/main/Controller/ACRemoteAPI.cpp

sendRawIRHandler函数中添加日志:

esp_err_t ACRemoteAPI::sendRawIRHandler(httpd_req_t *req) {
    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
    httpd_resp_set_hdr(req, "Content-Type", "application/json");

    std::string postData = getPostData(req);
    if (postData.empty()) {
        sendErrorResponse(req, "请求数据为空");
        return ESP_OK;
    }

    cJSON *json = cJSON_Parse(postData.c_str());
    if (!json) {
        sendErrorResponse(req, "JSON格式错误");
        return ESP_OK;
    }

    cJSON *freq = cJSON_GetObjectItem(json, "freq");
    cJSON *timings = cJSON_GetObjectItem(json, "timings");
    cJSON *channel = cJSON_GetObjectItem(json, "channel");

    if (!cJSON_IsNumber(freq) || !cJSON_IsArray(timings)) {
        sendErrorResponse(req, "缺少freq或timings参数");
        cJSON_Delete(json);
        return ESP_OK;
    }

    int ch = cJSON_IsNumber(channel) ? channel->valueint : 0;
    int hz = freq->valueint;
    if (hz <= 0) hz = 38000;

    std::vector<uint16_t> buf;
    int n = cJSON_GetArraySize(timings);
    buf.reserve(n);
    for (int i = 0; i < n; i++) {
        cJSON *v = cJSON_GetArrayItem(timings, i);
        if (!cJSON_IsNumber(v)) continue;
        int val = v->valueint;
        if (val < 0) val = 0;
        if (val > 65535) val = 65535;
        buf.push_back((uint16_t)val);
    }

    // ✅ 添加这段诊断日志
    ESP_LOGI(TAG, "========== ESP32收到数据 ==========");
    ESP_LOGI(TAG, "频率: %dHz", hz);
    ESP_LOGI(TAG, "通道: %d", ch);
    ESP_LOGI(TAG, "脉冲数量: %d", buf.size());
    if (buf.size() >= 20) {
        ESP_LOGI(TAG, "前20个脉冲:");
        for (int i = 0; i < 20; i++) {
            ESP_LOGI(TAG, "  [%d]: %d", i, buf[i]);
        }
    }
    ESP_LOGI(TAG, "====================================");

    bool ok = false;
    if (!buf.empty()) {
        CIR::GetInstance()->Send(ch, buf, (uint16_t)hz);
        ok = true;
        ESP_LOGI(TAG, "✅ 红外信号已发送");
    } else {
        ESP_LOGE(TAG, "❌ 脉冲数组为空");
    }

    cJSON *response = cJSON_CreateObject();
    cJSON_AddBoolToObject(response, "success", ok);
    cJSON_AddStringToObject(response, "message", ok ? "IR发送成功" : "IR数据为空");
    char *responseStr = cJSON_Print(response);
    httpd_resp_sendstr(req, responseStr);

    free(responseStr);
    cJSON_Delete(response);
    cJSON_Delete(json);
    return ESP_OK;
}

预期输出

========== ESP32收到数据 ==========
频率: 38000Hz
通道: 0
脉冲数量: 199
前20个脉冲:
  [0]: 4500
  [1]: 4400
  [2]: 500
  [3]: 1100
  [4]: 500
  [5]: 1100
  [6]: 500
  [7]: 1100
  [8]: 500
  [9]: 1100
  [10]: 500
  [11]: 1100
  [12]: 500
  [13]: 1100
  [14]: 500
  [15]: 1100
  [16]: 500
  [17]: 1100
  [18]: 500
  [19]: 1100
====================================
✅ 红外信号已发送

如果看到这样的输出说明ESP32端正确


第3步对比APP和ESP32的数据

检查清单

项目 APP端 ESP32端 是否一致
频率 38000 38000
脉冲数量 199 199
第1个脉冲 4500 4500
第2个脉冲 4400 4400
第3个脉冲 500 500
第4个脉冲 1100 1100

如果所有数据都一致,说明数据传输正确!


第4步检查红外硬件

硬件检查清单

1. 红外LED连接

ESP32 GPIO → 限流电阻(100Ω) → 红外LED正极 → 红外LED负极 → GND

检查:

  • GPIO引脚是否正确
  • 限流电阻是否存在?
  • 红外LED极性是否正确
  • 连接是否牢固?

2. 红外LED电流

测试方法:

  • 用万用表测量红外LED两端电压
  • 正常应该是1.2V-1.5V
  • 如果电压过低,增加电流
  • 如果电压过高,增加限流电阻

3. 红外LED发射角度

测试方法:

  • 用手机摄像头对准红外LED
  • 发送信号时应该看到LED闪烁紫色光
  • 如果看不到说明LED损坏或连接错误

4. 空调接收距离

测试方法:

  • 距离空调1米内测试
  • 红外LED对准空调接收器
  • 避免阳光直射

第5步测试不同品牌

测试清单

测试以下品牌的空调:

  • 美的Midea
  • 格力Gree
  • 海尔Haier
  • 其他品牌

结果分析

情况 可能原因 解决方案
所有品牌都不工作 硬件问题 检查红外LED连接
只有某些品牌不工作 SDK数据问题 更新SDK或换遥控器ID
偶尔工作 距离/角度问题 调整位置和角度
完全不工作 代码问题 检查上面的日志

第6步使用逻辑分析仪

如果有逻辑分析仪

连接方式:

逻辑分析仪CH1 → ESP32 GPIO红外发送引脚
逻辑分析仪GND → ESP32 GND

预期波形:

引导码: 4.5ms高 + 4.4ms低
数据0:  0.5ms高 + 1.1ms低
数据1:  0.5ms高 + 4.6ms低

如果波形正确说明ESP32发送正确


🎯 诊断流程图

开始
  ↓
APP端日志正确
  ├─ 否 → 检查SDK调用
  └─ 是 ↓
ESP32端日志正确
  ├─ 否 → 检查网络连接
  └─ 是 ↓
数据一致?
  ├─ 否 → 检查JSON解析
  └─ 是 ↓
红外LED闪烁
  ├─ 否 → 检查硬件连接
  └─ 是 ↓
空调响应?
  ├─ 否 → 检查距离/角度
  └─ 是 ↓
成功!✅

📞 常见问题

Q1: APP端日志显示脉冲数量为0

原因: SDK没有正确初始化或遥控器ID错误

解决:

// 检查SDK初始化
await initTiqiaa()

// 检查遥控器ID是否有效
const remote = await downloadRemote(remoteId)
console.log('遥控器信息:', remote)

Q2: ESP32端收不到数据

原因: 网络连接问题或URL错误

解决:

// 检查ESP32 IP
console.log('ESP32 IP:', this.esp32IP)

// 检查URL
console.log('请求URL:', `http://${this.esp32IP}:${this.apiPort}/api/ir/raw`)

// 测试连接
const response = await uni.request({
    url: `http://${this.esp32IP}:${this.apiPort}/api/status`,
    method: 'GET'
})
console.log('ESP32状态:', response.data)

Q3: 数据不一致

原因: JSON解析错误或数据类型转换问题

解决:

// 检查JSON解析
ESP_LOGI(TAG, "原始JSON: %s", postData.c_str());

// 检查数据类型
for (int i = 0; i < n; i++) {
    cJSON *v = cJSON_GetArrayItem(timings, i);
    if (!cJSON_IsNumber(v)) {
        ESP_LOGE(TAG, "第%d个元素不是数字", i);
    }
}

Q4: 红外LED不闪烁

原因: GPIO配置错误或LED损坏

解决:

// 检查GPIO配置
ESP_LOGI(TAG, "红外GPIO: %d", IR_GPIO_PIN);

// 测试GPIO
gpio_set_level(IR_GPIO_PIN, 1);
vTaskDelay(pdMS_TO_TICKS(1000));
gpio_set_level(IR_GPIO_PIN, 0);

Q5: 空调不响应

原因: 距离太远、角度不对或空调型号不匹配

解决:

  • 距离控制在1米内
  • 红外LED对准空调接收器
  • 尝试不同的遥控器ID
  • 检查空调是否支持该品牌

📝 诊断报告模板

完成诊断后,填写以下报告:

========== 红外系统诊断报告 ==========

日期: ___________
测试人: ___________

1. APP端数据
   - 频率: _______Hz
   - 脉冲数量: _______
   - 前5个脉冲: [_____, _____, _____, _____, _____]
   - 状态: [ ] 正常 [ ] 异常

2. ESP32端数据
   - 频率: _______Hz
   - 脉冲数量: _______
   - 前5个脉冲: [_____, _____, _____, _____, _____]
   - 状态: [ ] 正常 [ ] 异常

3. 数据一致性
   - [ ] 频率一致
   - [ ] 脉冲数量一致
   - [ ] 脉冲值一致

4. 硬件检查
   - [ ] 红外LED连接正确
   - [ ] 红外LED闪烁正常
   - [ ] 距离和角度合适

5. 测试结果
   - 美的空调: [ ] 成功 [ ] 失败
   - 格力空调: [ ] 成功 [ ] 失败
   - 海尔空调: [ ] 成功 [ ] 失败
   - 其他品牌: [ ] 成功 [ ] 失败

6. 结论
   问题原因: ___________________________
   解决方案: ___________________________

=====================================

祝你诊断顺利!如果还有问题,请提供诊断报告。