一个能够发送和接收红外信号的库。
可作为 Arduino 库“IRremote”使用。
?谷歌翻译
支持的红外协议
特征
4.x 版本的新功能
3.x 版本的新功能
将 2.x 程序转换为 4.x 版本
如何将旧的 MSB 前 32 位 IR 数据代码转换为新的 LSB 前 32 位 IR 数据代码
使用旧教程的 3.x 版本时出现错误
继续使用 2.x
为什么 *.hpp 而不是 *.cpp
使用新的 *.hpp 文件
教程
指定 IR 代码的 3 种方法
IR接收器引脚排列
接收IR码
免责声明
其他库,可能涵盖这些协议
协议=PULSE_DISTANCE
协议=未知
如何处理 IRremote 不支持的协议
解码IR数据结构
协议不明确
不同协议的RAM使用情况
处理未知协议
发送红外代码
公共 IR 代码数据库列表
发送 IRDB IR 代码
发送图钉
微型 NEC 接收器和发送器
FAST协议
常见问题解答和提示
在analogWrite()或tone()之后或者在运行电机之后接收停止
接收设置溢出标志
Neopixels、FastLed 等问题
无法与其他库一起使用/编译
多个 IR 接收器和发送器实例
增加发送的输出信号的强度
最低 CPU 时钟频率
Bang & Olufsen 协议
该库的示例
WOKWI 在线示例
机器人小车的红外控制
问题和讨论
该库的编译选项/宏
使用 Arduino IDE 更改包含 (*.h) 文件
使用 Sloeber IDE 修改编译选项
支持的主板
定时器和引脚使用
与其他库和 Arduino 命令(例如tone()和analogWrite())不兼容
用于发送的硬件 PWM 信号生成
为什么我们使用 30% 的占空比来发送
我们如何解码信号
NEC 编码图
5个Arduino IR接收库快速对比
历史
有用的链接
贡献者
执照
版权
NEC / Onkyo / Apple
Denon / Sharp
Panasonic / Kaseikyo
JVC
LG
RC5
RC6
Samsung
Sony
Universal Pulse Distance
Universal Pulse Width
Universal Pulse Distance Width
Hash
Pronto
BoseWave
Bang & Olufsen
Lego
FAST
Whynter
MagiQuest
可以通过在#include
行之前定义宏来关闭和打开协议,如下所示:
#define DECODE_NEC//#define DECODE_DENON#include
很多教程和示例。
积极维护。
允许接收和发送原始定时数据。
由于 4.3 IrSender.begin(DISABLE_LED_FEEDBACK)
将不再起作用,请改用IrSender.begin(DISABLE_LED_FEEDBACK, 0)
。
添加了新的通用脉冲距离/脉冲宽度/脉冲距离宽度解码器,涵盖了许多以前未知的协议。
打印如何通过IrReceiver.printIRSendUsage(&Serial)
发送接收到的命令的代码。
对于 32 位平台,RawData 类型现在是 64 位,因此与以前的 32 位平台相比, decodedIRData.decodedRawData
可以包含更多协议的完整帧信息。
收到命令后回调- 一旦收到消息,它就会调用您的代码。
改进了PULSE_DISTANCE
+ PULSE_WIDTH
协议的处理。
新的 FAST 协议。
使用printIRSendUsage()
自动打印相应的发送函数。
您必须将#define DECODE_DISTANCE
替换为#define DECODE_DISTANCE_WIDTH
(仅当您显式启用此解码器时)。
参数bool hasStopBit
不再需要并被删除,例如对于函数sendPulseDistanceWidth()
。
任何引脚都可用于接收,如果未定义SEND_PWM_BY_TIMER
也可用于发送。
可以激活反馈 LED 以进行发送/接收。
提供 8/16 位 **命令值以及 16 位地址和协议号用于解码(而不是旧的 32 位值)。
协议值符合协议标准。
NEC、Panasonic、Sony、Samsung 和 JVC 解码并先发送 LSB。
支持Universal Distance协议,涵盖了很多以前未知的协议。
与tone()库兼容。请参阅 ReceiveDemo 示例。
同时发送和接收。请参阅 SendAndReceive 示例。
支持更多平台。
允许生成非 PWM 信号,仅模拟低电平有效接收器信号,以便直接连接到现有接收设备,而无需使用 IR。
简单的协议配置,直接在源代码中。
减少内存占用并缩短解码时间。
包含一个非常小的 NEC 专用解码器,不需要任何定时器资源。
-> 5 个 Arduino IR 库的功能比较。
从3.1版本开始,用于发送的PWM的生成由软件完成,从而节省了硬件定时器并允许任意输出引脚用于发送。
如果您使用不使用-flto
标志进行编译的(旧)Arduino 核心,并且在编译期间收到有关 begin() 的错误消息,则可以激活 IRRemote.h 中的#define SUPPRESS_ERROR_MESSAGE_FOR_BEGIN
行。
添加了IRreceiver和IRsender对象,无需定义即可使用它们,就像众所周知的 Arduino Serial对象一样。
只需删除行IRrecv IrReceiver(IR_RECEIVE_PIN);
和/或IRsend IrSender;
在您的程序中,并替换所有出现的IRrecv.
或irrecv.
与IrReceiver
并用IrSender
替换所有IRsend
或irsend
。
由于解码值现在位于IrReceiver.decodedIRData
中,而不再位于results
中,因此请删除decode_results results
行或类似行。
与 Serial 对象一样,在 setup() 中调用IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK)
或IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK)
而不是IrReceiver.enableIRIn()
或irrecv.enableIRIn()
。
如需发送,请调用IrSender.begin();
在设置()中。
如果未定义 IR_SEND_PIN(在#include
行之前),则必须使用例如IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN);
旧的decode(decode_results *aResults)
函数被简单的decode()
替换。因此,如果您有一条语句if(irrecv.decode(&results))
将其替换为if (IrReceiver.decode())
。
解码结果现在位于IrReceiver.decodedIRData
中,不再位于results
中,因此将任何出现的results.value
和results.decode_type
(及类似的)替换为IrReceiver.decodedIRData.decodedRawData
和IrReceiver.decodedIRData.protocol
。
溢出、重复和其他标志现在位于IrReceiver.receivedIRData.flags
中。
很少使用: results.rawbuf
和results.rawlen
必须替换为IrReceiver.decodedIRData.rawDataPtr->rawbuf
和IrReceiver.decodedIRData.rawDataPtr->rawlen
。
NEC、Panasonic、Sony、Samsung 和 JVC 5 个协议已先转换为 LSB。用于发送旧 MSB 数据的发送函数已重命名为sendNECMSB
、 sendSamsungMSB()
、 sendSonyMSB()
和sendJVCMSB()
。旧的sendSAMSUNG()
和sendSony()
MSB 函数仍然可用。 sendPanasonic()
函数的旧 MSB 版本已被删除,因为它存在无人识别的错误,因此假定从未使用过。
有关将 MSB 代码转换为 LSB 的信息,请参阅下文。
#include#define RECV_PIN 2IRrecv irrecv(RECV_PIN); 解码结果结果;void setup() { ... 串行.开始(115200); // 建立串口通信 irrecv.enableIRIn(); // 启动接收器}void Loop() { if (irrecv.decode(&results)) { Serial.println(结果.值, HEX); ... irrecv.resume(); // 接收下一个值 } ... }
#include#define IR_RECEIVE_PIN 2void setup() { ... 串行.开始(115200); // // 建立串口通信 IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // 启动接收器}void Loop() { if (IrReceiver.decode()) { Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); // 打印“旧”原始数据 IrReceiver.printIRResultShort(&Serial); // 一行打印完整接收到的数据 IrReceiver.printIRSendUsage(&Serial); // 打印发送此数据所需的语句 ... IrReceiver.resume(); // 允许接收下一个值 } ... }
对于NEC、Panasonic、Sony、Samsung 和 JVC的新解码器,结果IrReceiver.decodedIRData.decodedRawData
现在是LSB-first ,正如这些协议的定义所示!
要将其中一种转换为另一种,必须反转字节/半字节位置,然后反转每个字节/半字节的所有位位置,或者将其写入一个二进制字符串并反转/镜像它。
示例: 0xCB 34 01 02
0x20 10 43 BC
半字节反转后
每个半字节位反转后的0x40 80 2C D3
0->0 1->8 2->4 3->C 4->2 5->A 6->6 7->E 8->1 9->9 A->5 B->D C->3 D->B E->7 F->F
0xCB340102
是二进制1100 1011 0011 0100 0000 0001 0000 0010
。
0x40802CD3
是二进制0100 0000 1000 0000 0010 1100 1101 0011
。
如果向后(从右到左)读取第一个二进制序列,您将得到第二个序列。为此,您可以使用bitreverseOneByte()
或bitreverse32Bit()
。
可以使用sendNECMSB()
、 sendSonyMSB()
、 sendSamsungMSB()
、 sendJVCMSB()
来发送旧的 MSB 代码而不进行转换。
如果您遇到旧教程代码(包括IRremote.h
而不是IRremote.hpp
的错误,只需尝试回滚到版本 2.4.0。
您的代码很可能会运行,并且您不会错过新功能。
考虑为您的项目使用原始 2.4 版本 2017 或最后一个向后兼容的 2.8 版本。
它可能就足够了,并且可以完美地处理 32 位 IR 代码。
如果这不适合您的情况,请放心,4.x 至少会尝试向后兼容,因此您的旧示例应该仍然可以正常工作。
仅以下解码器可用:
NEC
Denon
Panasonic
JVC
LG
RC5
RC6
Samsung
Sony
irrecv.decode(&results)
的调用使用旧的 MSB First 解码器(如 2.x 中),并在results.value
中设置 32 位代码。
无需解码为更有意义(恒定)的 8/16 位地址和 8 位命令。
每个 *.cpp 文件都是通过调用专用于该 cpp 文件的编译器来单独编译的。这些调用由 IDE/make 系统管理。在 Arduino IDE 中,当您单击“验证”或“上传”时,就会执行调用。
现在 Arduino 的问题是:
如何为所有 *.cpp 文件设置编译选项,尤其是使用的库?
Sloeber 或 PlatformIO 等 IDE 通过允许为每个项目指定一组选项来支持这一点。他们在每次编译器调用时添加这些选项,例如-DTRACE
。
但Arduino缺少这个功能。因此,解决方法不是单独编译所有源代码,而是通过将它们包含在源代码中将它们连接到一个巨大的源文件中。
这是通过例如#include "IRremote.hpp"
完成的。
但为什么不#include "IRremote.cpp"
呢?
尝试一下,您会看到大量错误,因为 *.cpp 文件的每个函数现在都编译了两次,第一次编译巨大的文件,第二次单独编译 *.cpp 文件,如上所述。
因此,不再可能使用扩展名cpp ,一种解决方案是使用hpp作为扩展名,以表明它是包含的 *.cpp 文件。
其他所有扩展(例如cinclude)都可以,但hpp似乎是常识。
为了更轻松地支持编译选项,您必须在主程序(又名带有 setup() 和 Loop() 的 *.ino 文件)中使用语句#include
而不是#include
。
在所有其他文件中,您必须使用以下内容,以防止multiple definitions
链接器错误:
#define USE_IRREMOTE_HPP_AS_PLAIN_INCLUDE#include
确保主程序中的所有宏都在#include
之前定义。
否则,以下宏肯定会被默认值覆盖:
RAW_BUFFER_LENGTH
IR_SEND_PIN
SEND_PWM_BY_TIMER
DroneBot Workshop 对 IR 遥控器和 IRremote 库进行了非常详细的介绍。
有 3 种不同的方式来指定特定的 IR 代码。
每个标记/脉冲和脉冲之间的间隔/距离的时序在列表或数组中指定。这可以指定所有 IR 代码,但需要大量内存并且根本不可读。这种定时阵列的一种正式定义(包括频率和重复的规范)是Pronto格式。
使用较低的时间分辨率可以节省内存。对于 IRremote,您可以使用 50 µs 分辨率,通过使用字节值而不是 int16 值,将内存需求减半。为了接收目的,您可以使用由decodeHash()
解码器提供的时间哈希值。
有 3 种主要的编码方案对二进制比特流/十六进制值进行编码:
PULSE_DISTANCE
。脉冲之间的距离决定了位值。这总是需要一个停止位!例如 NEC 和 KASEIKYO 协议。对于大多数协议来说,脉冲宽度是恒定的。
PULSE_WIDTH
。脉冲的宽度决定了位值,脉冲距离是恒定的。这不需要停止位!唯一已知的例子是 SONY 协议。
相位/曼彻斯特编码。脉冲/暂停转换(相位)相对于时钟的时间决定了位值。例如 RC5 和 RC6 协议。
相位编码具有恒定的位长度, PULSE_DISTANCE
具有恒定的脉冲宽度,而PULSE_WIDTH
则没有恒定的位长度!
使用非恒定脉冲宽度编码的PULSE_DISTANCE
的一个众所周知的示例是RS232 串行编码。这里使用非恒定脉冲宽度来实现恒定的位长度。
大多数红外信号都有一个特殊的标头来帮助设置接收器电路的自动增益。该标头不是编码的一部分,但通常对于特殊协议很重要,因此必须是可重现的。
请注意,有些代码使用PULSE_DISTANCE
编码,其中不止一个二进制 0/1 被放入脉冲/暂停组合中。这需要 2 种以上不同的脉冲或暂停长度组合。 HobToHood 协议使用这样的编码。
使用编码方案将 IR 代码的规范简化为比特流/十六进制值,默认情况下为 LSB 以及标头、0 和 1 的脉冲/暂停时序。十六进制值非常可读。这些方案不能在此比特流上放置任何语义,如地址、命令或校验和。
有一些常见协议直接在 IRremote 中实现。它们指定频率、标头、0 和 1 的时序以及其他值,如校验和、重复距离、重复编码、位切换等。还指定了十六进制值的语义,仅允许使用 2 个参数地址和指定 IR 代码的命令。这样可以节省内存并且可读性很高。地址通常也是恒定的,这进一步减少了内存需求。
Adafruit 红外传感器教程
在您的程序中,您可以使用以下命令检查是否已完全接收到 IR 帧:
if (IrReceiver.decode()) {}
这也对接收到的数据进行解码。
成功解码后,IR 数据包含在 IRData 结构中,可用作IrReceiver.decodedIRData
。
结构 IRData { 解码类型_t 协议; // UNKNOWN、NEC、SONY、RC5、PULSE_DISTANCE、... uint16_t 地址; // 解码后的地址 uint16_t 命令; // 解码后的命令 uint16_t extra; // 用于 Kaseikyo 未知供应商 ID。用于解码距离协议的刻度。 uint16_t 位数; // 接收到的数据位数(地址 + 命令 + 奇偶校验) - 确定协议长度(如果可能有不同的长度)。 uint8_t 标志; // IRDATA_FLAGS_IS_REPEAT、IRDATA_FLAGS_WAS_OVERFLOW 等。请参阅 IRDATA_FLAGS_* 定义 IRRawDataType 解码的RawData; // 最多 32 位(32 位 CPU 架构为 64 位)解码原始数据,用于 sendRaw 函数。 uint32_t 解码的RawDataArray[RAW_DATA_ARRAY_SIZE]; // 32 位解码后的原始数据,用于发送功能。 irparams_struct *rawDataPtr; // 要解码的原始时序数据的指针。主要是接收ISR填充的数据缓冲区。};
这是标志字段中包含的标志列表。
使用例如if(IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)
检查它。
旗帜名称 | 描述 |
---|---|
IRDATA_FLAGS_IS_REPEAT | 前一帧之间的间隙小于重复预期的最大间隙。 !!!我们不检查更改的命令或地址,因为几乎不可能在大约 100 毫秒内按下遥控器上的 2 个不同按钮! |
IRDATA_FLAGS_IS_AUTO_REPEAT | 当前重复帧是重复帧,总是在常规帧之后发送并且无法避免。仅指定用于 DENON 和 LEGO 协议。 |
IRDATA_FLAGS_PARITY_FAILED | 当前(自动重复)帧违反奇偶校验。 |
IRDATA_FLAGS_TOGGLE_BIT | 如果设置了 RC5 或 RC6 切换位,则设置该值。 |
IRDATA_FLAGS_EXTRA_INFO | 地址和数据中未包含额外信息(例如,Kaseikyo 未知供应商 ID 或解码的RawDataArray 中)。 |
IRDATA_FLAGS_WAS_OVERFLOW | 指定的RAW_BUFFER_LENGTH 标记和空格过多。为了避免无休止的溢出标记,在这种情况下 irparams.rawlen 设置为 0。 |
IRDATA_FLAGS_IS_MSB_FIRST | 该值主要由(已知)协议决定。 |
自动 myRawdata= IrReceiver.decodedIRData.decodedRawData;
此处描述了IrReceiver.decodedIRData.flags
的定义。
IrReceiver.printIRResultShort(&Serial);
IrReceiver.printIRResultRawFormatted(&Serial, true);`
原始数据取决于 Arduino 定时器相对于接收到的信号的内部状态,因此每次可能会略有不同。 (分辨率问题)。解码后的值是解释后的值,可以容忍如此微小的差异!
IrReceiver.printIRSendUsage(&Serial);
NEC协议定义为8位地址和8位命令。但物理地址和数据字段都是 16 位宽。额外的 8 位用于发送反转地址或奇偶校验命令。
扩展的NEC协议对16位地址使用额外的8位地址奇偶校验位,从而禁用地址的奇偶校验。
ONKYO 协议又使用地址和命令的附加 8 个奇偶校验位来表示 16 位地址和命令。
如果奇偶校验正确,解码器会将 16 位值减少为 8 位值。如果奇偶校验不正确,则假定没有奇偶校验错误,但假设扩展 NEC 或扩展 NEC 协议,则将这些值视为无奇偶校验的 16 位值。
但现在当我们想要接收例如16 位地址 0x00FF 或 0x32CD 时,我们遇到了问题!解码器将此解释为具有正确奇偶校验 0xFF / 0xCD 的 NEC 8 位地址 0x00 / 0x32,并将其减少为 0x00 / 0x32。
处理此问题的一种方法是使用#define DECODE_ONKYO
强制库始终使用 ONKYO 协议解释。另一种方法是检查IrReceiver.decodedIRData.protocol
是否是 NEC 而不是 ONKYO,并手动恢复奇偶校验减少。
长按时, NEC 协议不会重复其帧,而是发送一个特殊的短重复帧。这样可以轻松区分长按和重复按,并节省一些电池电量。这种行为对于 NEC 及其派生协议(例如 LG 和 Samsung)来说非常独特。
当然,也有一些远程控制系统,使用 NEC 协议,但仅在长按时重复第一帧,而不是发送特殊的短重复帧。我们将此命名为NEC2协议,并通过sendNEC2()
发送。
但要小心,NEC2 协议只能在第一帧之后并且长按时才能被 NEC 库解码器检测到!
长按时, SamsungLG 协议不会重复其帧,而是发送特殊的短重复帧。
RAW_BUFFER_LENGTH
确定解码前存储接收到的 IR 定时数据的字节缓冲区的长度。
对于高达 48 位的标准协议来说, 100就足够了,其中 1 位由一个标记和一个空格组成。我们总是需要额外的 4 个字节,1 个字节用于初始间隙,2 个字节用于标头,1 个字节用于停止位。
48位协议有 PANASONIC、KASEIKYO、SAMSUNG48、RC6。
NEC、SAMSUNG、WHYNTER、SONY(20)、LG(28) 等32位协议需要缓冲区长度为 68 。
BOSEWAVE、DENON、FAST、JVC、LEGO_PF、RC5、SONY(12 或 15)等16位协议需要缓冲区长度为 36 。
MAGIQUEST 需要的缓冲区长度为112 。
空调通常发送更长的协议数据流,最多 750 位。
如果RECORD_GAP_MICROS
确定的记录间隙从默认的 8 ms 更改为超过 20 ms,则缓冲区不再是字节,而是 uint16_t 缓冲区,需要两倍的 RAM。
该库旨在适合资源水平相对较低的 MCU 内部,并旨在作为库与其他也需要 MCU 资源才能运行的其他应用程序一起工作。
使用ReceiveDemo 示例打印出有关 IR 协议的所有信息。
ReceiveDump 示例为您提供了更多信息,但由于打印信息所需的时间,重复检测效果不佳。
如果该库似乎不支持您的协议,您可以尝试 IRMP 库,它尤其对曼彻斯特协议支持得更好。
对于空调,您可以尝试 IRremoteESP8266 库,它支持一组令人印象深刻的协议和大量空调,并且也可以在 ESP32 上运行。
Raw-IR-decoder-for-Arduino 不是一个库,而是一个 arduino 示例草图,它提供了许多解码方法,尤其是空调协议。这些协议的发送可以通过 Arduino 库 HeatpumpIR 来完成。
如果你得到这样的东西:
PULSE_DISTANCE: HeaderMarkMicros=8900 HeaderSpaceMicros=4450 MarkMicros=550 OneSpaceMicros=1700 ZeroSpaceMicros=600 NumberOfBits=56 0x43D8613C 0x3BC3BC
那么你就有了一个由56 位组成的代码,它可能来自空调遥控器。
您可以使用sendPulseDistanceWidth()
发送它。
uint32_t tRawData[] = { 0xB02002, 0xA010 }; IrSender.sendPulseDistance(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, false, 0, 0);
您可以通过调用sendPulseDistanceWidthData()
两次来发送它,一次用于前 32 位,下一次用于其余 24 位。
PULSE_DISTANCE
/ PULSE_WIDTH
解码器仅将定时流解码为存储为十六进制值的比特流。这些解码器不能在此比特流上放置任何语义,如地址、命令或校验和。但比特流比定时流更具可读性。默认情况下,该比特流首先读取 LSB 。如果LSB不适合进一步研究,可以在这里更改。
如果 RAM 不超过 2k,则解码器仅接受最多 2500 微秒的标记或空间持续时间以节省 RAM 空间,否则它接受最多 10 毫秒的持续时间。
如果您看到类似Protocol=UNKNOWN Hash=0x13BD886C 35 bits received
内容,则说明您在解码协议时遇到问题,或者协议不受支持。
如果收到的位数为奇数,则您的接收器电路可能有问题。可能是因为红外信号太弱。
如果您看到像+ 600,- 600 + 550,- 150 + 200,- 100 + 750,- 550
这样的时序,那么一个 450 µs 的空间被分成两个 150 和 100 µs 的空间,其间有 200 µs 的尖峰/误差信号。可能是因为接收器有缺陷或与附近的另一个发光源结合时信号较弱。
如果您看到像+ 500,- 550 + 450,- 550 + 450,- 500 + 500,-1550
这样的计时,那么标记通常比空格短,因此MARK_EXCESS_MICROS
(在您的 ino 文件中指定)应该为负数以补偿这一点在解码时。
如果您看到Protocol=UNKNOWN Hash=0x0 1 bits received
,则可能是初始标记之后的空格比RECORD_GAP_MICROS
长。在一些 LG 空调协议中观察到了这一点。在 .ino 文件中的#include
行之前使用一行重试,例如#define RECORD_GAP_MICROS 12000
。
要查看更多信息来支持您查找 UNKNOWN 协议的原因,您必须在 IRremoteInt.h 中启用//#define DEBUG
行。
如果您不知道您的红外发射器使用哪种协议,您有多种选择。
只需使用哈希值来决定接收到哪个命令。请参阅 SimpleReceiverForHashCodes 示例。
使用 IRreceiveDemo 示例或 IRreceiveDump 示例转储 IR 时序。然后,您可以使用 SendRawDemo 示例重现/发送该计时。
IRMP AllProtocol 示例打印40 个受支持协议之一的协议和数据。可以使用相同的库来发送此代码。
如果您手头有更大的 Arduino 板(> 100 kByte 程序内存),您可以尝试 Arduino 库 DecodeIR 的 IRremoteDecode 示例。
使用 IrScrutinizer。它可以通过导出为“Arduino Raw”来自动为您的协议生成发送草图。它支持 IRremote、旧的 IRLib 和 Infrared4Arduino。
如果您手头有一个可以生成您想要使用的 IR 代码的设备(又名 IR 遥控器),建议使用 ReceiveDemo 示例接收代码,该示例将在串行输出上告诉您如何发送它们。
Protocol=LG Address=0x2 Command=0x3434 Raw-Data=0x23434E 28 bits MSB first Send with: IrSender.sendLG(0x2, 0x3434,);
您会发现地址是一个常量,并且命令有时会被合理地分组。
如果您不确定用于发送的重复次数, 3是一个很好的起点。如果这有效,您可以稍后检查较低的值。
如果启用了DECODE_DISTANCE_WIDTH
,则printIRSendUsage()
打印的代码在 8 位和 32 位平台上会有所不同,因此最好在与发送程序相同的平台上运行接收程序。
如果合理的话,所有发送功能都支持重复发送。重复帧按照协议确定的固定周期发送。例如,对于 NEC,从开始到开始为 110 毫秒。
请记住,在最后发送的标记之后没有延迟。如果您自己处理重复帧的发送,则必须在重复帧之前插入合理的延迟才能正确解码。
可以使用sendNECMSB()
、 sendSonyMSB()
、 sendSamsungMSB()
、 sendJVCMSB()
来发送旧的 MSB 代码而不进行转换。
Flipper-IRDB 数据库中的代码转换起来非常简单,因为它们也使用地址/命令方案。
协议匹配为 NECext -> NECext(或 Onkyo)、Samsung32 -> Samsung、SIRC20 -> Sony(20 位)等。
irdb 数据库中找到的代码指定了一个设备、一个子设备和一个函数。大多数时候,设备和子设备可以作为地址参数的高字节和低字节,而函数是具有地址、命令和重复计数参数的新结构化函数的命令参数,例如IrSender.sendNEC((device << 8) | subdevice, 0x19, 2)
.
可以在 IR 协议的 IRP 定义文件中找到精确的映射。 “D”和“S”表示设备和子设备,“F”表示功能。
任何引脚都可以选择作为发送引脚,因为 PWM 信号默认是通过软件位联动生成的,因为SEND_PWM_BY_TIMER
未激活。
在ESP32上,ledc 通道 0 用于生成 IR PWM。
如果指定了IR_SEND_PIN
(作为 c 宏),则会减少程序大小并改善 AVR 的发送时序。如果您想使用变量来指定发送引脚,例如使用setSendPin(uint8_t aSendPinNumber)
,则必须禁用此IR_SEND_PIN
宏。然后您可以在发送 IR 帧之前随时更改发送引脚。另请参阅此库的编译选项/宏。
http://www.harctoolbox.org/IR-resources.html
Flipper IRDB 数据库
翻转解码 | 红外遥控解码 |
---|---|
三星32 | 三星 |
日本电气公司 | 日本电气公司 |
NECext | 安桥 |
<起始位><供应商ID:16><供应商ID奇偶校验:4><流派1:4><流派2:4><命令:10> ID 是地址的 MSB。 地址:8A 02 20 00 命令:56 03 00 00 ->红外远程: 地址0x6A8,发送Panasonic(02 20)和命令0x35 | <起始位> |
对于仅需要 NEC、NEC 变体或 FAST(见下文)协议的应用,包含一个特殊的接收器/发送器,其代码大小非常小,为 500 字节,并且不需要任何定时器。
TinyReceiver 接收器不像 IRremote 那样每 50 µs 对输入进行一次采样,而是使用引脚更改中断进行动态解码,这限制了协议的选择。
在每次级别更改时,级别和自上次更改以来的时间用于增量解码协议。
有了这个工作原理,我们就不能像IRremote那样等待超时然后解码协议了。
相反,我们需要知道哪个是协议的最后一位(级别更改)来进行最终解码以及调用可选的用户提供的回调函数handleTinyReceivedIRData()
。
这意味着,我们需要了解协议中的位数,从而了解协议(系列)。
查看 TinyReceiver 和 IRDispatcherDemo 示例。
请注意包含TinyIRReceiver.hpp
或TinyIRSender.hpp
而不是IRremote.hpp
。
//#define USE_ONKYO_PROTOCOL // 与 NEC 类似,但将 16 位地址和命令分别视为一个 16 位值,而不是 8 位正常值和 8 位反转值。//#define USE_FAST_PROTOCOL // 使用 FAST 协议而不是 NEC / ONKYO#include "TinyIRReceiver.hpp"void setup() { initPCIInterruptForTinyReceiver(); // 在 IR 输入信号发生变化时启用中断生成}void Loop() { if (TinyReceiverDecode()) { printTinyReceiverResultMinimal(&Serial); } // 不需要resume() :-)}
#include "TinyIRSender.hpp"void setup() { sendNEC(3, 0, 11, 2); // 在引脚 3 上发送地址 0 和命令 11,重复 2 次。}void Loop() {}
可以在这里找到另一个支持更多协议的微型接收器和发送器。
FAST 协议是一种专有的修改后的 JVC 协议,不带地址、具有奇偶校验且具有较短的标头。它的目的是对在另一块板上发送协议帧的事件做出快速响应。 FAST 的发送时间为 21 ms ,发送周期为 50 ms 。它具有用于错误检测的完整 8 位奇偶校验。
位时序就像 JVC
标头更短,3156 µs 与 12500 µs
无地址和 16 位数据,解释为 8 位命令和 8 位反转命令,导致固定协议长度为 (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 微秒或 29 毫秒。
重复作为完整帧发送,但周期为 50 毫秒/距离为 21 毫秒。
#define IR_SEND_PIN 3#includevoid setup() { sendFAST(11, 2); // 在引脚 3 上发送命令 11,重复 2 次。}void Loop() {}
#define USE_FAST_PROTOCOL // 使用 FAST 协议。无地址和 16 位数据,解释为 8 位命令和 8 位反转命令#include "TinyIRSender.hpp"void setup() { sendFAST(3, 11, 2); // 在引脚 3 上发送命令 11,重复 2 次。}void Loop() {}
FAST协议可以通过IRremote和TinyIRReceiver接收。
50 µs 的接收器采样间隔由定时器生成。在许多板上,这必须是硬件定时器。在一些有软件定时器的板卡上,使用软件定时器。
请注意,用于接收的硬件定时器不应用于analogWrite()
。
特别是电机控制经常使用analogWrite()
函数,因此如果在此处指示的引脚上使用,将停止接收。
在 Uno 和其他 AVR 板上,接收器计时器与音频计时器相同。因此,接收将在tone()
命令之后停止。请参阅 ReceiveDemo 示例如何处理它,即如何使用IrReceiver.restartTimer()
。
如果RAW_BUFFER_LENGTH
对于协议的所有标记和空间来说太小,则设置标志IRDATA_FLAGS_WAS_OVERFLOW
。这可能发生在长协议帧上,例如来自空调的协议帧。如果RECORD_GAP_MICROS
小于一帧和第三个重复帧之间的实际间隙,则也可能发生这种情况,从而将两者解释为一个连续帧。最好的办法就是放弃时机,看看哪个理由成立。
当您使用Neopixels (又名 WS2811/WS2812/WS2812B)或其他阻塞中断时间较长(> 50 µs)的库时,IRremote 将无法正常工作。
无论您使用 Adafruit Neopixel lib 还是 FastLED,许多低端 CPU(例如基本 Arduino)上的中断都会被禁用超过 50 µs。反过来,这会在需要时停止 IR 中断处理程序的运行。另请参阅此视频。
一种解决方法是等待 IR 接收器空闲,然后再使用if (IrReceiver.isIdle()) { strip.show();}
发送 Neopixel 数据。
这至少可以防止中断正在运行的红外传输,并且(取决于 Neopixel 的更新速率)可能会很好地工作。
在更强大的处理器上还有一些其他解决方案,请参阅 Marc MERLIN 的此页面
仅当您停用IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
行时,另一个库才会工作/编译。 。
这通常是由于定时器资源与其他库发生冲突。请看下文。
该库仅支持每个 CPU 一个 IR 接收器和一个 IR 发送器对象(IRrecv 和 IRsend)。
然而,由于发送是一个串行任务,您可以使用setSendPin()
来切换要发送的引脚,从而模拟多个发送者。
接收器使用特殊的定时器触发功能,每 50 µs 从一个引脚读取数字红外信号值。
因此,必须将多个红外接收器的输出引脚连接在一起才能使用多个红外接收器。 IR 接收器模块内部使用 NPN 晶体管作为输出设备,只需一个 30k 电阻连接到 VCC。这基本上是一个“集电极开路”,允许多个输出引脚连接到一个 Arduino 输入引脚。
但是,请记住,来自其中一个接收器的任何微弱/受干扰的信号也会干扰来自另一个接收器的良好信号。
免费增加红外功率的最佳方法是串联使用 2 或 3 个红外二极管。一个二极管在 20 mA 时需要 1.2 V 电压,在 100 mA 时需要 1.5 V 电压,因此您可以为最多 3 个二极管提供 5 V 输出。
要使用 1.2 V 和 20 mA 以及 5 V 电源为2 个二极管供电,请将电阻器设置为:(5 V - 2.4 V) -> 2.6 V / 20 mA = 130 Ω 。
对于3 个二极管,需要 1.4 V/20 mA = 70 Ω 。
由于AVR 引脚处的损耗,实际电流可能会更低。例如,20 mA 时为 0.3 V。
如果不需要超过20mA的电流,则无需使用外部晶体管(至少对于AVR芯片而言)。
在我的 Arduino Nano 上,我总是使用 100 Ω 串联电阻和一个 IR LED ?。
对于接收,最小 CPU 时钟频率为 4 MHz ,因为 50 µs 定时器 ISR(中断服务例程)在 16 MHz ATmega 上大约需要 12 µs。
TinyReceiver 不需要轮询,运行频率为 1 MHz。
对于发送,默认软件生成的 PWM 在以 8 MHz 运行的 AVR 上存在问题。 PWM 频率约为 30 kHz,而不是 38 kHz,RC6 不可靠。您可以通过#define SEND_PWM_BY_TIMER
切换到定时器 PWM 生成。
默认情况下,Bang & Olufsen 协议解码器未启用,即如果 #define DECODE_
未显式启用任何协议。它必须始终通过#define DECODE_BEO
显式启用。这是因为它的IR 传输频率为 455 kHz ,因此需要不同的接收器硬件 (TSOP7000)。
由于生成 455 kHz PWM 信号目前仅针对SEND_PWM_BY_TIMER
实现,因此仅当定义了SEND_PWM_BY_TIMER
或USE_NO_SEND_PWM
时,发送才有效。
有关详细信息,请参阅 ir_BangOlufsen.hpp。
这些示例位于文件 > 示例 > 自定义库/IRremote 中的示例。
为了使示例适合 ATtiny85 和 ATtiny88 的 8K 闪存,该 CPU 需要 Arduino 库 ATtinySerialOut。
另请参阅 DroneBot Workshop SimpleReceiver 和 SimpleSender。
SimpleReceiver和SimpleSender示例是一个很好的起点。一个简单的例子可以用 WOKWI 在线测试。
SimpleReceiverForHashCodes仅使用哈希解码器。它将所有长度超过 6 的 IR 帧转换为 32 位哈希码,从而能够接收未知协议。
请参阅:http://www.righto.com/2010/01/using-centric-remotes-with-arduino.html
如果代码大小或计时器使用很重要,请查看这些示例。
TinyReceiver示例使用TinyIRReceiver库,该库只能接收 NEC、Extend NEC、ONKYO 和 FAST 协议,但不需要任何定时器。他们使用引脚更改中断进行动态解码,这就是协议选择受到限制的原因。
TinyReceiver可以用WOKWI在线测试。
TinySender示例使用TinyIRSender库,该库只能发送 NEC、ONKYO 和 FAST 协议。
它以标准格式发送 NEC 协议代码,具有 8 位地址和 8 位命令,如 SimpleSender 示例中所示。它可以选择使用扩展 NEC、ONKYO 和 FAST 协议进行发送。与 SimpleSender 相比,节省 780 字节程序内存和 26 字节 RAM,SimpleSender 的功能相同,但使用 IRRemote 库(因此更加灵活)。
如果协议不是 NEC 并且代码大小很重要,请查看此示例。
ReceiveDemo 接收所有协议,并使用 Arduinotone() 函数在收到的每个数据包上生成蜂鸣声。
检测到长按一个红外按钮(接收一个命令的多次重复)。
AllProtocolsOnLCD 还在1602 LCD 上显示简短结果。 LCD 可以并行或串行连接 (I2C)。
通过将调试引脚接地,您可以强制打印每个帧的原始值。调试引脚的引脚编号在设置期间打印,因为它取决于板和 LCD 连接类型。
此示例还作为如何一起使用 IRremote 和tone() 的示例。
接收所有协议并以不同风格(包括 Pronto 格式)转储接收到的信号。由于打印需要很长时间,重复信号可能会被跳过或解释为未知。
至少发送一次所有可用协议。
发送时演示接收。
按下按钮时记录并回放最后接收到的红外信号。已知协议的IR帧由适当的协议编码器发送。 UNKNOWN
协议帧存储为原始数据并使用sendRaw()
发送。
尝试使用通用DistanceWidth 解码器解码每个 IR 帧,存储数据并在按下按钮时使用sendPulseDistanceWidthFromArray()
发送数据。
如果 RAM 不超过 2k,则解码器仅接受最多 2500 微秒的标记或空间持续时间以节省 RAM 空间,否则它接受最多 10 毫秒的持续时间。
距离宽度协议存储数据需要17个字节。 ReceiveAndSend 示例需要 16 个字节用于已知协议数据,37 个字节用于egNEC 协议的原始数据。
用作红外远程宏扩展器。接收 Samsung32 协议并在接收到指定的输入帧时,它会发送多个 Samsung32 帧,并在其间有适当的延迟。这是我的旧三星 H5273 电视的Netflix 密钥模拟。
用于为不同的 IR 代码调用程序的不同函数的框架。
用遥控器控制继电器(连接到输出引脚)。
用户定义类的示例,它本身使用 IRremote 中的 IRrecv 类。
发送由串行输入控制的 LG 空调 IR 代码的示例。
只需使用函数bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter)
您就可以通过任何其他命令源控制空调。
文件acLG.h包含 LG 空调 IR 协议的命令文档。基于 LG AKB73315611 遥控器的逆向工程。
IReceiverTimingAnalysis 可以使用 WOKWI 进行在线测试。在模拟运行时单击接收器以指定各个 IR 代码。
接收和发送 AEG/Elektrolux Hob2Hood 协议的示例。
此示例分析 IR 接收器模块传送的信号。值可用于确定接收信号的稳定性以及用于确定协议的提示。
它还计算MARK_EXCESS_MICROS
值,该值是 IR 接收器模块引入的标记(脉冲)持续时间的扩展。
可以用 WOKWI 在线测试。在仿真运行时单击接收器以指定各个 NEC IR 代码。
ReceiveDemo + SendDemo 在一个程序中。发送时演示接收。在这里您可以看到接收器输出(蓝色)与红外二极管输入(黄色)之间的延迟。
简易接收器
通过 IR 键 5 进行简单切换
小接收器
接收时序分析
带 LCD 输出和开关语句的接收器
Arduino PWMMotorControl 库的此示例使用 IRremote 库控制机器人汽车的基本功能。
它控制2个PWM电机通道,每个通道2个电机。
在这里您可以找到汽车组装和代码的说明。
IR_RobotCar,TL1838 红外接收器插入扩展板。
在未先测试一些示例之前,请勿提出问题!
如果您遇到问题,请发布显示此问题的 MCVE(最小完整可验证示例)。我的经验是,大多数时候你会在创建这个 MCVE 时发现问题?
使用代码块;当我们可以阅读您的代码时,它可以帮助我们为您提供帮助!
要根据不同的要求定制库,可以使用一些编译选项/宏。
这些宏必须在程序中的#include
行之前定义才能生效。
通过启用/禁用它们来修改它们,或者更改值(如果适用)。
姓名 | 默认值 | 描述 |
---|---|---|
RAW_BUFFER_LENGTH | 200 | 原始输入 uint16_t 缓冲区的缓冲区大小。一定要均匀!如果太小,将设置溢出标志。对于高达 48 位的常规协议,100 就足够了,但对于大多数空调协议,需要高达 750 的值。使用 ReceiveDump 示例查找满足您要求的最小值。值 200 需要 200 字节 RAM。 |
EXCLUDE_UNIVERSAL_PROTOCOLS | 残疾人 | 从decode() 中排除脉冲距离宽度协议的通用解码器和decodeHash(所有协议的特殊解码器)。最多可节省 1000 字节程序存储器。 |
DECODE_ | 全部 | 选择要解码的单个协议。您可以指定多个协议。看这里 |
DECODE_STRICT_CHECKS | 残疾人 | 检查协议时序所需的其他特性,例如常量标记协议的标记长度,其中空间长度决定位值。需要最多 194 个字节的程序存储器。 |
IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK | 残疾人 | 最多可保存 60 字节程序存储器和 2 字节 RAM。 |
MARK_EXCESS_MICROS | 20 | MARK_EXCESS_MICROS 在解码前从所有标记中减去并添加到所有空格中,以补偿不同红外接收模块的信号形成。 |
RECORD_GAP_MICROS | 5000 | IR 传输之间的最小间隙,用于检测协议的结束。 必须大于协议的任何空间,例如 4500 µs 的 NEC 标头空间。 必须小于命令和重复之间的任何间隙;例如,索尼的重传间隙约为 24 毫秒。 请记住,这是接收到的命令结束与解码开始之间的延迟。 |
DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE | 如果 RAM <= 2k,则为 50,否则为 200 | 值 200 允许解码长达 10 ms 的标记或间隔持续时间。 |
IR_INPUT_IS_ACTIVE_HIGH | 残疾人 | 如果您使用具有高电平有效输出信号的 RF 接收器,请启用它。 |
IR_SEND_PIN | 残疾人 | 如果指定,它会减少程序大小并改善 AVR 的发送时序。如果您想使用变量来指定发送引脚,例如使用setSendPin(uint8_t aSendPinNumber) ,则不得在源中使用/禁用此宏。 |
SEND_PWM_BY_TIMER | 残疾人 | 禁用软件中的载波 PWM 生成并使用硬件 PWM(通过定时器)。具有更精确的 PWM 生成的优点,特别是占空比
展开
附加信息
相关应用
为您推荐
相关资讯
全部
|