从零破解小米红外协议用Arduino打造万能电暖器遥控器去年冬天我发现自己陷入了一个尴尬的境地——客厅的老式电暖器遥控器不知所踪而手边唯一带红外功能的小米盒子遥控器却对这台古董设备束手无策。这个看似简单的日常痛点却引发了一场有趣的硬件逆向工程之旅。本文将分享如何通过信号捕获、协议分析、代码实现三个关键阶段让小米遥控器成功控制非生态链设备。整个过程只需要基础电子元件和Arduino开发板特别适合想要入门硬件破解的开发者。1. 红外信号捕获实战1.1 硬件准备清单Arduino Uno开发板兼容版亦可VS1838B红外接收模块成本约¥2逻辑分析仪可选但强烈推荐杜邦线若干小米红外遥控器测试使用小米盒子3代提示VS1838B的OUT引脚需接Arduino的数字引脚建议选择支持中断的D2或D3引脚1.2 基础电路搭建连接电路时需注意红外接收头的方向性。典型接法如下// 简易接线示意图 void setup() { pinMode(2, INPUT); // 红外接收OUT → D2 Serial.begin(115200); }使用逻辑分析仪捕获原始信号时会发现小米协议的特殊之处——它采用四进制编码而非传统的NEC协议。通过多次采样不同按键可以观察到以下特征特征项典型值μs说明引导脉冲9000起始标志逻辑0400-600短高电平短低电平逻辑11200-1400长高电平短低电平逻辑21800-2000短高电平长低电平逻辑32400-2600长高电平长低电平帧间隔45000连续发送时的间隔时间2. 小米四进制协议深度解析2.1 数据帧结构拆解典型的小米红外数据帧由12位组成结构如下[Start][D0][D1][D2][D3][D4][D5][D6][D7][D8][D9][Stop]以电源键为例捕获到的原始数据序列可能是2 0 1 2 0 0 3 3 0 12.2 编码转换算法小米采用独创的四进制到十六进制转换方案。理解这个转换过程是逆向的关键将每个四进制数字转换为2位二进制0 → 001 → 012 → 103 → 11将二进制序列按4位一组转换为十六进制2(10) 0(00) 1(01) 2(10) → 1000 0110 → 0x86 0(00) 0(00) 3(11) 3(11) → 0000 1111 → 0x0F最终得到键值码0x860F2.3 常见按键码表通过大量采样测试整理出部分功能键的对应关系按键功能四进制序列十六进制码电源20120033010x860F音量20120033020x8613音量-20120033000x860B方向左20120033030x86173. Arduino解码程序实现3.1 红外接收核心代码以下代码实现了小米协议的高精度捕获#include IRremote.h #define RECV_PIN 2 IRrecv irrecv(RECV_PIN); decode_results results; void setup() { Serial.begin(115200); irrecv.enableIRIn(); } void loop() { if (irrecv.decode(results)) { if (results.decode_type UNKNOWN) { Serial.println(捕获到未知协议开始分析...); analyzeXiaomiProtocol(results.rawbuf, results.rawlen); } irrecv.resume(); } } void analyzeXiaomiProtocol(uint16_t *buf, uint8_t len) { uint8_t code[12] {0}; for (uint8_t i 1, j 0; i len j 12; i 2) { uint16_t pulse buf[i]; if (pulse 2000) code[j] 3; else if (pulse 1600) code[j] 2; else if (pulse 1000) code[j] 1; else code[j] 0; j; } // 打印原始四进制序列 Serial.print(解码结果: ); for (uint8_t i 0; i 12; i) { Serial.print(code[i]); Serial.print( ); } Serial.println(); }3.2 信号发送模块成功解码后我们需要实现反向发送功能。这里使用Arduino的PWM引脚驱动红外LEDvoid sendXiaomiCode(uint16_t cmd) { // 38kHz载波频率 enableIROut(38); // 发送引导脉冲 mark(9000); space(4500); // 发送数据位 for (uint8_t i 0; i 12; i) { switch((cmd (22 - i*2)) 0x03) { case 0: mark(600); space(600); break; case 1: mark(1200); space(600); break; case 2: mark(600); space(1200); break; case 3: mark(1200); space(1200); break; } } // 结束脉冲 mark(600); space(0); }4. 电暖器控制方案定制4.1 设备学习模式破解大多数老式电暖器都具备学习模式操作步骤通常为长按电暖器设置键5秒进入学习状态在10秒内发送目标红外信号设备自动保存信号特征通过逻辑分析仪捕获原装遥控器的信号特征后可以将其转换为小米协议能发送的格式。例如某品牌电暖器的开关信号特征为载波频率38kHz数据格式简单的脉冲距离编码信号长度24位4.2 信号转换算法将传统编码转换为小米兼容格式的Python示例def convert_to_xiaomi(original_signal): xiaomi_code [] for pulse in original_signal: if pulse 800: xiaomi_code.append(0) # 短脉冲 elif 800 pulse 1600: xiaomi_code.append(1) # 中等脉冲 elif 1600 pulse 2400: xiaomi_code.append(2) # 长脉冲 else: xiaomi_code.append(3) # 超长脉冲 return xiaomi_code[:12] # 截取前12位4.3 完整控制方案最终实现的电暖器控制功能包括温度调节通过音量键映射温度±定时开关利用方向键设置时长模式切换用菜单键循环切换工作模式童锁功能电源键长按3秒启用实际测试中发现某些电暖器对信号时序要求严格可能需要微调脉冲宽度。建议通过以下参数进行校准// 在sendXiaomiCode函数中添加校准参数 const uint16_t timing_calibration[4][2] { {550, 550}, // 0 {1150, 550}, // 1 {550, 1150}, // 2 {1150, 1150} // 3 };这个项目最有趣的部分是发现不同品牌设备的信号特征差异。有次测试时误将空调的强力模式信号发送给电暖器结果设备竟然进入了某种隐藏的高功率状态——这种意外发现往往是最有价值的学习经验。建议大家在成功控制基础功能后不妨尝试发送各种非常规信号组合说不定会有惊喜。