亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

WiFi IR Blaster

组件和用品

乐鑫 ESP8266 ESP-01
您可以使用标准的 ESP8266 或 NodeMCU 开发套件来做到这一点
× 1
Arduino Nano R3
× 1
通用晶体管 NPN
× 1
Adafruit 红外 LED
× 1

必要的工具和机器

烙铁(通用)

应用和在线服务

Arduino IDE
NodeMCU 固件

关于这个项目

向前两步...

似乎主要的手机制造商正在远离内置 IR 发射器,所以我正在寻找一种方法来使我的“哑”设备面向未来,这些设备目前未与我的物联网基础设施集成。我有一个网状网络智能家居,但我需要找到一个物理遥控器来打开我的电视?一定有更好的方法。

我最近构建了一个 IR 发射器,用于控制我家中的独立空调,之前的另一个项目是一个连接 HVAC 通风口和一个 android 连接的 web 应用程序。从本质上讲,我需要做的就是将这两个东西组合成一个带有 webapp 前端的网络连接的 IR 发射器,这样我就可以按下手机上的按钮并将 IR 信号发送到我的媒体中心。这些可以部署在每个房间,并通过一个界面在任何地方进行控制,因此这方面的应用非常广泛。

快速原型制作

我拿起了一些未使用的硬件,并连接了连接到 WiFi、接受 HTTP 连接和发送红外信号所需的一切。

这工作得很好,因为我可以请求分配给 ESP8266 的 IP 上的特定 URL,并让 Arduino 向红外 LED 输出“电源”信号。我只需要找出托管 web 应用程序的位置,将 URL 发送到 IR Blaster,然后将这些请求解析为特定的 IR 代码。在 ESP8266 上使用 AT 命令非常繁琐,并且在发送请求和 LED 闪烁之间有一些原因导致 1-2 秒的延迟。

NodeMCU

我继续使用 NodeMCU ESP8266 开发板,因为它具有板载电源调节、USB 到串行接口以及在这个小封装中的大量 I/O 引脚(它也是面包板友好的)。事实证明,已经有一个 ESP8266 WebServer 库可以接受 GET 请求,我能够适应它来发送 IR 代码,而常规的 IRremote 库开箱即用。

NodeMCU 上的 ESP8266 不够强大,无法托管 web 应用程序本身,因此我将在未充分利用的 C.H.I.P. 上运行它。 9 美元的计算机已经在我的家庭网络上运行。另一个限制是 ESP8266 是 3.3v 板,因此直接从 I/O 引脚驱动的 IR LED 非常暗,并且必须紧邻要向其发送信号的设备。我改为使用 I/O 引脚驱动一个 npn 晶体管来打开/关闭 5v 电源电压。

休息...ish

在做了一些研究之后,我找到了一个很好的教程,用于为 Arduino 实现 REST API 来控制 adafruit 上的 LED。我使用他们的 JavaScript 和 PHP 文件提交 cURL 请求并将其加载到已经运行 apache 但可以轻松托管在云中的 CHIP 上。在为遥控器创建一个基本的 HTML 页面后,我添加了 manifest.json 和图标文件,以便它可以在 Android 手机上作为本机 web 应用程序运行。

在 Arduino 方面,我精简了网络服务器,只接受 GET 请求,解析 URL,发送 200 OK,然后断开连接。根据 URL,Arduino 将发送映射到按下按钮的 IR 代码。

万能的怪物

一切正常,零延迟。我发现我使用的 IR LED 的角度非常窄,所以我必须小心它们的指向是否正确。一些工业魔术贴让我可以将它安装在架子下,看不见,并确保它始终指向另一端的红外接收器。我在 LED 引线上添加了一些粗规格线,以便对它们进行微调。

IR LED 的电阻器导致它们几乎无法使用,因此晶体管使用未调节的 5v 电压为它们供电。这使我可以将 IR 从墙壁上反射回来并将冲击波安装在整个房间,但肯定会对寿命产生影响。我希望因为它们很少使用并且 IR 信号是超短脉冲(占空比比大多数昏暗的 PWM 信号低),所以我在一段时间内不需要更换 LED。我确保为版本 2 订购了一些广角和更高输出的 IR LED,所以当它们最终死掉时,我将用一个内联电阻器替换它们。

3 个月更新和未来功能

我每天都在使用它,它运行完美。我什至在我们的家庭房间中添加了第二个设备来控制我们的窗户空调和另一台电视。

未来计划:

  • 将 Web UI 迁移到云服务
  • 与 Amazon Echo 集成以获取语音命令(完成)
  • 下一次硬件迭代还将配备 DHT22 温度传感器,我正在研究为吊扇传输射频的方法
  • 为学习功能添加 IR 接收器,以便您可以“教授”现有遥控器的 IR 发射器命令
  • 与我的家庭自动化/安全集成以在不使用时关闭设备

这款小型联网红外发射器正在慢慢填补我的智能家居和传统电器之间的空白。

代码

  • 用于 ESP8266 Arduino Sketch 的 WiFi IR Blaster
  • script.js
  • index.html
  • curl.php
  • manifest.json
用于 ESP8266 Arduino Sketch 的 WiFi IR BlasterC/C++
您将需要 ESP8266 wifi 库和 IRremote.h。如果库中支持您的遥控器,您还应该选择不使用原始 IR 代码。我改编自我使用非标准 IR 代码构建的空调控制器的草图。
/* * WiFi IR Blaster by Buddy Crotty * 使用 ESP8266 模块或开发板接收 HTTP GET 请求 * 然后发送 IR 代码根据这些请求连接到附加的 IR LED。 * 这与作为前端的另一个 Web 服务器一起使用时效果最好 * 根据按下的按钮发送 cURL 请求。 * cURL 格式:http://ESP8266/IRcode */#include #include #include const char* ssid ="AP_SSID";const char* password ="AP_Pass ";MDNSResponder mdns;int khz =38; // NEC 和 SamsungIRsend 的 38kHz 载波频率 irsend(4); //IR LED 连接到 GPIO4(NodeMCU 上的引脚 D2) // 为“TV Power”插入 RAW IR 信号 unsigned int irTVpwr[] ={4650,4250, 700,1550, 650,1550, 700,1550, 650,450 ,650500,600500,600500,600550,550,1700,550,1650,600,1650,550550,600500,600550,550550,600500,600550,550,1650,600550,550550,600500,600550,550550,600500,600 ,1650, 600,500, 600,1650, 550,1700, 550,1650, 600,1650, 550,1650, 600,1650, 600}; // SAMSUNG E0E040BF // 为“TV Source”插入 RAW IR 信号 unsigned int irTVsrc[] ={4600,4300, 700,1550, 650,1550, 650,1600, 650,450, 650,450, 605,605,050505 1650,550,1650,600,1650,550550,600500,600550,550550,550550,600,1650,550550,550550,600500,600500,600550,550550,600500,600550,550,1650,550,1700,550, 1650, 600,1600, 600,1650, 600,1600, 600,1650, 550}; // SAMSUNG E0E0807F // 为“TV Mute”插入 RAW IR 信号 unsigned int irTVmute[] ={4650,4250, 700,1550, 650,1550, 700,1550, 650,450, 650,500,06,005,005,005 1650,600,1600,600,1650,550550,600500,600550,550550,600500,600,1650,550,1650,600,1650,550,1650,600550,550550,550550,600500,600550,550550,550550, 600,500, 600,1650, 550,1650, 600,1650, 550,1650, 600}; // SAMSUNG E0E0F00F // 为“TV Volume Down”插入 RAW IR 信号 unsigned int irTVvdn[] ={4650,4250, 700,1550, 650,1550, 700,1550, 650,450, 650,450,405,605,6505,605,0505 ,1650,550,1650,550,1650,600550,550550,550550,600500,600500,600,1650,600,1600,600500,600,1650,550550,600500,600500,600550,550550,600500,600,1650 , 550,550, 550,1650, 600,1650, 550,1650, 600,1650, 550}; // SAMSUNG E0E0D02F // 为“TV Volume Up”插入 RAW IR 信号 unsigned int irTVvup[] ={4600,4300, 650,1600, 650,1550, 650,1600, 600,500, 600,505,05,05,0505,0505 ,1700,550,1650,600,1650,550550,600500,600550,550550,600500,600,1650,600,1650,550,1650,600550,550550,600500,600550,550550,600500,600550,550550,600 ,1600, 600,1650, 600,1650, 550,1650, 600,1650, 600}; // SAMSUNG E0E0E01F // 为“TV Channel Up”插入 RAW IR 信号 unsigned int irTVchup[] ={4650,4250, 700,1550, 650,1600, 650,1550, 650,500, 600,500,506,005,005,005 ,1650,550,1650,600,1650,600500,600500,600550,550550,600550,550550,550,1650,600550,600500,600,1650,550550,600500,600550,550,1650,600,550,550,1650 , 600,1650, 600,500, 600,1650, 600,1600, 600,1650, 600}; // SAMSUNG E0E048B7 // 为“TV Channel Down”插入 RAW IR 信号 unsigned int irTVchdn[] ={4600,4350, 650,1550, 650,1600, 650,1600, 600,500, 600,500,5,05,0505,0505 ,1650,600,1650,550,1700,550550,550550,600500,600550,550550,600500,600550,550550,550550,600,1650,600500,600500,600550,550,1650,600,1650,600,1650 , 550,1650, 600,550, 550,1650, 600,1650, 600,1650, 550}; // SAMSUNG E0E008F7 // 为“接收器功率”插入 RAW IR 信号 unsigned int irRECpwr[] ={9050,4350, 650,500, 600,1600, 600,500, 650,500, 600,1600,5,6,006,6006 550550,600500,600,1600,650,1600,600500,600,1650,600,1600,600500,600,1650,600,1600,600,550,600,1600,600500,600550,600,1600,600,1600, 650,500, 600,500, 600,1600, 650,500, 600,1600, 600,1650, 600,500, 600,500, 600}; // NEC 4B36D32C // 为“接收器开机”插入 RAW IR 信号 unsigned int irRECpwrON[] ={9000,4400, 600,550, 600,1600, 600,500, 600,550, 600,1600,600,6005,6005 ,600,1600,600500,650,1600,600,1600,600500,650,1600,600,1600,600500,600550,600500,600,1600,600550,600500,600500,650500,600500,600,1600,650 ,1600, 600,500, 600,1600, 650,1600, 600,1600, 600,1600, 600,1600, 650}; // NEC 4BB620DF // 为“接收器关机”插入 RAW IR 信号 unsigned int irRECpwrOFF[] ={9000,4400, 600,550, 550,1650, 600,550, 550,550, 600,1650,5,50506050 ,600550,550550,550,1650,600,1650,600,550,550,1650,600,1650,550550,600,1650,550,1650,600,1650,600500,600550,550550,600,1650,550550,600500 , 600,550, 550,550, 550,1700, 550,1650, 600,1650, 550,550, 600,1650, 550}; // NEC 4B36E21D // 为“Receiver Mute”插入 RAW IR 信号 unsigned int irRECmute[] ={9000,4400, 650,450, 650,1600, 600,500, 600,500, 650,1600,0,6006,6005 600,1600,650500,600,1600,650,1600,600500,600,1600,650,1600,600500,600,1650,600500,600,1600,650500,600500,600500,600500,650500,600500,600, 1600, 650,500, 600,1600, 600,1600, 650,1600, 600,1650, 600,1600, 600}; // NEC 4BB6A05F // 为“Receiver Volume Down”插入 RAW IR 信号 unsigned int irRECvdn[] ={9150,4250, 750,350, 700,1550, 700,400, 700,450, 650,1550,4,05,600601 ,600,1650,600500,600,1650,600,1600,600,550,600,1600,600,1650,600500,600,1650,600,1600,650500,600500,600500,650500,600500,600500,600550,600500 , 600,1650, 600,1600, 600,1650, 600,1650, 600,1600, 600,1650, 600}; // NEC 4BB6C03F // 为“Receiver Volume Up”插入 RAW IR 信号 unsigned int irRECvup[] ={9050,4400, 650,500, 600,1600, 600,550, 600,500, 600,1650,5,6006010 ,600,1600,600,550,600,1600,600,1600,650500,600,1600,650,1600,600500,600550,600,1600,600550,600500,600550,600500,600550,600500,600,1600,650500 , 600,1600, 600,1650, 600,1600, 600,1650, 600,1600, 600,1600, 600}; // NEC 4BB640BF // 为“Receiver Source CBL/SAT”插入 RAW IR 信号 unsigned int irRECsrc[] ={8950,4450, 600,500, 600,1650, 600,500, 600,500, 600,1650,50,6006 ,1650,600,1600,600,550,600,1600,600,1650,600500,600,1600,600,1650,600500,600500,600,1650,600,1600,600,1650,600500,600500,600500,650500 , 600,1600, 600,500, 600,550, 600,500, 600,1600, 600,1650, 600,1600, 600,1650, 600}; // NEC 4BB6708F // 创建服务器实例 // 指定监听的端口作为参数 WiFiServer server(80);void setup() { Serial.begin(115200);延迟(10); irsend.begin(); // 连接到 WiFi 网络 Serial.println(); Serial.println(); Serial.print("连接到"); Serial.println(ssid); WiFi.begin(ssid, 密码);而(WiFi.status()!=WL_CONNECTED){延迟(500); Serial.print("."); Serial.println(""); Serial.println("WiFi 已连接"); // 启动服务器 server.begin(); Serial.println("HTTP 服务器启动"); // 打印 IP 地址 Serial.print("IP 地址:"); Serial.println(WiFi.localIP()); if (mdns.begin("IRBlasterLR", WiFi.localIP())) { Serial.println("MDNS Responder Started"); Serial.println(); Serial.println();}void loop() { // 检查客户端是否连接了 WiFiClient client =server.available();如果(!客户端){ 返回; } // 等到客户端发送一些数据 Serial.println("new client");而(!client.available()){ 延迟(1); } // 读取请求的第一行 String req =client.readStringUntil('\r'); Serial.println(req);客户端冲洗(); // 匹配请求 if (req.indexOf("/irTVpwr") !=-1){ irsend.sendRaw(irTVpwr, sizeof(irTVpwr) / sizeof(irTVpwr[0]), khz); Serial.println("IRreq irTVpwr 已发送"); } else if (req.indexOf("/irTVsrc") !=-1){ irsend.sendRaw(irTVsrc, sizeof(irTVsrc) / sizeof(irTVsrc[0]), khz); Serial.println("IRreq irTVsrc 已发送"); } else if (req.indexOf("/irTVmute") !=-1){ irsend.sendRaw(irTVmute, sizeof(irTVmute) / sizeof(irTVmute[0]), khz); Serial.println("IRreq irTVmute 已发送"); } else if (req.indexOf("/irTVvdn") !=-1){ irsend.sendRaw(irTVvdn, sizeof(irTVvdn) / sizeof(irTVvdn[0]), khz); Serial.println("IRreq irTVvdn 已发送"); } else if (req.indexOf("/irTVvup") !=-1){ irsend.sendRaw(irTVvup, sizeof(irTVvup) / sizeof(irTVvup[0]), khz); Serial.println("IRreq irTVvup 已发送"); } else if (req.indexOf("/irTVchup") !=-1){ irsend.sendRaw(irTVchup, sizeof(irTVchup) / sizeof(irTVchup[0]), khz); Serial.println("IRreq irTVchup 已发送"); } else if (req.indexOf("/irTVchdn") !=-1){ irsend.sendRaw(irTVchdn, sizeof(irTVchdn) / sizeof(irTVchdn[0]), khz); Serial.println("IRreq irTVchdn 已发送"); } else if (req.indexOf("/irALLpwr") !=-1){ irsend.sendRaw(irRECpwrON, sizeof(irRECpwrON) / sizeof(irRECpwrON[0]), khz); irsend.sendRaw(irTVpwr, sizeof(irTVpwr) / sizeof(irTVpwr[0]), khz);延迟(2000); irsend.sendRaw(irRECsrc, sizeof(irRECsrc) / sizeof(irRECsrc[0]), khz); Serial.println("IRreq irALLpwr 已发送"); } else if (req.indexOf("/irRECpwr") !=-1){ irsend.sendRaw(irRECpwr, sizeof(irRECpwr) / sizeof(irRECpwr[0]), khz); Serial.println("IRreq irRECpwr 已发送"); } else if (req.indexOf("/irRECpwrON") !=-1){ irsend.sendRaw(irRECpwrON, sizeof(irRECpwrON) / sizeof(irRECpwrON[0]), khz); Serial.println("IRreq irRECpwrON 已发送"); } else if (req.indexOf("/irRECpwrOFF") !=-1){ irsend.sendRaw(irRECpwrOFF, sizeof(irRECpwrOFF) / sizeof(irRECpwrOFF[0]), khz); Serial.println("IRreq irRECpwrOFF 已发送"); } else if (req.indexOf("/irRECmute") !=-1){ irsend.sendRaw(irRECmute, sizeof(irRECmute) / sizeof(irRECmute[0]), khz); Serial.println("IRreq irRECmute 已发送"); } else if (req.indexOf("/irRECvdn") !=-1){ irsend.sendRaw(irRECvdn, sizeof(irRECvdn) / sizeof(irRECvdn[0]), khz); Serial.println("IRreq irRECvdn 已发送"); } else if (req.indexOf("/irRECvup") !=-1){ irsend.sendRaw(irRECvup, sizeof(irRECvup) / sizeof(irRECvup[0]), khz); Serial.println("IRreq irRECvup 已发送"); } else { Serial.println("请求无效");客户端停止();返回;客户端刷新(); // 将响应发送给客户端 //client.print(s); client.print("HTTP/1.1 200 OK\r\n");延迟(1); Serial.println("客户端断开连接"); Serial.println(); // 当函数返回并且'client'对象被销毁时,客户端实际上会断开连接}
script.jsJavaScript
webapp的javascript(需要jquery)
//发送IR命令的函数function buttonClick(clicked_id){ if (clicked_id =="irTVpwr"){ $.get( "curl.php", { room:"192.168.1.62" , 按钮:"irTVpwr"} ); } if (clicked_id =="irTVsrc"){ $.get( "curl.php", { room:"192.168.1.62", button:"irTVsrc"} ); } if (clicked_id =="irTVmute"){ $.get( "curl.php", { room:"192.168.1.62", button:"irTVmute"} ); } if (clicked_id =="irTVvdn"){ $.get( "curl.php", { room:"192.168.1.62", button:"irTVvdn"} ); } if (clicked_id =="irTVvup"){ $.get( "curl.php", { room:"192.168.1.62", button:"irTVvup"} ); } if (clicked_id =="irTVchup"){ $.get( "curl.php", { room:"192.168.1.62", button:"irTVchup"} ); } if (clicked_id =="irTVchdn"){ $.get( "curl.php", { room:"192.168.1.62", button:"irTVchdn"} ); } if (clicked_id =="irRECpwr"){ $.get( "curl.php", { room:"192.168.1.62", button:"irRECpwr"} ); } if (clicked_id =="irALLpwr"){ $.get( "curl.php", { room:"192.168.1.62", button:"irALLpwr"} ); } if (clicked_id =="irRECpwrON"){ $.get( "curl.php", { room:"192.168.1.62", button:"irRECpwrON"} ); } if (clicked_id =="irRECpwrOFF"){ $.get( "curl.php", { room:"192.168.1.62", button:"irRECpwrOFF"} ); } if (clicked_id =="irRECmute"){ $.get( "curl.php", { room:"192.168.1.62", button:"irRECmute"} ); } if (clicked_id =="irRECvdn"){ $.get( "curl.php", { room:"192.168.1.62", button:"irRECvdn"} ); } if (clicked_id =="irRECvup"){ $.get( "curl.php", { room:"192.168.1.62", button:"irRECvup"} ); } }
index.htmlHTML
显示按钮的基本 html。
 



TV





     


接收器





curl.phpPHP
向 ESP8266 发送 GET 请求的 php 脚本
manifest.jsonJSON
这将允许网页在 android.
{ "name":"WiFi Remote", "icons":[ { "src":"remote_icon_36.png", "sizes":"36x36" , "type":"image/png", "density":0.75 }, { "src":"remote_icon_48.png", "sizes":"48x48", "type":"image/png", "density" :1.0 }, { "src":"remote_icon_128.png", "sizes":"128x128", "type":"image/png", "密度":1.0 }, { "src":"remote_icon_192.png" , "sizes":"192x192", "type":"image/png", "density":1.0 }], "scope":"/remote/", "start_url":"/remote/index.html", "display":"fullscreen", "orientation":"portrait"}

示意图

没什么真正的,只是电源和连接到 NPN 晶体管的单个引脚,以从 5v 电源电压驱动两个串联的 IR LED(没有电阻器)。 如果您想运行额外的 LED 或需要更少的 3.3v 电源电压降,您可以使用 NPN晶体管来切换多个 PNP 晶体管(每个 LED 一个)。这种配置允许您使用尽可能多的 LED,因为您的电源电压可以为其提供电流。

制造工艺

  1. WiFi RTLS 的缺点
  2. 2015 年无线新技术
  3. 如何在 3 美元的 WiFi 设备上安装安全的嵌入式 Web 服务器
  4. NodeMCU 和 Raspberry Pi 3 B+
  5. 由 ANDROID 智能手机控制的 RASPBERRY PI WIFI 机器人
  6. 使用 Raspberry Pi 的 Wifi 控制机器人
  7. 什么是 WiFi 通话?它是如何工作的?
  8. IOT - 使用 ESP8266、Arduino 和超声波传感器的智能罐
  9. WebServerBlink 使用 Arduino Uno WiFi
  10. 带有 Arduino 或 ESP8266 的电容式指纹传感器
  11. 使用 Arduino 和 ESP8266 的 WiFi 登录页面的智能门锁
  12. 什么是喷珠?喷砂指南