ESP8266:Примеры/Управление RGB-лампочкой с помощью ИК-передатчика и ESP8266
Черновик |
Управление RGB-лампочкой с помощью ИК-передатчика и ESP8266
В этом проекте мы научимся использовать ИК-передатчик для управления RGB-светодиодной ИК-лампочкой при помощи веб-сервера на базе ESP8266. Мы сможем отправлять команды для включения/выключения лампочки, уменьшения/увеличения ее яркости, переключения ее на красный, зеленый, синий, фиолетовый цвета и т.д. Проект будет поделен на 2 части:
- Расшифровка ИК-сигналов, отправляемых пультом управления лампочкой
- Настройка ESP8266 на отправление этих ИК-сигналов
Передача и прием ИК-сигналов
На фото ниже изображен ИК-приемник TSOP4838.
Как видите, он оснащен 3 контактами:
- OUT (вывод данных);
- GND (Заземление);
- VCC (Источник напряжения);
Когда вы нажимаете на кнопки на пульте управления, он отправляет модулированные ИК-сигналы. Они содержат информацию, принимаемую ИК-приемником.
Каждая кнопка отправляет собственный ИК-сигнал. Таким образом, мы можем привязать каждый из этих ИК-сигналов к кнопкам на веб-странице, обслуживаемой ESP8266. Затем эти сигналы – отправляемые ИК-передатчиком, подключенным к ESP8266 – можно будет использовать для управления лампочкой.
Необходимое оборудование
- Плата ESP8266 - 1шт.;
- ИК-приемник TSOP4838 - 1шт.;
- Светодиодный ИК-передатчик - 1шт.;
- RGB-светодиодная ИК-лампочка (E27/B22) с пультом управления - 1шт.;
- Контактная макетная плата - 1шт.;
- Провода-перемычки;
Часть 1 – Расшифровка ИК-сигналов
В этой части проекта мы расшифруем ИК-сигналы, привязанные к каждой кнопке, чтобы потом эмулировать их при помощи ESP8266.
Схема
Подключите ИК-приемник и ESP8266 друг к другу согласно схеме ниже.
Данная схема приведена для ИК приемника TSOP4838, другие модели могут иметь различную распиновку. |
Код
Для работы с ИК-передатчиком и ИК-приемником нам нужно будет установить в IDE Arduino библиотеку «IRremoteESP8266». Для этого кликните в IDE Arduino на «Скетч» > «Подключить библиотеку» > «Управлять библиотеками...» (Sketch > Include Library > Manage Libraries…).
Затем вбейте в поиске «ir remote esp8266» и, найдя нужную библиотеку, кликните по кнопке «Установка» (Install). Или можете загрузить ее ZIP-архив отсюда и установить вручную.
Скопируйте код ниже в IDE Arduino, а затем загрузите его на ESP8266. Перед этим проверьте, правильные ли в IDE Arduino выбраны плата и COM-порт.
/*
* https://github.com/markszabo/IRremoteESP8266/blob/master/examples/IRrecvDemo/IRrecvDemo.ino
*
* IRremoteESP8266: IRrecvDemo
*
* Демонстрирует получение ИК-кодов при помощи библиотеки «IRrecv».
* Ко входному контакту RECV_PIN
* должен быть подключен ИК-детектор/демодулятор.
* Авторские права принадлежат Кену Ширриффу (2009), http://arcfn.com
* Изменения:
* Версия 0.2, июнь 2017
* - Изменен GPIO-контакт
(теперь он такой же, как и в других примерах);
* - Для печати «uint64_t» используется наш собственный метод;
* - Скорость передачи данных изменена на 115200 бод.
* Версия 0.1, сентябрь 2015
* - Основана на скетче «IrsendDemo» (версия 0.1, июль 2009),
* написанном Кеном Ширриффом
*/
#ifndef UNIT_TEST
#include <Arduino.h>
#endif
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRutils.h>
// ИК-детектор/демодулятор подключен к контакту GPIO14
// (на плате NodeMCU это контакт D5):
uint16_t RECV_PIN = 14;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup() {
Serial.begin(115200);
irrecv.enableIRIn(); // запускаем приемник
}
void loop() {
if (irrecv.decode(&results)) {
// print() и println() не умеют
// обрабатывать печать вместительных типов данных (uint64_t):
serialPrintUint64(results.value, HEX);
Serial.println("");
irrecv.resume(); // получаем следующее значение
}
delay(100);
}
Открываем монитор порта на скорости 115200 бод.
В этом проекте мы будем эмулировать 10 кнопок пульта управления. Нажмите на пульте на кнопку «ON». В результате в мониторе порта должен появиться код для этой кнопки.
Примечание: На одну и ту же кнопку можно нажать несколько раз – чтобы убедиться, что код получен именно для той кнопки, что вам нужна. Если вы увидите что-то вроде «FFFFFFFF», просто игнорируйте, это мусор.
Повторите этот процесс и для других кнопок. Запишите коды для всех кнопок, т.к. позже они нам еще понадобятся. На картинке ниже показаны ИК-сигналы для всех нужных нам кнопок на пульте управления.
Часть 2 – Настройка ESP8266 на отправку ИК-сигналов
В этой части мы построим цепь из светодиодного ИК-передатчика, управляемого с помощью веб-сервера на базе ESP8266.
Схема
Подключите ИК-передатчик к ESP8266 согласно схеме ниже.
ИК-передатчик нужно поместить рядом с лампочкой, чтобы она могла принимать отправляемые им ИК-сигналы.
Код
Код ниже запустит на вашей ESP8266 веб-сервер, передающий данные через порт «80». Веб-сервер будет показывать в браузере простую веб-страницу с 10 кнопками, управляющими RGB-светодиодной лампочкой.
Скопируйте код ниже в IDE Arduino, но пока не загружайте.
Сначала прочтите следующий раздел, в котором рассказывается, как отредактировать этот скетч, чтобы он заработал на вашей ESP8266.
Если у вас код ниже работает нестабильно, то вы можете попробовать вот этот альтернативный вариант. |
/*
* Скетч для управления RGB-светодиодной ИК-лампочкой с помощью ESP8266
* Руи Сантос
* Более подробно о проекте на: http://randomnerdtutorials.com
*/
#include <ESP8266WiFi.h>
#ifndef UNIT_TEST
#include <Arduino.h>
#endif
#include <IRremoteESP8266.h>
#include <IRsend.h>
// ИК-передатчик управляется через контакт GPIO4 (D2):
IRsend irsend(4);
// Вставьте здесь SSID и пароль для своей WiFi-сети:
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Переменная для хранения информации о том,
// какая кнопка была последней нажата на веб-странице:
String lastState;
// Создаем объект для сервера с портом «80»:
WiFiServer server(80);
void setup() {
irsend.begin();
Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
delay(10);
// Подготавливаем контакт GPIO4:
pinMode(4, OUTPUT);
digitalWrite(4, 0);
// Подключаемся к WiFi-сети:
Serial.print("Connecting to "); // "Подключаемся к "
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected"); // "Подключились к WiFi"
// Запускаем сервер:
server.begin();
Serial.println("Server started"); // "Сервер запущен"
// Печатаем IP-адрес:
Serial.println(WiFi.localIP());
}
void loop() {
// Проверяем, подключился ли клиент:
WiFiClient client = server.available();
if (!client) {
return;
}
// Ждем, пока клиент отправит какие-нибудь данные:
Serial.println("new client"); // "новый клиент"
while(!client.available()){
delay(1);
}
// Считываем первую строчку запроса:
String req = client.readStringUntil('\r');
Serial.println(req);
client.flush();
// Смотрим, какой именно запрос отправлен:
int irCode;
if (req.indexOf("/lamp/on") != -1) {
irCode = 0xFFE01F;
lastState = "on";
}
else if (req.indexOf("/lamp/off") != -1) {
irCode = 0xFF609F;
lastState = "off";
}
else if (req.indexOf("/lamp/brighten") != -1) {
irCode = 0xFFA05F;
lastState = "brighten";
}
else if (req.indexOf("/lamp/dim") != -1) {
irCode = 0xFF20DF;
lastState = "dim";
}
else if (req.indexOf("/lamp/red") != -1) {
irCode = 0xFF906F;
lastState = "red";
}
else if (req.indexOf("/lamp/green") != -1) {
irCode = 0xFF10EF;
lastState = "green";
}
else if (req.indexOf("/lamp/blue") != -1) {
irCode = 0xFF50AF;
lastState = "blue";
}
else if (req.indexOf("/lamp/yellow") != -1) {
irCode = 0xFF8877;
lastState = "yellow";
}
else if (req.indexOf("/lamp/cyan") != -1) {
irCode = 0xFF708F;
lastState = "cyan";
}
else if (req.indexOf("/lamp/purple") != -1) {
irCode = 0xFF6897;
lastState = "purple";
}
else {
lastState = "none";
Serial.println("Invalid request - IR signal not sent");
// "Неправильный запрос – ИК-сигнал не отправлен"
}
// Отправляем ИК-сигнал RGB-светодиодной лампочке:
Serial.print("NEC: ");
Serial.println(irCode, HEX);
irsend.sendNEC(irCode, 32);
client.flush();
// Готовим ответ клиенту (содержит веб-страницу):
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>";
s += "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"></head>";
s += "<h1>RGB Lamp</h1>Last state: ";
s += lastState;
s += "<p><a href=\"/lamp/on\"><button>ON</button></a><a href=\"/lamp/off\"><button>OFF</button></a></p>";
s += "<p><a href=\"/lamp/brighten\"><button>BRIGHTEN</button></a><a href=\"/lamp/dim\"><button>DIM</button></a></p>";
s += "<p><a href=\"/lamp/red\"><button>RED</button></a><a href=\"/lamp/green\"><button>GREEN</button></a><a href=\"/lamp/blue\"><button>BLUE</button></a></p>";
s += "<p><a href=\"/lamp/yellow\"><button>YELLOW</button></a><a href=\"/lamp/cyan\"><button>CYAN</button></a><a href=\"/lamp/purple\"><button>PURPLE</button></a></p>";
s += "</html>\n";
// Отправляем ответ клиенту и отключаем его:
client.print(s);
delay(1);
Serial.println("Client disconnected"); // "Клиент отключен"
client.stop();
}
Редактируем скетч
Перед загрузкой скетча в него нужно вписать SSID и пароль для своей WiFi-сети:
// Вставьте здесь SSID и пароль для вашей WiFi-сети:
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Теперь возьмите ИК-коды, найденные в части 1, и впишите их в переменные «irCode», соответствующие нужным командам.
// Смотрим, какой именно запрос отправлен:
int irCode;
if (req.indexOf("/lamp/on") != -1) {
irCode = 0xFFE01F;
lastState = "on";
}
else if (req.indexOf("/lamp/off") != -1) {
irCode = 0xFF609F;
lastState = "off";
}
else if (req.indexOf("/lamp/brighten") != -1) {
irCode = 0xFFA05F;
lastState = "brighten";
}
else if (req.indexOf("/lamp/dim") != -1) {
irCode = 0xFF20DF;
lastState = "dim";
}
(...)
Добавив новые операторы else if(), вы можете оснастить скетч и другими кнопками пульта. Но эти кнопки также нужно будет добавить на веб-страницу, и для этого в код нужно будет вписать примерно следующее (здесь показаны фрагменты для кнопок «ON», «OFF», «BRIGHTEN» и «DIM»):
s += "<p><a href=\"/lamp/on\"><button>ON</button></a><a href=\"/lamp/off\"><button>OFF</button></a></p>";
s += "<p><a href=\"/lamp/brighten\"><button>BRIGHTEN</button></a><a href=\"/lamp/dim\"><button>DIM</button></a></p>";
Внеся все необходимые изменения, загрузите скетч на ESP8266.
Узнаем IP-адрес ESP8266
Загрузив скетч на ESP8266, кликните в IDE Arduino на «Инструменты» > «Монитор порта» (Tools > Serial Monitor). Когда ESP8266 загрузится, в мониторе порта должен напечататься ее IP-адрес.
В моем случае это «192.168.1.22» (как на скриншоте выше). В вашем случае IP-адрес, скорее всего, будет другим. Сохраните его, чтобы затем с его помощью заходить на веб-страницу для управления ИК-лампочкой.
Демонстрация
Откройте веб-браузер на любом устройстве, подключенном к той же сети, что и ESP8266, введите в его адресную строку IP-адрес ESP8266 и нажмите на ↵ Enter .
Поместите светодиодный ИК-передатчик рядом с ИК-лампочкой. Понажимайте на кнопки на веб-странице для управления лампочкой – поменяйте цвет, яркость, включите/выключите ее и т.д.
Альтернативный вариант серверного кода
Если у вас предыдущий вариант работает нестабильно(частые разрывы, зависания и попросту браузер не может отобразить страницу), попробуйте более стабильный вариант:
#include <ESP8266WiFi.h>
#ifndef UNIT_TEST
#include <Arduino.h>
#endif
#include <IRremoteESP8266.h>
#include <IRsend.h>
// ИК-передатчик управляется через контакт GPIO4 (D2):
IRsend irsend(4);
// Вставьте здесь SSID и пароль для своей WiFi-сети:
const char* ssid = "ваш ssid";
const char* password = "ваш пароль";
// переменная для хранения HTTP-запроса:
String header;
// Переменная для хранения информации о том,
// какая кнопка была последней нажата на веб-странице:
String lastState;
// Создаем объект для сервера с портом «80»:
WiFiServer server(80);
void setup() {
irsend.begin();
Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
delay(10);
// Подготавливаем контакт GPIO4:
pinMode(4, OUTPUT);
digitalWrite(4, 0);
// Подключаемся к WiFi-сети:
Serial.print("Connecting to "); // "Подключаемся к "
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected"); // "Подключились к WiFi"
// Запускаем сервер:
server.begin();
Serial.println("Server started"); // "Сервер запущен"
// Печатаем IP-адрес:
Serial.println(WiFi.localIP());
}
void loop() {
// начинаем прослушивать входящих клиентов:
WiFiClient client = server.available();
if (client) { // если подключился новый клиент,
Serial.println("New Client."); // печатаем сообщение
// «Новый клиент.»
// в мониторе порта;
String currentLine = ""; // создаем строку для хранения
// входящих данных от клиента;
while (client.connected()) { // цикл while() будет работать
// все то время, пока клиент
// будет подключен к серверу;
if (client.available()) { // если у клиента есть данные,
// которые можно прочесть,
char c = client.read(); // считываем байт, а затем
Serial.write(c); // печатаем его в мониторе порта
header += c;
if (c == '\n') { // если этим байтом является
// символ новой строки
// если получили два символа новой строки подряд,
// то это значит, что текущая строчка пуста;
// это конец HTTP-запроса клиента,
// а значит – пора отправлять ответ:
if (currentLine.length() == 0) {
// HTTP-заголовки всегда начинаются
// с кода ответа (например, «HTTP/1.1 200 OK»)
// и информации о типе контента
// (чтобы клиент понимал, что получает);
// в конце пишем пустую строчку:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
// "Соединение: отключено"
client.println();
int irCode;
if (header.indexOf("GET /lamp/on") >= 0) {
irCode = 0xFFE01F;
lastState = "on";
}
else if (header.indexOf("GET /lamp/off") != -1) {
irCode = 0xFF609F;
lastState = "off";
}
else if (header.indexOf("GET /lamp/brighten") != -1) {
irCode = 0xFFA05F;
lastState = "brighten";
}
else if (header.indexOf("GET /lamp/dim") != -1) {
irCode = 0xFF20DF;
lastState = "dim";
}
else if (header.indexOf("GET /lamp/red") != -1) {
irCode = 0xFF906F;
lastState = "red";
}
else if (header.indexOf("GET /lamp/green") != -1) {
irCode = 0xFF10EF;
lastState = "green";
}
else if (header.indexOf("GET /lamp/blue") != -1) {
irCode = 0xFF50AF;
lastState = "blue";
}
else if (header.indexOf("GET /lamp/yellow") != -1) {
irCode = 0xFF8877;
lastState = "yellow";
}
else if (header.indexOf("GET /lamp/cyan") != -1) {
irCode = 0xFF708F;
lastState = "cyan";
}
else if (header.indexOf("GET /lamp/purple") != -1) {
irCode = 0xFF6897;
lastState = "purple";
}
else {
lastState = "none";
Serial.println("Invalid request - IR signal not sent");
// "Неправильный запрос – ИК -сигнал не отправлен"
}
// Отправляем ИК-сигнал RGB-светодиодной лампочке:
Serial.print("NEC: ");
Serial.println(irCode, HEX);
irsend.sendNEC(irCode, 32);
client.flush();
// показываем веб-страницу:
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// веб-страница:
client.println("</head><body><h1>RGB Lamp</h1>Last state:" + lastState);
client.println("<p><a href=\"/lamp/on\"><button>ON</button></a><a href=\"/lamp/off\"><button>OFF</button></a></p>");
client.println("<p><a href=\"/lamp/brighten\"><button>BRIGHTEN</button></a><a href=\"/lamp/dim\"><button>DIM</button></a></p>");
client.println("<p><a href=\"/lamp/red\"><button>RED</button></a><a href=\"/lamp/green\"><button>GREEN</button></a><a href=\"/lamp/blue\"><button>BLUE</button></a></p>");
client.println("<p><a href=\"/lamp/yellow\"><button>YELLOW</button></a><a href=\"/lamp/cyan\"><button>CYAN</button></a><a href=\"/lamp/purple\"><button>PURPLE</button></a></p>");
client.println("</body></html>");
// конец HTTP-ответа задается
// с помощью дополнительной пустой строки:
client.println();
// выходим из цикла while():
break;
} else { // если получили символ новой строки,
// очищаем текущую строку «currentLine»:
currentLine = "";
}
} else if (c != '\r') { // если получили любые данные,
// кроме символа возврата каретки,
currentLine += c; // добавляем эти данные
// в конец строки «currentLine»
}
}
}
// очищаем переменную «header»:
header = "";
// отключаем соединение:
client.stop();
Serial.println("Client disconnected.");
// "Клиент отключился."
Serial.println("");
}
}
Итого
Итак, с помощью этого проекта мы научились встраивать ИК-передатчик и ИК-приемник в ESP8266-проект. Это лишь шаблон, но возможности применения этих ИК-устройств – безграничны. К примеру, вместо ИК-лампочки можно управлять телевизором, кондиционером воздуха, термостатом, лентой RGB-светодиодов и любым другим устройством, управляемым с помощью пульта дистанционного управления.
Так же вы можете по аналогии с вот этим примером сделать управление лампой не через браузер,а с помощью Android-виджетов.
См.также
Внешние ссылки
ESP8266 AT-команды | |
---|---|
Список AT-команд | |
Базовые команды |
|
Команды для WiFi |
|
Команды для TCP/IP |
|