ИК-порт Wi-Fi
Компоненты и расходные материалы
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
| × | 1 |
Необходимые инструменты и машины
![]() |
|
Приложения и онлайн-сервисы
![]() |
| |||
![]() |
|
Об этом проекте
Два шага вперед ...
Похоже, что основные производители телефонов отказываются от встроенных ИК-передатчиков, поэтому я ищу способ защитить мои «глупые» устройства, которые в настоящее время не интегрируются с моей инфраструктурой IoT, в будущем. У меня есть умный дом с ячеистой сетью, но мне нужно найти физический пульт, чтобы включить телевизор? Там должен быть лучший способ.
Недавно я построил ИК-передатчик, который управляет автономными кондиционерами в моем доме, и еще одним предыдущим проектом был подключенный вентилятор HVAC с подключенным к Android веб-приложением. По сути, все, что мне нужно сделать, это объединить эти две вещи в подключенный к Интернету ИК-порт с интерфейсом веб-приложения, чтобы я мог нажимать кнопки на своем телефоне и получать ИК-сигналы, отправляемые в мои медиацентры. Их можно развернуть в любой комнате и управлять ими с помощью единого интерфейса, поэтому приложения для этого чрезвычайно широки.
Быстрое прототипирование
Я схватил неиспользуемое оборудование и подключил все, что мне нужно, чтобы подключиться к моему Wi-Fi, принимать HTTP-соединения и отправлять ИК-сигналы.

Это сработало отлично, так как я мог запросить конкретный URL-адрес на IP-адресе, назначенном ESP8266, и заставить Arduino выводить сигнал «Power» на ИК-светодиод. Мне просто нужно было выяснить, где разместить веб-приложение, отправить URL-адреса на ИК-бластер, а затем проанализировать эти запросы на определенные ИК-коды. Это было очень утомительно делать с помощью AT-команд с ESP8266, и что-то вызывало задержку в 1-2 секунды между отправкой запроса и миганием светодиода.

NodeMCU
Я выбрал плату разработчика NodeMCU ESP8266, потому что она имеет встроенную регулировку мощности, USB-последовательный интерфейс и множество контактов ввода-вывода в этом небольшом корпусе (он также удобен для макетов). Оказывается, уже существует библиотека ESP8266 WebServer, которая принимает запросы GET, которые я смог адаптировать для отправки ИК-кодов, а обычная библиотека IRremote работает из коробки.

ESP8266 на NodeMCU недостаточно мощный для размещения самого веб-приложения, поэтому я буду запускать его на недостаточно используемом C.H.I.P. Компьютер за 9 долларов, который уже подключен к моей домашней сети. Еще одним ограничением является то, что ESP8266 - это плата на 3,3 В, поэтому ИК-светодиоды, управляемые непосредственно от вывода ввода / вывода, были очень тусклыми и должны были находиться рядом с устройством, на которое он отправлял сигнал. Вместо этого я использовал вывод ввода-вывода для управления npn-транзистором для включения / выключения напряжения питания 5 В.
ОТДЫХ ... ну
Проведя небольшое исследование, я нашел отличное руководство по реализации REST API для Arduino для управления светодиодами на adafruit. Я использовал их файлы JavaScript и PHP для отправки запросов cURL и загрузил их на ЧИП, который уже запускает apache, но с таким же успехом может быть размещен в облаке. После создания базовой HTML-страницы для пульта дистанционного управления я добавил файлы manifest.json и icon, чтобы его можно было запускать как собственное веб-приложение на телефоне Android.



На стороне Arduino я обрезал веб-сервер, чтобы просто принять запрос GET, проанализировать URL-адрес, отправить 200 OK и затем отключиться. На основе URL-адреса Arduino отправит ИК-код, сопоставленный нажатой кнопке.
Универсальный Remonster



Все работает безотказно с нулевой задержкой. Я обнаружил, что ИК-светодиоды, которые я использую, имеют очень узкий угол, поэтому я должен следить за их правильным направлением. Некоторые промышленные липучки позволяют мне устанавливать их под полкой, вне поля зрения, и следить за тем, чтобы они оставались направленными на ИК-приемники на другом конце. Я добавил толстый провод к выводам светодиодов, чтобы их можно было точно настроить.
Из-за резисторов для ИК-светодиодов они стали практически непригодными для использования, поэтому транзистор питает их нерегулируемым напряжением 5 В. Это позволяет мне отражать ИК-излучение от стен и устанавливать бластер по всей комнате, но определенно повлияет на долговечность. Я надеюсь, что, поскольку они используются очень редко, а ИК-сигналы представляют собой сверхкороткие импульсы (более низкий рабочий цикл, чем у большинства тусклых сигналов ШИМ), мне не нужно будет заменять светодиоды в течение некоторого времени. Я заказал несколько широкоугольных ИК-светодиодов с более высокой выходной мощностью для версии 2, поэтому, когда они, наконец, умрут, я заменю их на встроенный резистор.
Обновление за 3 месяца и будущие функции
Я использую это каждый день, и он работал безупречно. Я даже добавил второе устройство в нашу семейную комнату, чтобы управлять нашим оконным кондиционером и другим телевизором.
Планы на будущее:
- Перенести веб-интерфейс в облачную службу
- Интеграция с Amazon Echo для голосовых команд (Готово)
- В следующей итерации оборудования также будет датчик температуры DHT22, и я изучаю способы передачи радиочастотного излучения для моих потолочных вентиляторов.
- Добавьте ИК-приемник для функции обучения, чтобы вы могли "обучать" командам ИК-бластера с существующих пультов дистанционного управления.
- Интеграция с моей домашней автоматизацией / безопасностью, чтобы отключать бытовые приборы, когда они не используются.
Этот небольшой подключенный ИК-передатчик постепенно заполняет пробел между моим умным домом и устаревшей техникой.
Код
- WiFi IR Blaster для ESP8266 Arduino Sketch
- script.js
- index.html
- curl.php
- manifest.json
WiFi IR Blaster для ESP8266 Arduino Sketch C / C ++
Вам понадобится библиотека Wi-Fi ESP8266 и IRremote.h. Вам также следует отказаться от использования необработанных ИК-кодов, если ваш пульт поддерживается библиотекой. Я адаптировал этот набросок на основе созданного мной контроллера кондиционера, который использовал нестандартные ИК-коды./ * * WiFi IR Blaster от Бадди Кротти * Используйте модуль ESP8266 или плату разработчика для получения HTTP-запроса GET * и затем отправки ИК-кодов к подключенному ИК-светодиоду на основе этих запросов. * Это лучше всего работает с другим веб-сервером, выступающим в качестве внешнего интерфейса, * который отправляет запросы cURL в зависимости от того, какие кнопки нажаты. * формат cURL:http:// ESP8266 / IRcode * / # include#include #include const char * ssid ="AP_SSID"; const char * password ="AP_Pass "; MDNSResponder mdns; int khz =38; // Несущая частота 38 кГц для NEC и SamsungIRsend irsend (4); // ИК-светодиод подключен к GPIO4 (вывод D2 на NodeMCU) // Вставить ИК-сигнал RAW для "TV Power" unsigned int irTVpwr [] ={4650,4250, 700,1550, 650,1550, 700,1550, 650,450 , 650,500, 600,500, 600,500, 600,550, 550,1700, 550,1650, 600,1650, 550,550, 600,500, 600,550, 550,550, 600,500, 600,550, 550,1650, 600,550, 550,550, 600,500, 600,550, 550,550, 600,500, 600 , 1650, 600, 500, 600, 1650, 550, 1700, 550, 1650, 600, 1650, 550, 1650, 600, 1650, 600}; // SAMSUNG E0E040BF // Вставить ИК-сигнал RAW для "TV Source" unsigned int irTVsrc [] ={4600,4300, 700,1550, 650,1550, 650,1600, 650,450, 650,450, 600,550, 550,550, 600,500, 600, 1650, 550,1650, 600,1650, 550,550, 600,500, 600,550, 550,550, 550,550, 600,1650, 550,550, 550,550, 600,500, 600,500, 600,550, 550,550, 600,500, 600,550, 550,1650, 550,1700, 550, 1650, 600, 1600, 600, 1650, 600, 1600, 600, 1650, 550}; // SAMSUNG E0E0807F // Вставить ИК-сигнал RAW для "TV Mute" unsigned int irTVmute [] ={4650,4250, 700,1550, 650,1550, 700,1550, 650,450, 650,500, 600,500, 600,500, 600,500, 600, 1650, 600,1600, 600,1650, 550,550, 600,500, 600,550, 550,550, 600,500, 600,1650, 550,1650, 600,1650, 550,1650, 600,550, 550,550, 550,550, 600,500, 600,550, 550,550, 550,550, 600 500, 600, 1650, 550, 1650, 600, 1650, 550, 1650, 600}; // SAMSUNG E0E0F00F // Вставьте ИК-сигнал RAW для "TV Volume Down" без знака int irTVvdn [] ={4650,4250, 700,1550, 650,1550, 700,1550, 650,450, 650,450, 650,450, 600,550, 550,550, 600 , 1650, 550,1650, 550,1650, 600,550, 550,550, 550,550, 600,500, 600,500, 600,1650, 600,1600, 600,500, 600,1650, 550,550, 600,500, 600,500, 600,550, 550,550, 600,500, 600,1650 , 550, 550, 550, 1650, 600, 1650, 550, 1650, 600, 1650, 550}; // SAMSUNG E0E0D02F // Вставьте ИК-сигнал RAW для увеличения громкости ТВ без знака int irTVvup [] ={4600,4300, 650,1600, 650,1550, 650,1600, 600,500, 600,550, 600,500, 600,550, 550,550, 550 , 1700, 550,1650, 600,1650, 550,550, 600,500, 600,550, 550,550, 600,500, 600,1650, 600,1650, 550,1650, 600,550, 550,550, 600,500, 600,550, 550,550, 600,500, 600,550, 550,550, 600 , 1600, 600, 1650, 600, 1650, 550, 1650, 600, 1650, 600}; // SAMSUNG E0E0E01F // Вставить ИК-сигнал RAW для "TV Channel Up" без знака int irTVchup [] ={4650,4250, 700,1550, 650,1600, 650,1550, 650,500, 600,500, 600,500, 650,500, 600,500, 600 , 1650, 550, 1650, 600, 1650, 600, 500, 600, 500, 600, 550, 550, 550, 600, 550, 550, 550, 550, 1650, 600, 550, 600 500, 600, 1650, 550 550, 600 500, 600, 550, 550, 1650, 600, 550, 550, 1650 , 600,1650, 600,500, 600,1650, 600,1600, 600,1650, 600}; // SAMSUNG E0E048B7 // Вставить ИК-сигнал RAW для "TV Channel Down" unsigned int irTVchdn [] ={4600,4350, 650,1550, 650,1600, 650,1600, 600,500, 600,500, 600,550, 550,550, 600,550, 550 , 1650, 600,1650, 550,1700, 550,550, 550,550, 600,500, 600,550, 550,550, 600,500, 600,550, 550,550, 550,550, 600,1650, 600,500, 600,500, 600,550, 550,1650, 600,1650, 600,1650 , 550,1650, 600,550, 550,1650, 600,1650, 600,1650, 550}; // SAMSUNG E0E008F7 // Вставить ИК-сигнал RAW для «Мощность приемника» unsigned int irRECpwr [] ={9050,4350, 650,500, 600,1600, 600,500, 650,500, 600,1600, 600,550, 600,1600, 600,1650, 550,550, 600,500, 600,1600, 650,1600, 600,500, 600,1650, 600,1600, 600,500, 600,1650, 600,1600, 600,550, 600,1600, 600,500, 600,550, 600,1600, 600,1600, 650,500, 600,500, 600,1600, 650,500, 600,1600, 600,1650, 600,500, 600,500, 600}; // NEC 4B36D32C // Вставить IR-сигнал RAW для "Receiver Power On" unsigned int irRECpwrON [] ={9000,4400, 600,550, 600,1600, 600,500, 600,550, 600,1600, 600,500, 600,1600, 650,1600 , 600,1600, 600,500, 650,1600, 600,1600, 600,500, 650,1600, 600,1600, 600,500, 600,550, 600,500, 600,1600, 600,550, 600,500, 600,500, 650,500, 600,500, 600,1600, 650 , 1600, 600,500, 600,1600, 650,1600, 600,1600, 600,1600, 600,1600, 650}; // NEC 4BB620DF // Вставить ИК-сигнал RAW для "Receiver Power Off" unsigned int irRECpwrOFF [] ={9000,4400, 600,550, 550,1650, 600,550, 550,550, 600,1650, 550,550, 600,1650, 550,1650 , 600,550, 550,550, 550,1650, 600,1650, 600,550, 550,1650, 600,1650, 550,550, 600,1650, 550,1650, 600,1650, 600,500, 600,550, 550,550, 600,1650, 550,550, 600,500 , 600,550, 550,550, 550,1700, 550,1650, 600,1650, 550,550, 600,1650, 550}; // NEC 4B36E21D // Вставить ИК-сигнал RAW для "Отключение звука приемника" unsigned int irRECmute [] ={9000,4400, 650,450, 650,1600, 600,500, 600,500, 650,1600, 600,500, 600,1650, 600,1600, 600,1600, 650,500, 600,1600, 650,1600, 600,500, 600,1600, 650,1600, 600,500, 600,1650, 600,500, 600,1600, 650,500, 600,500, 600,500, 600,500, 650,500, 600,500, 600, 1600, 650,500, 600,1600, 600,1600, 650,1600, 600,1650, 600,1600, 600}; // NEC 4BB6A05F // Вставить ИК-сигнал RAW для «Уменьшение громкости приемника» unsigned int irRECvdn [] ={9150,4250, 750,350, 700,1550, 700,400, 700,450, 650,1550, 700,450, 600,1600, 650,1600 , 600,1650, 600,500, 600,1650, 600,1600, 600,550, 600,1600, 600,1650, 600,500, 600,1650, 600,1600, 650,500, 600,500, 600,500, 650,500, 600,500, 600,500, 600,550, 600,500 , 600,1650, 600,1600, 600,1650, 600,1650, 600,1600, 600,1650, 600}; // NEC 4BB6C03F // Вставить ИК-сигнал RAW для "увеличения громкости приемника" unsigned int irRECvup [] ={9050,4400, 650,500, 600,1600, 600,550, 600,500, 600,1650, 600,500, 600,1600, 650,1600 , 600,1600, 600,550, 600,1600, 600,1600, 650,500, 600,1600, 650,1600, 600,500, 600,550, 600,1600, 600,550, 600,500, 600,550, 600,500, 600,550, 600,500, 600,1600, 650,500 , 600,1600, 600,1650, 600,1600, 600,1650, 600,1600, 600,1600, 600}; // NEC 4BB640BF // Вставить ИК-сигнал RAW для "Receiver Source CBL / SAT" unsigned int irRECsrc [] ={8950,4450, 600,500, 600,1650, 600,500, 600,500, 600,1650, 600,500, 600,1600, 600 , 1650, 600,1600, 600,550, 600,1600, 600,1650, 600,500, 600,1600, 600,1650, 600,500, 600,500, 600,1650, 600,1600, 600,1650, 600,500, 600,500, 600,500, 650,500 , 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 (); // Подключаемся к сети Wi-Fi 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 запущен"); } Serial.println (); Serial.println ();} void loop () {// Проверяем, подключился ли клиент WiFiClient client =server.available (); если (! клиент) {возврат; } // Дождитесь, пока клиент отправит данные Serial.println ("новый клиент"); в то время как (! client.available ()) {задержка (1); } // Считываем первую строку запроса String req =client.readStringUntil ('\ r'); Serial.println (требуется); client.flush (); // Соответствие запросу if (req.indexOf ("/ irTVpwr")! =-1) {irsend.sendRaw (irTVpwr, sizeof (irTVpwr) / sizeof (irTVpwr [0]), khz); Serial.println («IRreq irTVpwr отправлен»); } иначе, если (req.indexOf ("/ irTVsrc")! =-1) {irsend.sendRaw (irTVsrc, sizeof (irTVsrc) / sizeof (irTVsrc [0]), khz); Serial.println («IRreq irTVsrc отправлен»); } иначе, если (req.indexOf ("/ irTVmute")! =-1) {irsend.sendRaw (irTVmute, sizeof (irTVmute) / sizeof (irTVmute [0]), khz); Serial.println («IRreq irTVmute отправлен»); } иначе, если (req.indexOf ("/ irTVvdn")! =-1) {irsend.sendRaw (irTVvdn, sizeof (irTVvdn) / sizeof (irTVvdn [0]), khz); Serial.println («IRreq irTVvdn отправлен»); } иначе, если (req.indexOf ("/ irTVvup")! =-1) {irsend.sendRaw (irTVvup, sizeof (irTVvup) / sizeof (irTVvup [0]), khz); Serial.println («IRreq irTVvup отправлен»); } иначе, если (req.indexOf ("/ irTVchup")! =-1) {irsend.sendRaw (irTVchup, sizeof (irTVchup) / sizeof (irTVchup [0]), khz); Serial.println («IRreq irTVchup отправлен»); } иначе, если (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.stop (); возвращение; } client.flush (); // Отправляем ответ клиенту //client.print(s); client.print ("HTTP / 1.1 200 OK \ r \ n"); задержка (1); Serial.println («Клиент отключен»); Serial.println (); // Клиент будет фактически отключен // когда функция вернется и объект client будет удален}
script.js JavaScript
javascript для webapp (требуется jquery)// Функция для отправки ИК-команд 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"}); } если (clicked_id =="irTVmute") {$ .get ("curl.php", {комната:"192.168.1.62", кнопка:"irTVmute"}); } if (clicked_id =="irTVvdn") {$ .get ("curl.php", {room:"192.168.1.62", button:"irTVvdn"}); } если (clicked_id =="irTVvup") {$ .get ("curl.php", {комната:"192.168.1.62", кнопка:"irTVvup"}); } если (clicked_id =="irTVchup") {$ .get ("curl.php", {комната:"192.168.1.62", кнопка:"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.html HTML
Базовый HTML для отображения кнопок.
TV
Получатель
curl.php PHP
php-скрипт для отправки запросов GET на ESP8266php $ room =$ _GET ['room']; $ button =$ _GET ['кнопка']; // Создание вызова cURL $ service_url ='http://'. $ комната. '/'. кнопка $; $ curl =curl_init ($ service_url); // Отправляем cURL на доску Yun curl_setopt ($ curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); $ curl_response =curl_exec ($ curl); curl_close ($ curl); // Распечатать ответ echo $ curl_response;?>
manifest.json JSON
Это позволит веб-странице работать как собственное веб-приложение в Android.{"name":"WiFi Remote", "icons":[{"src":"remote_icon_36.png", "sizes":"36x36" , "тип":"изображение / png", "плотность":0,75}, {"src":"remote_icon_48.png", "размеры":"48x48", "тип":"изображение / png", "плотность" :1.0}, {"src":"remote_icon_128.png", "sizes":"128x128", "type":"image / png", "density":1.0}, {"src":"remote_icon_192.png" , "sizes":"192x192", "type":"image / png", "density":1.0}], "scope":"/ remote /", "start_url":"/remote/index.html", "дисплей":"полноэкранный", "ориентация":"портрет"}
Схема
Ничего особенного, просто питание и один контакт, подключенный к транзистору NPN, для последовательного управления двумя ИК-светодиодами (без резисторов) от напряжения питания 5 В.

Производственный процесс
- Недостатки Wi-Fi RTLS
- Новая беспроводная технология 2015 г.
- Как установить защищенный встроенный веб-сервер на устройство Wi-Fi стоимостью 3 доллара
- Связь MQTT между NodeMCU и Raspberry Pi 3 B +
- РОБОТ МАЛИНЫ PI WIFI, УПРАВЛЯЕМЫЙ С СМАРТ-ТЕЛЕФОНА ANDROID
- Робот, управляемый Wi-Fi и использующий Raspberry Pi
- Что такое звонки по WiFi? Как это работает?
- IOT - Smart Jar с использованием ESP8266, Arduino и ультразвукового датчика
- Умный дверной замок с использованием страницы входа в WiFi от Arduino и ESP8266
- Что такое бисерный взрыв? Руководство по дробеструйной очистке