红外遥控您的电脑
本文介绍了一种最简单的方法,可以使用您已有的任何红外遥控器来远程控制任何计算机。想法是从沙发上控制计算机上的音乐或视频播放器。我在互联网上看到了许多此类项目,但没有一个让我满意。
特点
- 这个项目非常容易构建。也非常适合绝对的初学者
- 它适用于任何操作系统:Windows、Linux、Macintosh……
- 超简单的硬件。您只需要焊接3根电线
- 硬件非常小巧(3.6厘米 x 1.8厘米)
- 非常便宜:总硬件成本为 21 美元
- 您无需在计算机上安装任何额外软件
- 适用于任何遥控器,无论其发送何种信号
- 无需为每种遥控信号类型编程特殊的解码器
- 自动检测红外数据速率(“比特率”)
- 通过模拟USB键盘向计算机发送按键
- 通过虚拟串行端口(CDC)将调试输出发送到计算机,该端口实时显示红外信号
- 接收器非常灵敏。即使红外信号需要反射两次才能到达,也能在几米远的地方接收到
- 只需几分钟即可将源代码适配到您的需求(将按键分配给遥控按钮)
要求
- 您需要一个可以通过键盘按键控制的音乐播放器或视频播放器。
- 播放器程序必须在前台(活动窗口),否则将无法接收到按键。
我的目的
我想控制我电脑上的音乐播放器。我使用的是MusicMatch。这个程序已经比较老了,但比WinAmp或Windows Media Player好很多。该程序最主要的功能可以通过键盘控制:播放、暂停、停止、下一曲、上一曲。这对我来说已经足够了。
我的功放有这个遥控器
我用红色标记的按钮在听电脑音乐时没有功能。
它们是用于调谐器和其他用途的。
当我按下这些按钮中的任何一个时,功放都不会有任何反应。
所以我的想法是重新利用这些按钮来控制电脑。
硬件
只需要两个组件:一个红外接收芯片和一个Teensy 3.2。
IR接收器的+5V电源来自USB线。
即使是初学者也很容易焊接这3根线。
IR接收器TSOP38238非常灵敏。它有一个38 kHz的带通滤波器,用于过滤来自遥控器的信号。
此滤波器是必需的,以消除噪声,因为荧光灯会发出非常“嘈杂”的光。
如果您在客厅使用荧光灯,您可能会发现遥控器的灵敏度会变差。
大多数遥控器使用38 kHz载波频率。有些使用36 kHz,这也可以工作。(请参阅Zip文件中的数据手册)
只有少数公司(如 Bang & Olufsen)使用完全不同的频率。
在这种情况下,您需要另一个接收芯片或另一个遥控器。
您可以在一些在线商店购买此IR接收器(或类似型号)
Teensy (20 美元) 也可以从 Adafruit 和 Digikey 购买。或者您可以直接从 PJRC 购买。
Teensy 3.2 是一款非常通用且速度极快的开发板,内存容量大。
与Arduino开发板不同,Teensy配备了更好的软件库(TeensyDuino),可以轻松模拟USB设备(键盘、鼠标、游戏手柄等)。此外,Teensy比Arduino开发板体积更小(3.6厘米 x 1.8厘米),价格也更便宜(20 美元)。
遥控器
这里可以看到我用于测试的一些遥控器
它们分别来自雅马哈功放、Grundig 功放(来自20世纪90年代,至今仍可用!)和 LG 电视。下方中间是一个来自
红外信号
雅马哈、LG、NEC 和 LED 控制器的红外信号看起来是这样的
这是在 IR 接收芯片输出端测得的。当没有 IR 信号时,输出为高电平。当检测到 38 kHz 的载波频率时,输出变为低电平。换句话说:上述信号中的每个低电平对应一个 38 kHz 调制光的脉冲。对于上述所有遥控器,最短的低电平脉冲约为 550 µs。整个信号包含 67 个高/低过渡。开头有一个较长的起始阶段,为电视或 Hi-Fi 设备中的接收微处理器提供足够的时间来准备接收 IR 信号。下方的数字(白色)表示低电平或高电平脉冲的长度。“1”表示 550 µs。“3”表示 3 x 550 µs = 1650 µs。我的源代码会自动检测 IR 信号的“比特率”。
上面的信号编码了遥控器上按下的一个按钮。每个按钮会产生不同的信号。但如果您长时间按下某个按钮(例如,调高音量),遥控器会发送一个“重复序列”,该序列始终相同。
所以,如果您按下“音量增大”按钮,就会发送第一个图像中的信号一次,然后只要您按住该按钮,就会重复发送第二个图像中的信号。
通用遥控信号检测
我在 Github 和 Teensyduino 库中看到了非常长的 IR 信号解码代码。对于每种遥控信号类型,都编写了一个单独的解码器:适用于 Aiwa、Denon、JVC、LG、Lego、Mitsubishi、NEC、Panasonic、RC5、RC6、Samsung、Sanyo、Sharp、Sony、Whynter。巨大的库包含数千行代码。那么,哪个对应雅马哈呢?如果我的型号未实现怎么办?例如,Grundig 就缺失了。这肯定不是一个通用的解决方案。
我还找到了一个 Linux 项目,需要数百个配置文件。每种遥控器都必须编写一个单独的配置文件。这肯定不是我的项目。
互联网上也有一些硬件项目,它们使用的硬件要复杂得多,也昂贵得多。我发现一个项目甚至使用了无法通过 USB 线像 Teensy/Arduino 板那样编程的微处理器。您需要购买额外的硬件编程器来上传固件。对我来说,这绝对不可能!
我一直在寻找一种不依赖于遥控信号类型的最简单的解决方案。我找到了一个:我根本不关心信号中每个比特的含义。在第一步,我检测短脉冲长度的平均值(对于绝大多数控制,这个值在 400µs 到 700µs 之间)。有些遥控器对 Lo 和 Hi 脉冲使用不同的间隔。例如,Hi 为 400µs,Low 为 600µs。因此,我的代码会单独计算它们。然后我计算乘数。对于上图中的信号,我得到:16,8,1,1,1,3,1,1,1,3,1,3,1,3,..... 我不需要理解它们的意思。我只需要识别它们何时出现。然后我将信号转换为字符串,并从此字符串计算 CRC 32。对于遥控器上的每个按钮,我都会得到一个不同的 8 位十六进制值。我的“解码器”只需要不到 50 行 C 代码。
当信号为低电平时,我使用小写字母;当信号为高电平时,我使用大写字母。
例如,“1”变成“A”或“a”。“3”变成“C”或“c”,等等...
但是,起始阶段的两个长脉冲(9毫秒和4.5毫秒)是一个例外。它们不是短脉冲的整数倍。因此,第一个长脉冲可能有时被检测为短脉冲长度的16倍,有时是15倍。因此,我将长脉冲替换为“X”或“x”,因为它们的精确长度并不重要。
雅马哈代码
Lo: 9000 us --> Len: 15 --> Char: 'x' Hi: 4473 us --> Len: 8 --> Char: 'X' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 537 us short --> Len: 1 --> Char: 'A' Lo: 613 us short --> Len: 1 --> Char: 'a' Hi: 1633 us --> Len: 3 --> Char: 'C' Lo: 579 us short --> Len: 1 --> Char: 'a' Hi: 541 us short --> Len: 1 --> Char: 'A' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 1657 us --> Len: 3 --> Char: 'C' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 1662 us --> Len: 3 --> Char: 'C' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 1659 us --> Len: 3 --> Char: 'C' Lo: 584 us short --> Len: 1 --> Char: 'a' Hi: 1659 us --> Len: 3 --> Char: 'C' Lo: 583 us short --> Len: 1 --> Char: 'a' Hi: 537 us short --> Len: 1 --> Char: 'A' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 1662 us --> Len: 3 --> Char: 'C' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 539 us short --> Len: 1 --> Char: 'A' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 1660 us --> Len: 3 --> Char: 'C' Lo: 579 us short --> Len: 1 --> Char: 'a' Hi: 541 us short --> Len: 1 --> Char: 'A' Lo: 584 us short --> Len: 1 --> Char: 'a' Hi: 536 us short --> Len: 1 --> Char: 'A' Lo: 583 us short --> Len: 1 --> Char: 'a' Hi: 537 us short --> Len: 1 --> Char: 'A' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 535 us short --> Len: 1 --> Char: 'A' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 1658 us --> Len: 3 --> Char: 'C' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 535 us short --> Len: 1 --> Char: 'A' Lo: 586 us short --> Len: 1 --> Char: 'a' Hi: 1659 us --> Len: 3 --> Char: 'C' Lo: 609 us short --> Len: 1 --> Char: 'a' Hi: 510 us short --> Len: 1 --> Char: 'A' Lo: 584 us short --> Len: 1 --> Char: 'a' Hi: 1659 us --> Len: 3 --> Char: 'C' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 1636 us --> Len: 3 --> Char: 'C' Lo: 606 us short --> Len: 1 --> Char: 'a' Hi: 539 us short --> Len: 1 --> Char: 'A' Lo: 586 us short --> Len: 1 --> Char: 'a' Hi: 532 us short --> Len: 1 --> Char: 'A' Lo: 588 us short --> Len: 1 --> Char: 'a' Hi: 537 us short --> Len: 1 --> Char: 'A' Lo: 583 us short --> Len: 1 --> Char: 'a' Hi: 1637 us --> Len: 3 --> Char: 'C' Lo: 632 us short --> Len: 1 --> Char: 'a' Hi: 486 us short --> Len: 1 --> Char: 'A' Lo: 607 us short --> Len: 1 --> Char: 'a' Hi: 1662 us --> Len: 3 --> Char: 'C' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 539 us short --> Len: 1 --> Char: 'A' Lo: 581 us short --> Len: 1 --> Char: 'a' Hi: 541 us short --> Len: 1 --> Char: 'A' Lo: 583 us short --> Len: 1 --> Char: 'a' Hi: 1655 us --> Len: 3 --> Char: 'C' Lo: 584 us short --> Len: 1 --> Char: 'a' Hi: 1659 us --> Len: 3 --> Char: 'C' Lo: 585 us short --> Len: 1 --> Char: 'a' Hi: 1657 us --> Len: 3 --> Char: 'C' Lo: 585 us short --> Len: 1 --> Char: 'a' Lo: Shortest: 579 us, Limit: 868 us, Average over 33 short intervals: 587 us Hi: Shortest: 486 us, Limit: 729 us, Average over 16 short intervals: 532 us Decoded: xXaAaCaAaCaCaCaCaAaCaAaCaAaAaAaAaCaAaCaAaCaCaAaAaAaCaAaCaAaAaCaCaCa CRC: 0x1856440C Button: Volume Up -------------------------- Lo: 9025 us --> Len: 16 --> Char: 'x' Hi: 2210 us short --> Len: 4 --> Char: 'D' Lo: 581 us short --> Len: 1 --> Char: 'a' Lo: Shortest: 581 us, Limit: 871 us, Average over 1 short intervals: 581 us Decoded: xDa CRC: 0xF4FCC4CA Button: Volume Up -------------------------- |
这是发送到计算机虚拟串行 COM 端口的调试输出。例如,您可以在 Arduino 编译器的“Serial Monitor”中看到此输出。您可以确切地看到 Teensy 接收到了什么以及它是如何处理的。最后会打印出 CRC,它标识了遥控器上的按钮或重复序列。
我的代码也处理“重复序列”。只要按住遥控器上的任何按钮,就会发送重复器。对于音量增大/减小等按钮,让按键重复到计算机是有意义的。但对于“暂停”按钮则没有意义。如果您重复“暂停”命令,音频/视频播放器会在您按下按钮时在播放和暂停之间不断切换。有些遥控器根本不使用重复序列。因此,我的代码有一个标志,您必须只为需要重复的命令设置该标志。
注意:在计算机上调节音量是错误的。您应该始终将计算机的音量保持在 100%,只在您的功放上调节音量。
Grundig 代码
Decoded: aXaAaAaAaAaAaAaAaAaAa Decoded: aXaAaBbAaAaAaAaAaAa Decoded: aXaAaBbAaAaAaAaAaAa Decoded: aXaAaBbAaAaAaAaAaAa Decoded: aXaAaAaAaAaAaAaAaAaAa |
它完全不同
- 它使用短脉冲和长脉冲之间 1:2 的比例,而不是雅马哈的 1:3。(“b”和“B”而不是“c”和“C”)
- 数据包短得多。
- 与其发送重复序列,不如在按住按钮时重复发送命令本身。
- 命令的前后会发送一个始终相同的序列:0101010101010101010
但遥控器之间的所有这些差异都不重要。我的代码适用于任何遥控器。
控制电脑
对于 MusicMatch 播放器,需要发送以下按键
- 遥控器上的播放按钮发送 CTRL + P 到电脑
- 遥控器上的停止按钮发送 CTRL + S 到电脑
- 遥控器上的暂停按钮发送 Pause 键到电脑
- 遥控器上的调低按钮发送 ALT + 左箭头 到电脑(上一曲)
- 遥控器上的调高按钮发送 ALT + 右箭头 到电脑(下一曲)
您只需要修改 `ExecuteAction()` 函数以满足您的需求。您可以通过调试输出来获取每个按钮的 CRC 代码,然后将其复制粘贴到源代码中。 `PressKey()` 函数随后通过 Teensy 模拟的 USB 键盘将按键发送到计算机。
void ExecuteAction(uint32_t u32_CRC) { ..... switch (u32_CRC) { case 0xA9EBE518: Serial.println("Button: Tuning Up"); PressKey(MODIFIERKEY_ALT, KEY_RIGHT, 0); // Next Track break; case 0x168ECD6E: Serial.println("Button: Tuning Down"); PressKey(MODIFIERKEY_ALT, KEY_LEFT, 0); // Previous Track break; case 0x8F21CFD3: Serial.println("Button: Play"); PressKey(MODIFIERKEY_CTRL, KEY_P, 0); // Play break; case 0x3044E7A5: Serial.println("Button: Stop"); PressKey(MODIFIERKEY_CTRL, KEY_S, 0); // Stop break; case 0x57041AEF: Serial.println("Button: Pause"); PressKey(0, KEY_PAUSE, 0); // Pause break; ..... } ...... } |
特殊情况:RC5
有些遥控器会发送一个切换位。一个典型的例子是飞利浦开发的 RC5 代码
这意味着每次按下遥控器上的同一个按钮时,这个位都会被切换。所以您会为同一个按钮得到两个 CRC 代码:一个切换位为高,一个切换位为低。在这种情况下,您的代码应该如下所示
switch (u32_CRC) { case 0xA9EBE518: // Toggle bit = 1 case 0x4F78A03C: // Toggle bit = 0 Serial.println("Button: Tuning Up"); PressKey(MODIFIERKEY_ALT, KEY_RIGHT, 0); // Next Track break; ..... } |
编程
要对 Teensy 的处理器进行编程,您需要一根 micro USB 线,并需要安装
您需要像此截图中的红色设置一样配置编译器
使用“Serial + Keyboard + Mouse + Joystick”选项,Teensy 可以模拟 USB HID 键盘、HID 鼠标和 HID 游戏手柄。这里只使用键盘。“Serial”是您将在计算机上看到的虚拟 COM 端口,您将从那里接收调试输出。
您可以使用免费软件 TeraTerm 或 Arduino 编译器的“Serial Monitor”来读取调试输出。
注意:连接 Teensy 的 USB 线时,Windows 可能会变得非常慢。Teensy 会同时模拟 4 个 USB 设备,Windows 可能需要长达 10 秒才能访问串行端口。此外,Arduino 编译器中的 Serial Monitor 存在一个 bug,可能导致 COM 端口从未出现。为了避免此问题,您在上传固件到 Teensy 之前必须关闭 Serial Monitor。
故障排除
如果不起作用,请检查以下步骤
- 将 USB 线插入 Teensy 时,Teensy 板上的 LED 必须闪烁一次。如果不闪烁,则说明您可能没有正确上传固件。解压 Zip 文件,双击“IR_Receiver.ino”文件。如上图所示配置 Arduino 编译器。在编译器工具栏中,单击第二个“Upload”(上传)按钮(带右箭头)。必须打开另一个窗口:Teensy Loader。现在按下 Teensy 板上的小按钮。等待 Teensy Loader 显示“Reboot OK”。
- 每当 Teensy 接收到任何 IR 信号时,Teensy 上的 LED 必须以红外信号的节奏快速闪烁。如果您按下遥控器上的按钮,LED 保持关闭,请检查遥控器是否正常工作,并检查 IR 接收器与 Teensy 之间的连接是否正确。
- 当 Teensy 连接到计算机时,必须出现一个 COM 端口。这可能需要长达 10 秒。第一次连接 Teensy 时,甚至需要更长时间,并且您需要安装CDC 驱动程序(只有一个 INF 文件)。您可以在 ZIP 文件中找到驱动程序。您可以在控制面板的“Ports”(端口)下看到此端口,显示为“Teensy USB serial”。此外,在“Human Interface Devices”(人体接口设备)下,您会找到三个“HID Input Device”。它们是键盘、鼠标和游戏手柄,您可以在“Keyboards”(键盘)和“Mice and other pointing devices”(鼠标和其他指针设备)下找到它们。如果您不确定,请断开 Teensy,这些设备应该会在几秒钟后在控制面板中消失。
- 在编译器的“Tools”(工具)菜单中选择 Teensy COM 端口,然后打开“Serial Monitor”(串行监视器)。然后按一下遥控器上的按钮。您必须看到 Teensy 发送的调试输出。在源代码中,您可以将 PRINT_RAW_SAMPLES 设置为 true 或 false,具体取决于您想要多少调试输出。
可能的扩展
您可以通过此项目完成更多事情。此外,您还可以将继电器连接到 Teensy 以打开或关闭设备,或者用遥控器调暗灯光。如果您连接 12V 的LED 灯带或 LED 灯,您可以使用 Teensy 的 500 Hz PWM 输出,并通过 MOSFET 晶体管(如 BUZ71A)放大信号。
您还可以为计算机编写一个程序,该程序在串行 COM 端口上监听 Teensy 发送的 CRC 代码,并执行更复杂的操作(例如,关闭操作系统、启动程序等)。在 C# 中,可以使用 System.IO.Ports.SerialPort 用几行代码完成。
简易电灯开关
您可以在房间的主灯开关上扩展一个双稳态继电器。这样,您就可以通过遥控器或灯开关来打开和关闭灯。
一个双稳态继电器有两个线圈,只需要一个短脉冲即可切换到另一个位置并永久保持在该位置,直到另一个线圈通电。您可以在 Digikey 等地方找到双稳态继电器。PB1695-ND 在 5V 下需要 80mA。它售价 4.40 美元,可切换 16A。Teensy 的 Vin 引脚直接连接到 USB 线缆的 +5V,该线缆提供足够的电流(500mA)用于继电器,因此您不需要额外的 5V 电源,只要计算机在运行。
但是,如果您想在计算机关闭时也能切换灯,则需要额外的 5V 电源,并且您必须剪断 Teensy 底部的跳线,以将此 5V 电源与 USB 线缆的 5V 断开。
更多使用 Teensy 的项目
这是我用 Teensy 制作并发布在 Codeproject 上的第三个电子项目。您可能也对以下项目感兴趣:
- DIY 电子 RFID 门锁带电池备份
它使用具有 DES / AES 加密的 Desfire RFID 卡用于电子门锁。 - 使用 Teensy 模拟 USB HID 键盘、鼠标、触摸屏
它通过 USB 模拟 3 种类型的触摸屏。