ESP32-S3 红外接收

红外信号需要搭载在一个固定频率的“载波”上发射,以减少环境光干扰。接收头必须选择与发射端匹配的频率才能正确接收。常见的频率有38kHz(最主流)、36kHz、40kHz、56.7kHz等。你的遥控器和接收头必须“同频”,才能“共振”通信。如果频率不匹配,会导致接收距离变短甚至完全无法接收。

不同的家电厂商发展出了多种通信协议,它们在地址码、命令码、数据格式和重复码上都有各自的规定。常见的包括:
NEC协议:使用最广泛的协议之一,采用脉冲宽度调制,具有8位地址和8位命令。
飞利浦RC-5 / RC-6协议:采用脉冲位置调制,有固定的编码结构。
索尼SIRC协议:索尼设备常用,有12位、15位和20位等多种数据格式。
其他:如你之前提到的三星、LG、JVC、松下等,都有各自定义的协议。

点击 牛瘪汤 主页可以了解更多。



1. 核查原理图

ESP32 S3 红外接收使用 TOP75238TR 双红外接收头,接收更稳定。供电范围 3-5V。
IR-RMT
追查原理图 IR_RX 与 IO7 连接,记住端口等下要用。

2. 编写测试 demo

以下是基于ESP32-S3与红外接收模块(连接IO7引脚)的Arduino代码,使用IRMP库实现多种红外协议(NEC、SONY、RC5、RC6、Panasonic、LG、JVC、SAMSUNG、Whynter、COOLIX)的解码检测,并包含RAW原始信号识别。代码会打印出协议名称、地址、命令等信息,对RAW信号输出长度和首脉冲宽度。

#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRutils.h>

// ==== 配置参数 =====
const uint16_t kRecvPin = 7;           // 红外接收头连接到 GPIO7
const uint32_t kBaudRate = 115200;     // 串口通讯波特率
const uint16_t kCaptureBufferSize = 1024; // 捕获缓冲区大小 (单位: 毫秒), 通常 1024 足够

// 在多协议解码时,建议开启超时设置,以适应长信号(如空调)
const uint8_t kTimeout = 15; // 关闭超时: 0; 典型值: 15 或 50 毫秒
// ===================

// 初始化红外接收对象
IRrecv irrecv(kRecvPin, kCaptureBufferSize, kTimeout, true);
decode_results results; // 用于存储解码结果的结构体

void setup() {
  // 初始化串口,用于打印解码信息
  Serial.begin(kBaudRate);
  while (!Serial) // 等待串口连接(针对部分开发板)
    delay(50);
  Serial.println("\n" __FILE__);
  Serial.print("IRrecv multi-protocol decoding is now running and waiting for remote signal on GPIO ");
  Serial.println(kRecvPin);

  // 启用红外接收器
  irrecv.enableIRIn();
  #if DECODE_HASH
  // 如果需要解码未知协议的原始信号,必须启用 HASH 解码。
  // 这允许库将无法识别的协议作为原始数据转储。
  irrecv.setUnknownThreshold(1); // 可选: 设置未知解码的最小长度
  #endif
  Serial.println("Ready to receive IR signals.");
}

void loop() {
  // 检查是否解码到信号
  if (irrecv.decode(&results)) {
    // 调用函数打印解码结果
    printDecodedResults(&results);
    // 打印信号的原始数据(时序)到串口,有助于分析未知协议
    Serial.println(resultToHumanReadableBasic(&results));
    // 必须调用 resume() 来准备接收下一个信号
    irrecv.resume();
  }
  delay(100); // 简单的防抖动延迟,避免串口输出过快
}

/**
 * 打印解码结果的详细信息。
 * 根据协议类型,格式化输出协议名称、地址、命令、数值等。
 * @param results 指向 decode_results 结构体的指针
 */
void printDecodedResults(decode_results *results) {
  // 输出协议名称
  Serial.print("Protocol: ");
  Serial.print(typeToString(results->decode_type, results->repeat)); // 使用库函数获取协议名
  // 如果是未知协议,输出 Hash 值便于识别
  if (results->decode_type == decode_type_t::UNKNOWN) {
    Serial.print(" (Hash: 0x");
    Serial.print(results->value, HEX);
    Serial.print(")");
  }
  Serial.print("\t");

  // 打印协议相关的具体数值(地址、命令、数据值等)
  // 使用库提供的函数 resultToHumanReadableBasic 也可以输出类似信息,
  // 但为了更清晰的展示,我们手动解析几个常见字段。
  if (results->decode_type != decode_type_t::UNKNOWN) {
    // 打印数据值 (Value)
    Serial.print("Value: 0x");
    Serial.print(results->value, HEX);

    // 打印地址 (Address) - 很多协议有这个字段
    if (results->address > 0 || results->command > 0) { // 简单的判断,避免打印无意义的 0
        Serial.print("\tAddr: 0x");
        Serial.print(results->address, HEX);
        Serial.print("\tCmd: 0x");
        Serial.print(results->command, HEX);
    }

    // 打印位数
    Serial.print("\tBits: ");
    Serial.print(results->bits);
  }
  Serial.println(); // 换行
}

接收到红外遥控,可以看到日志。

IRrecv multi-protocol decoding is now running and waiting for remote signal on GPIO 7
Ready to receive IR signals.
Protocol: NEC	Value: 0x27D00FF	Addr: 0xDF80	Cmd: 0x0	Bits: 32
Protocol  : NEC
Code      : 0x27D00FF (32 Bits)

Protocol: NEC	Value: 0x27D48B7	Addr: 0xDF80	Cmd: 0x12	Bits: 32
Protocol  : NEC
Code      : 0x27D48B7 (32 Bits)

结语

文章都看到完了,就不点个关注吗,老铁!
欢迎关注博主–牛瘪汤

更多推荐