一、项目背景与意义​

在智能家居、远程控制等领域,红外信号的应用十分广泛。比如我们日常使用的电视遥控器、空调遥控器,都是通过发射红外信号来实现对设备的控制。

二、硬件选型与原理​

(一)硬件清单​

VS1838B 红外接收头、红外遥控器( NEC 编码格式)

三、软件准备与代码解析

(一)软件工具

红外解码库:为了简化红外信号解码的程序编写,我们可以使用第三方的红外解码库,例如 “IRremote” 库。该库支持多种常见的红外编码格式(如 NEC、Sony、RC5、RC6 等),提供了丰富的函数接口,方便我们读取和解析红外信号。安装 “IRremote” 库的方法如下:打开 Arduino IDE,点击 “项目” 菜单,选择 “加载库”,再点击 “管理库”,在弹出的 “库管理器” 对话框中,在搜索框输入 “IRremote”,找到对应的库后,点击 “安装” 即可完成安装。

(二)库函数准备

如图当你下载好官方的库之后,可以进入库查看库函数。对于Arduino快速开发,很多常用模块都能直接找到库使用。在红色箭头处,可以看到相应的库函数。到时候直接调用库函数就行。

(二)学习使用IRremoteInt红外库函数

在学习函数前,需先了解 2 个关键数据结构 —— 它们是函数操作的数据载体:

数据结构 作用 核心字段(常用)
IRData 存储解码后的红外信号数据(新版本核心结构,替代旧版decode_results protocol(协议类型,如NEC/RC5)、address(设备地址)、command(控制命令)
decode_results 旧版解码结果结构(已 deprecated,兼容旧代码用) value(旧版命令值)、bits(数据位数)、isRepeat(是否为重复信号)

1. 检查是否有信号:available()
  • 函数原型bool available()
  • 作用:判断是否接收到可解码的红外信号,返回true表示有可用信号,false表示无。
  • 使用场景:在loop()中轮询,有信号时再执行解码,避免无效计算。
  • 示例
    void loop() {
      if (IrReceiver.available()) { // 有信号时解码
        IrReceiver.decode(); // 执行解码
        // 后续处理解码结果...
      }
    }
    

3. 解码信号:decode()
  • 函数原型bool decode()(新版本) / bool decode(decode_results *aResults)(旧版,已废弃)
  • 作用:对接收的原始红外信号进行解码,将结果存入IrReceiver.decodedIRData(新版本核心字段)。
  • 返回值true表示解码成功,false表示解码失败(如信号不匹配已知协议)。
  • 关键说明
    解码成功后,通过IrReceiver.decodedIRData获取详细信息,例如:
  • IrReceiver.decodedIRData.protocol:协议类型(如NEC/RC5/SONY);
    IrReceiver.decodedIRData.address:设备地址(红外遥控器的 “设备标识”);
    IrReceiver.decodedIRData.command:控制命令(如 “电源键”“音量 +” 对应的数值)。
  • 示例

    if (IrReceiver.decode()) {
      Serial.print("协议: ");
      switch(IrReceiver.decodedIRData.protocol) {
        case NEC: Serial.println("NEC"); break;
        case RC5: Serial.println("RC5"); break;
        default: Serial.println("未知");
      }
      Serial.print("地址: 0x");
      Serial.print(IrReceiver.decodedIRData.address, HEX); // 十六进制输出地址
      Serial.print(" 命令: 0x");
      Serial.println(IrReceiver.decodedIRData.command, HEX); // 十六进制输出命令
    }
    
4. 准备接收下一个信号:resume()
  • 函数原型void resume()
  • 作用:重置接收器状态,清空当前解码结果,准备接收下一个红外信号。
  • 必须调用:每次decode()成功后,若需继续接收信号,必须调用resume(),否则后续无法接收新信号。
  • 示例
    if (IrReceiver.decode()) {
      // 处理解码结果...
      IrReceiver.resume(); // 重置,准备接收下一个信号
    }
    

三、红外发送核心函数(IRsend类)

IRsend类负责生成并发送指定协议的红外信号,核心函数围绕 “初始化→发送指定协议信号” 设计:

1. 初始化发送器:begin()
  • 函数原型

无预设发送引脚时:void begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback = false, uint_fast8_t aFeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN)
有预设发送引脚(定义IR_SEND_PIN)时:void begin(bool aEnableLEDFeedback = false, uint_fast8_t aFeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN)

  • 作用:初始化红外发送器,绑定发射引脚(如红外 LED 的引脚)、配置反馈 LED(可选)。
  • 参数说明
    • aSendPin:红外 LED 的控制引脚(如3);
    • 其他参数同IRrecv::begin()(反馈 LED 配置)。
  • 硬件注意:红外 LED 需串联 220Ω 限流电阻,避免烧毁。
  • 示例

    #include <IRremote.hpp>
    #define IR_SEND_PIN 3 // 红外LED接3脚
    void setup() {
      IrSender.begin(IR_SEND_PIN); // 初始化发送器
    }
    
2. 发送 NEC 协议信号:sendNEC()
  • 函数原型
  • void sendNEC(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats = NO_REPEATS)
  • 作用:发送NEC 协议的红外信号(最常用的红外协议,如电视、空调遥控器多采用)。
  • 参数说明
  • aAddress:设备地址(需与接收端匹配,如0x00);
  • aCommand:控制命令(如 “电源” 对应0x12,“音量 +” 对应0x14);
  • aNumberOfRepeats:重复发送次数(默认NO_REPEATS=0,即发送 1 次;设为2则发送 1 次原始信号 + 2 次重复信号)。

  • 示例:发送 “NEC 协议,地址 0x00,命令 0x12” 的信号(模拟按 “电源键”):
    void loop() {
      IrSender.sendNEC(0x00, 0x12, 0); // 地址0x00,命令0x12,不重复
      Serial.println("已发送NEC信号");
      delay(2000); // 每2秒发送一次
    }
    

需要编写的代码

// 引入IRremote库
#include <IRremote.h>


const int RECV_PIN = 11;

// 创建IRrecv对象,用于接收红外信号,参数为红外接收引脚
IRrecv irrecv(RECV_PIN);

// 创建decode_results对象,存储解码后的结果
decode_results results;

void setup() {
 
  Serial.begin(9600);
  
  // 使能红外接收功能
  irrecv.enableIRIn();
  
}

void loop() {
  // 接收到进行解码
  if (irrecv.decode(&results)) {

    Serial.print("接收到的红外信号编码值(十六进制):0x");
    Serial.println(results.value, HEX);
    
    // 输出红外信号的编码格式
    Serial.print("编码格式:");
    switch(results.decode_type) {
      case NEC:
        Serial.println("NEC");
        break;
      case SONY:
        Serial.println("SONY");
        break;
      case RC5:
        Serial.println("RC5");
        break;
      case RC6:
        Serial.println("RC6");
        break;
      default:
        Serial.println("未知格式");
        break;
    }
    
    // 输出红外信号的脉冲数
    Serial.print("脉冲数:");
    Serial.println(results.rawlen);
    
    // 换行,使串口监视器上的输出更清晰
    Serial.println();
    
    // 准备接收下一次红外信号
    irrecv.resume();
  }
}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐