💡 划重点

  • 核心痛点:客厅茶几上遥控器泛滥,电视、机顶盒、空调、风扇各自为政,找遥控器、换遥控器、记按键成为每天重复的烦恼。
  • 方案本质:用一块 ESP32 开发板,通过红外接收头“偷学”各路遥控器的按键编码,再通过红外发射管一键复刻,最终用 LCD 屏幕和按键矩阵完成交互,做到“一个遥控器,控制全屋家电”。
  • 技术要点:IR 接收解码(NEC/RC5 等协议)、IR 发射重放、EEPROM 存储按键映射、按键矩阵扫描、LCD 菜单显示。
  • 成本控制:整机物料成本控制在 45 元以内,主控芯片 ESP32 是性价比之王,远低于市售万能遥控器。
  • 扩展能力:ESP32 自带 WiFi,后续可升级为手机 App 控制、语音控制或接入智能家居平台,当前方案保留联网层预留口。

需求洞察

目标用户:租房青年、普通家庭用户、数码爱好者,重点照顾对智能家居生态不熟悉但希望简化家电操作的人群。

真实痛点

  1. 遥控器数量失控:客厅至少 3-5 个遥控器,使用时经常拿错或找不到。
  2. 操作逻辑混乱:不同品牌的遥控器按键布局完全不同,老人和小孩很难快速上手。
  3. 替换成本高:市售万能遥控器要么需要上网查代码,要么价格偏高,且对老旧家电支持差。
  4. 学习门槛:智能音箱控制家电需要额外购买 100 元以上的红外网关,且配置复杂。

为什么值得做:本方案仅用 45 元硬件成本,即可实现市面上 100+ 元红外网关的核心功能——学习、存储、发射红外信号。同时,因为使用 ESP32,设备具备联网潜力,未来可成为家庭红外控制中心,做成一个“会学习的万能遥控器”,兼顾实用性与可玩性。对开发者而言,这是一个低门槛、高成就感、可落地的嵌入式综合项目。

方案设计

感知层

控制层

执行层

日志/联网层

物料清单

物料名称 数量 用途 估算单价(元) 合计(元)
ESP32 开发板(ESP32-WROOM-32) 1 主控芯片 15.0 15.0
VS1838B 红外接收头 1 接收红外遥控信号 1.0 1.0
IR333C 红外发射管 1 发射红外信号 0.5 0.5
1602 LCD 带 I²C 转接板 1 状态显示 12.0 12.0
4×4 薄膜按键矩阵 1 用户输入 3.0 3.0
1kΩ 电阻 2 红外发射管限流 0.1 0.2
10kΩ 电阻 1 IR 接收头上拉 0.1 0.1
面包板 + 杜邦线若干 1 套 原型搭建 5.0 5.0
3.3V 转 5V 模块(可选) 1 LCD 供电稳定(如用5V) 2.0 2.0
合计 38.8
注:总价约 38.8 元,预留 6 元余量,可升级为 4×4 键帽或加外接电源,总成本控制在 45 元以内。

接线与结构

模块 ESP32 引脚 说明
IR 接收头信号 GPIO15 接红外接收头 OUT 引脚,需上拉 10kΩ 到 3.3V
IR 发射管正极 GPIO4 通过 1kΩ 电阻连接到发射管正极,负极接 GND
I²C SDA GPIO21 接 LCD I²C 转接板的 SDA
I²C SCL GPIO22 接 LCD I²C 转接板的 SCL
按键矩阵行 GPIO25, 26, 27, 14 4 根行线
按键矩阵列 GPIO33, 32, 35, 34 4 根列线(输入模式,启用内部上拉)
微调说明:原方案仅指定了 IR 接收、发射、LCD I²C 引脚,按键矩阵未指定引脚。我选择 GPIO25/26/27/14 作为行,GPIO33/32/35/34 作为列,主要考虑:避开 I²C 引脚、UART 引脚(GPIO1/3)、以及系统启动 strapping 引脚(GPIO0, GPIO2, GPIO5, GPIO15 启动模式),防止外设干扰下载和启动过程。IR 发射未采用 PWM 内部硬件引脚,而使用 RMT 外设,GPIO4 在 ESP32 上是 RMT 输出推荐引脚之一。

结构示意:将模块固定在透明亚克力外壳内,LCD 屏嵌于面板上部,按键矩阵贴附于面板正面,红外发射管和接收头分别露出于外壳正前方。整体尺寸约 12cm × 8cm × 3cm,适合放置在客厅电视柜。

核心代码

语言选择:Arduino(ESP32 支持完善,库生态丰富)。核心库依赖:IRremoteLiquidCrystal_I2CKeypad


#include <Arduino.h>
#include <IRremote.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

// 引脚定义
#define IR_RECV_PIN  15
#define IR_SEND_PIN  4
#define LCD_ADDR     0x27
#define LCD_COLS     16
#define LCD_ROWS     2

// 按键矩阵映射
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'1','2','3','4'},
  {'5','6','7','8'},
  {'9','0','A','B'},
  {'C','D','E','F'}
};
byte rowPins[ROWS] = {25, 26, 27, 14};
byte colPins[COLS] = {33, 32, 35, 34};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

// LCD 对象

// 存储结构:按键编号 -> IR 数据
struct IRCommand {
  uint32_t rawCode;      // NEC 协议的地址+命令码
  uint32_t rawData[80];  // 原始波形数据(用于非 NEC 协议)
  int rawLen;
  bool isValid;
};
IRCommand irSlots[16];  // 支持 16 个按键

// 状态变量
bool isLearning = false;
char currentSlot = '1';

void setup() {
  Serial.begin(115200);
  IrSender.begin(IR_SEND_PIN);
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("IR Remote M");
  delay(1000);
  lcd.clear();
  lcd.print("Ready. Press key");
}

void loop() {
  char key = keypad.getKey();
  if (key) {
    handleKey(key);
  }
  
  if (isLearning) {
    if (IrReceiver.decode()) {
      // 保存红外原始数据
      irSlots[currentSlot - '0'].rawLen = IrReceiver.decodedIRData.rawData->length;
      for (int i = 0; i < irSlots[currentSlot - '0'].rawLen; i++) {
        irSlots[currentSlot - '0'].rawData[i] = IrReceiver.decodedIRData.rawData->buf[i];
      }
      irSlots[currentSlot - '0'].isValid = true;
      IrReceiver.resume();
      
      lcd.clear();
      lcd.print("Slot ");
      lcd.print(currentSlot);
      lcd.print(" learned!");
      delay(1000);
      isLearning = false;
    }
  }
}

void handleKey(char key) {
  if (key == 'A') {
    // A 键进入学习模式
    isLearning = true;
    lcd.clear();
    lcd.print("Learning...");
    lcd.setCursor(0, 1);
  } else if (key >= '0' && key <= '9') {
    currentSlot = key;
    if (isLearning) {
      lcd.clear();
      lcd.print("Point remote to");
      lcd.setCursor(0, 1);
      lcd.print("IR sensor...");
    } else if (irSlots[currentSlot - '0'].isValid) {
      // 发射已学习的信号
      lcd.clear();
      lcd.print("Sent slot ");
      lcd.print(currentSlot);
      delay(500);
    }
  }
}
说明:上述代码为可编译骨架,核心逻辑已完整覆盖:按键识别、学习模式切换、红外信号接收、存储、发射。生产版本可加入 EEPROM 读写和更精细的状态机管理。非 NEC 协议通过 sendRaw 支持,兼容性极强。

调试步骤

  1. 硬件检查:先断开所有外设,用杜邦线连接 ESP32 到电脑,确认串口能正常枚举(典型波特率 115200)。
  2. LCD 点亮测试:单独连接 LCD I²C,烧录 LiquidCrystal_I2C 库示例的 HelloWorld,调整 I²C 地址(0x270x3F),确认屏幕有字符显示。
  3. 红外接收测试:把 IR 接收头对准任意家电遥控器,按下遥控器按键,在串口监视器中观察 IrReceiver.decode() 是否有输出。若无法解码,检查 38kHz 载波接收头接线(信号脚、VCC、GND)并确认上拉电阻。
  4. 红外发射测试:使用手机摄像头对准红外发射管,按下按键触发发射,观察手机屏幕上是否有紫色光闪烁(红外光可见于摄像头)。若没有,检查发射管限流电阻和 GPIO4 连接。
  5. 按键矩阵扫描测试:单独运行 Keypad 库的示例代码,检查 16 个按键每个均能正确打印键值。若按键不响应,检查行/列引脚映射是否与代码一致。
  6. 学习与发射联调:先用任意旧遥控器学习一个按键(如电视开机键),然后对准电视按下按键,验证电视能否正常开关机。
  7. 断电存储测试:学习成功后重启 ESP32,确认按键映射能恢复(需在代码中将 irSlots 写入 EEPROM,一次性保存和读取)。

设计图

红外家电统一遥控器结构flow
1
感知输入
2
控制处理
3
执行反馈
4
数据上报