重新利用旧遥控器
组件和用品
| × | 1 | ||||
| × | 3 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
关于这个项目
该项目允许您重复使用旧录像机、电视、DVD 播放器等多余的遥控器。
您可以使用遥控器通过继电器、功率晶体管或任何其他 5 伏信号可以控制的设备来打开灯、加热器等设备。如图所示,它最多只能切换 6 个 LED。这个想法是提供草图和面包板布局,以便发送到 LED 的信号可以并行发送到用户想象的任何东西!
按照设计,它可以从任何遥控器读取 6 个 IR 代码并“记住”它们。我喜欢使用 1, 2, 3, 4, 5, 6 - 但任何六个键都可以使用。请注意,具有 6 个已知代码以外的 IR 代码的任何其他键都用作重置并将所有输出设置为关闭。我通过将代码作为长整数写入 Arduio 板上的 EEPROM 存储器来实现这一点。每个占用 4 个字节,但由于 UNO 和 NANO 各有 1024 个字节的 EEPROM 内存,因此有足够的空间。正如人们所期望的那样,这种记忆可以通过重置和断电保持。除了拨动开关外,整个东西都可以放在一个面包板上。可以将引脚焊接到此开关以将其包含在面包板上。我很懒,在开发过程中用胶带把它放在我的桌子上。
我已经用五种不同的旧剩余物进行了尝试,它们的表现都一样。我挣扎的“问题”是来自某些遥控器的杂散光或较弱的信号。为了解决这个问题,我小心地将接收器“LED”向下弯曲到大约 45 度,然后在上面放了一个自制的小纸板和胶带盒,一端敞开。它似乎可以从 5-8 英尺或更远的地方始终如一地捕捉到代码。在超过五天的测试和调整程序中,我没有错过任何机会。
要对其进行编程,请使用“学习”位置。您可以通过拨动切换开关从“运行”模式进入“学习”模式。此切换会打开红色模式指示灯 LED,表明它已准备好收听。它使 LED 1 闪烁,然后您按下遥控器上的一个键。闪烁的 LED 1 被编程为对该代码作出反应。一旦它识别出代码,它就会迅速使模式指示灯 LED 闪烁一两秒钟(如此之快,看起来像是在振动!)然后移动到下一个 LED。这一直持续到所有六个都被编程。然后模式指示灯 LED 以一秒为间隔缓慢闪烁,指示系统应切换到运行模式。
我在编程时发现最常见的错误是忘记将手指移到遥控器上的下一个数字。因此很容易用相同的代码对两个输出进行编程。每次启动时,它都会查找此类重复项。如果它找到它们,它就会使“有问题”的 LED 闪烁几次,以表明可能需要重新编程。然而,一个人可能想要几个键做同样的事情,所以它不会强制重新编程。
模式状态、错误等由红色状态 LED 的闪烁率指示。由闪烁的 LED 等指示的所有信息都被发送到串行监视器。我将它设置为使用 LED 闪烁序列,因此用户可以在没有计算机的情况下进行设置。发送到串行监视器的消息比记住以各种速度闪烁的 LED 意味着什么更容易理解。由于这通常只会被编程几次,因此将其连接到您的 PC 并在串行监视器上观看文本可能更自然。
草图代码中有很多制衡。它们有很好的文档记录(我希望!),所以我不会在这里提供详细信息。熟悉 C、C++ 和 Arduino IDE 的用户应该能够轻松地遵循代码并根据需要进行修改。
附录: 我已经用 5 个继电器与 LED 1 到 5 并联进行了测试,它按预期工作。它们都切换 120 VAC 台灯,因此电路按预期工作。我的继电器用完了,所以必须假设第 6 个信号也能工作。请注意,这只是一个概念证明。我不得不用 CD4011 四与非门反转前四个输出的信号,因为它们在 0 伏而不是 5 伏时关闭。单个继电器在 + 5 伏信号上工作,因此不需要信号反转。 请小心切换电源电压。它们是高电压,有可能造成严重电击甚至死亡!
请记住,这只是一个示例。发挥您的想象力,将哪些设备连接到 6 个输出。享受!
代码
- IR 远程再利用草图
红外远程再利用草图Arduino
/* 使用 IR 遥控器切换 6 个 LED,以说明如何重新调整 surpulus 遥控器的用途,以便它们可用于控制几乎任何设备。当拨动开关处于“学习”或程序位置时,此草图学习任何 IR 遥控器上 1、2、3、4、5、6 和 0 按钮的制造商代码。这些值保存在 Arduino Nano 的 EEPROM 中。当拨动开关置于“运行”模式时,这些值用于确定按下了哪个键。然后由遥控器打开和关闭 6 个相关的 LED。这是为了演示如何学习和设置代码,而不管红外遥控器的类型。除了 LED 之外,输出还可以扩展为打开或关闭带有继电器、大功率晶体管等的设备。 Paul M Dunphy VE1DX 2020 年 3 月 */ // 包含由 Ken Shirriff 开发的红外远程库#include// 提供读取/写入 1024 字节 EEPROM#include long unsigned int 的能力intIRCode;long unsigned int savedIRCodes[6];long unsigned int dupeCheck[6]; // 定义红外传感器的引脚const int Recv_Pin =2; // 定义引脚常量来切换 LEDsconst int PinOne =12; const int PinTwo =11;const int PinThree =10; const int PinFour =9;const int PinFive =8; const int PinSix =7;// 定义引脚常量以读取和指示// 运行/学习切换开关的状态。const int switchPin =4; const int statusPin =5; const unsigned long int repeatKeyPress =0xFFFFFFFF;boolean learnMode; // 用于根据切换开关跟踪我们所处的 // 模式。boolean first_iteration; //定义整数以记住每个LED的切换状态int togglestate1;int togglestate2;int togglestate3;int togglestate4;int togglestate5;int togglestate6;int current_remote_code;int remote_code_1;int remote_code_2;int remote_code_3;int remote_code_4;int remote_code_5;int remote_code_6; // 定义 IR 接收器和结果对象 IRrecvirrecv(Recv_Pin);decode_results results;void EEPROMWritelong(int address, long value)// 向 EEPROM 写入一个 4 字节(32 位)长整数// 因为它们是 4 字节长,所以它们是存储在 // 地址到地址 + 3 { // 使用 bitshift 将长整数分解为 4 个字节。 // 一 =最高有效 -> 四 =最低有效字节字节四 =(值 &0xFF);字节三 =((value>> 8) &0xFF);字节二 =((值>> 16) &0xFF);字节一 =((值>> 24) &0xFF); EEPROM.write(地址,四); EEPROM.write(address + 1, 三); EEPROM.write(address + 2, 二); EEPROM.write(地址 + 3, 一); }long EEPROMReadlong(long address)// 从 EEPROM 中读取一个 4 字节(32 位)长整数。// 因为它们是 4 字节长,所以它们被存储在 // 地址到地址 + 3 { long Four =EEPROM.read(地址);长三 =EEPROM.read(地址 + 1);长二 =EEPROM.read(地址 + 2); long one =EEPROM.read(address + 3); //将字节组合成一个长整数并返回 return ((four <<0) &0xFF) + ((three <<8) &0xFFFF) + ((two <<16) &0xFFFFFF) + ((one <<0) 24) &重复按键); }int Flip_LED(int led, int toggle_state) { if(toggle_state==0) { digitalWrite(led, HIGH);切换状态=1; } else { digitalWrite(led, LOW);切换状态=0;返回toggle_state; }void Reset() { // 关闭所有 LED 并将切换标志设置为关闭 (0) digitalWrite(PinOne, LOW);数字写入(PinTwo,低);数字写入(PinThree,低);数字写入(PinFour,低);数字写入(PinFive,低);数字写入(PinSix,低);切换状态1 =0;切换状态2 =0;切换状态3 =0;切换状态4 =0;切换状态5 =0;切换状态6 =0; }void guessType() { Serial.print("Remote 似乎是一个"); switch (results.decode_type){ case NEC:Serial.println("NEC");休息;案例索尼:Serial.println(“索尼”);休息; case RC5:Serial.println("RC5");休息; case RC6:Serial.println("RC6");休息; case DISH:Serial.println("DISH");休息;案例夏普:Serial.println(“夏普”);休息; case JVC:Serial.println("JVC ");休息;案例三洋:Serial.println("三洋");休息;案例三菱:Serial.println(“三菱”);休息; case SAMSUNG:Serial.println("SAMSUNG");休息; case LG:Serial.println("LG");休息; case WHYNTER:Serial.println("WHYNTER ");休息; case AIWA_RC_T501:Serial.println("AIWA_RC_T501 ");休息;案例松下:Serial.println("松下");休息; case DENON:Serial.println("DENON");休息;默认: case UNKNOWN:Serial.println("UNKNOWN ");休息; } } int learnCodeRead(int pinCode) { if (irrecv.decode(&results)) { pinCode =results.value;返回密码; } void Confirm() { int i; for(i=0; i<=20; i++) { digitalWrite(statusPin, HIGH);延迟(50);数字写入(状态引脚,低);延迟(50);数字写入(状态引脚,高); // 让“学习”LED 保持高电平 } void learn_Mode() { boolean goodCode;内部 i, j;内部位置; int pin[6] ={12,11,10,9,8,7}; // 按顺序开始监听每个 if (first_iteration) { Serial.println(); Serial.println("进入学习模式"); Serial.println(); } intIRCode =0;位置 =0;好代码 =真; j =0; while ((goodCode=true) and (j<=5)) { for(i=0; i<=25; i++) { digitalWrite(pins[j], HIGH);延迟(200); intIRCode =learnCodeRead(intIRCode);数字写入(引脚[j],低);延迟(200); intIRCode =learnCodeRead(intIRCode); goodCode =((intIRCode !=repeatKeyPress) 和 (intIRCode !=0));如果(好代码){ i =30; // 避免循环的技巧,因为 'break' // 不适用于循环 }irrecv.resume(); // 重新开始听 } goodCode =(intIRCode !=repeatKeyPress and intIRCode !=0); if (goodCode) { if (j==0) { guessType(); Serial.print("写入 EEPROM 位置");Serial.print(location); Serial.print(" IR code =");Serial.println(intIRCode,HEX); EEPROMWritelong(位置,intIRCode);位置 =位置 + 4; j++;确认(); intIRCode =0;简历.resume(); // 再次开始聆听 } } Serial.println(); Serial.println("让 Arduino 回到运行模式。"); while (digitalRead(switchPin) ==HIGH) { digitalWrite(statusPin, HIGH);延迟(1000);数字写入(状态引脚,低);延迟(1000); Serial.println(); Serial.println("返回运行模式。"); // 这里可能不需要那么激烈,但是 // 这是一个“重置”,以确保我们退出学习模式 // 并正确重启。 // 删除以下 4 行 *可能* 可以。延迟(50);串行.flush();延迟(50); asm 易失性(“jmp 0”); } void run_Mode() { if (first_iteration) { Serial.println("进入运行模式"); } if (irrecv.decode(&results)) { if (results.value!=repeatKeyPress) { current_remote_code =results.value; Serial.print("检测到按键按下,IR 代码 ="); Serial.println(current_remote_code,HEX); if (current_remote_code ==remote_code_1) { togglestate1 =Flip_LED(PinOne,togglestate1); } else if (current_remote_code ==remote_code_2) { togglestate2 =Flip_LED(PinTwo,togglestate2); } else if (current_remote_code ==remote_code_3) { togglestate3 =Flip_LED(PinThree,togglestate3); } else if (current_remote_code ==remote_code_4) { togglestate4 =Flip_LED(PinFour,togglestate4); } else if (current_remote_code ==remote_code_5) { togglestate5 =Flip_LED(PinFive,togglestate5); } else if (current_remote_code ==remote_code_6) { togglestate6 =Flip_LED(PinSix,togglestate6); } else { 重置(); } } 延迟(500); // 用于绕过快速的数据串 // 如果按下按钮。 // 通过在循环中引入延迟来减慢响应时间。简历.resume(); // 重新开始监听 } } void setup() { first_iteration =true;输入 i,j,k;内部位置; int dupeFlash[6] ={12,11,10,9,8,7}; // 将数字固定到闪存 // 如果发现重复项 Serial.begin(9600); ircv.enableIRIn(); // 启用 IR 接收器 /* 以下代码段永远不需要重置 EEPROM。 * 然而,一些新的、现成的 NANO 出现了,它们的 EEPROM 设置为 * FFFFFFFF。这恰好是当 * 一个键被按下时许多红外遥控器发送的代码。此草图在多个位置检查该代码*,如果为“密钥”分配了十六进制 FFFFFFFF,它将无法正常工作。为了*防止这个问题,我们检查FFFFFFFFs,如果找到,我们将*6个关键位置设置为Sony RM-YD104代码。如果发生这种情况,除非您 * 正在使用该特定遥控器,否则您将需要以“学习” * 模式运行草图以对其进行初始化。 */// ==============开始新的 Arduino ==================boolean defaultToSony =false; long unsigned int IRCode =0;位置 =0; for(i=0; i<=5; i++) { IRCode =EEPROMReadlong(location); if (IRCode==repeatKeyPress) { defaultToSony =true; } 位置 =位置 + 4; } if (defaultToSony) { Serial.println("在 EEPROM 内存中找到 HEX FFFFFFFF。设置代码"); Serial.println("对于索尼 RM-YD104 遥控器。现在运行'学习'模式"); Serial.println("建议使用,除非那是你的遥控器。"); EEPROMWritelong(0, 0x10);延迟(50); EEPROMWritelong(4, 0x810);延迟(50); EEPROMWritelong(8, 0x410);延迟(50); EEPROMWritelong(12, 0xC10);延迟(50); EEPROMWritelong(16, 0x210);延迟(50); EEPROMWritelong(20, 0xA10);延迟(50); } // ==============结束新的 Arduino ==================// 将 LED 引脚设置为输出 pinMode(PinOne, OUTPUT); pinMode(PinTwo, 输出); pinMode(PinThree,输出); pinMode(PinFour, OUTPUT); pinMode(PinFive,输出); pinMode(PinSix,输出);重启(); // 从它们全部关闭 pinMode(statusPin, OUTPUT); 开始pinMode(switchPin, INPUT); //从上次使用的远程获取代码 Serial.println(); Serial.println("读取存储的红外遥控代码......");位置 =0; for(j=0; j<=5; j++) {savedIRCodes[j] =EEPROMReadlong(location); Serial.print("从 EEPROM 位置读取");Serial.print(location); Serial.print(" IR code =");Serial.println(savedIRCodes[j],HEX);位置 =位置 + 4; dupeCheck[j]=savedIRCodes[j]; // 保存副本以进行重复检查 } // 查找分配给 // 输出的连续重复代码。我们不寻找整体重复,因为 // 它们不太可能发生。经验表明, // 在编程期间,最可能的错误是在背对背 LED 上按 // 两次相同的键。如果发现重复 // ,通过闪烁可疑的 LED 来表明这一点。 // 只有 6 个 LED,因此只需进行 21 次比较 // 即可找到任何重复项 (6 + 5 + 4 + 3 + 2 + 1 =21)。 // 可以通过先对数组进行排序等来增强此部分以查找任何重复项 for (i =0; i <5 - 1; i++) { for (j =i + 1; j <6; j++ ) { if (dupeCheck[i] ==dupeCheck[j]) { Serial.println("发现重复代码。建议重新运行学习模式"); for(k=0; k<=5; k++) { digitalWrite(dupeFlash[i],HIGH);数字写入(dupeFlash [j],高);延迟(1000);数字写入(dupeFlash [i],低);数字写入(dupeFlash [j],低);延迟(1000); } } } } remote_code_1 =savedIRCodes[0]; remote_code_2 =savedIRCodes[1]; remote_code_3 =savedIRCodes[2]; remote_code_4 =savedIRCodes[3]; remote_code_5 =保存的 IRCodes[4]; remote_code_6 =savedIRCodes[5];延迟(1000); Serial.println("读取存储的代码。"); Serial.println(); } void loop() { // 检查开关是打开还是关闭。如果它打开(在学习模式下)// switchPin 是高电平:learnMode =(digitalRead(switchPin) ==HIGH); if (learnMode) { first_iteration =true;重启();数字写入(状态引脚,高); // 打开学习模式 LED:learn_Mode();重启(); first_iteration =false; } else { digitalWrite(statusPin, LOW); // 关闭学习模式 LED:run_Mode(); first_iteration =false; } }
示意图
制造工艺