Умный WiFi выключатель света

от автора

Доброго времени суток, уважаемый читатель.

Немного лирики в начале. Идея «умного» выключателя света совсем не нова и, наверное, это первое, что приходит в голову тем, кто начал знакомство с платформой Arduino и элементами IoT. И я этому не исключение. Поэкспеременировав с элементами цепей, моторчиками и светодиодами хочется сделать нечто более прикладное, что востребовано в повседневной жизни и, самое главное, будет удобно в использовании, а не останется жертвой эксперимента в неугоду комфорту.

В этой статье я расскажу, как я сделал выключатель, который будет работать как обычный (т.е. что обычно закреплен на стене) и в то же время позволит управлять им через WiFi (или через Интернет, как это сделано в данном случае).

Итак, составим список того, что понадобится для осуществления задуманного. Сразу скажу, я намеревался не тратиться сильно на комплектующие и выбирал компоненты по отзывом на форумах и соотношению цены к качеству. Поэтому некоторые компоненты возможно покажутся тут неуместными для опытных электролюбителей, но прошу не судить строго, т.к. я только новичек в электромеханике и буду очень признателен за комментарии более опытных специалистов.

Наименование Описание Цена
1 HLK-PM01 Адаптер 220VAC в 5VDC 4,02€
2 SSR-40DA Твердотельное реле для управления током в цепи 3,35€
3 AMS1117-3.3 Понижатель напряжения c 5V на 3V 1,29€
4 ESP8266-01 Микроконтроллер с WiFi 2,35€
Итого: 11,01€

Так же мне понадобились: сервер, с помощью которого выключатель будет управляться через Интернет, Arduino Uno, с помощью которого я программировал ESP, роутер и расходные материалы как провода, клеммы и т.д., всё это может варироваться от вкусов и никак не повлияет на конечный результат.

Цены взяты из Ebay, где я их и покупал.

А вот как выглядят элементы из таблицы:

Теперь можно составить и схему подключения:

Как вы наверное заметили, схема очень простая. Все собиратся легко, быстро и без пайки. Эдакий рабочий прототип, с которым не нужно долго возиться. Всё связано проводами и клеммами. Единственный минус это то, что реле не влезло в гнездо выключателя. Да, изначально я планировал запихнуть всё это в стену за выключателем, чтобы смотрелось эстетично. Но к моему сожалению места в гнезде оказалось мало и реле просто напросто не влезло ни вдоль, ни поперек:

Поэтому временно я вынес реле за гнездо, до тех пор пока не найду подходящую коробку выключателя с розеткой чтобы спрятать железо внутрь. Но нет ничего более постоянного, чем временное, не правда ли? Поэтому все это выглядит сейчас вот так:

Изолента спасёт от удара током… надеюсь.

А теперь поговорим о програмной части.

И прежде чем приступать к разбору кода и деталей, я приведу общую схему реализации управления лампочкой.

Надеюсь, я когда нибудь все перепишу и связь будет основана на более быстром протоколе нежели HTTP, но для начала сойдет. Удаленно лампочка меняет свое состояние приблизительно за 1-1.5 секунды, а с выключателя моментально, как и подобает порядочному выключателю.

Программировании ESP8266-01

Самый простой способ сделать это — с помощью Arduino. Скачать необходимые библиотеки для Arduino IDE можно с GitHub. Там же все инструкции по установке и настройке.

Далее нам нужно подключить ESP к компьютеру, для этого понадобится либо USB to Serial Адаптер (типа FTDi, CH340, FT232RL) либо любая Arduino платформа (у меня была Arduino Uno) с выходами RX и TX.

Стоит отметить, что ESP8266-01 питается от 3.3 Вольта, а значит ни в коем случае не подключайте его к питанию Arduino, которые (часто) питаются от 5 Вольт, напрямую иначе все сгорит к чертям. Можно использовать понижатель напряжения, который приведен в таблице выше.

Схема подключения проста: подключаем TX, RX и GND ESP к RX, TX и GND адаптера/Arduino соотвественно. После этого, собственно, подключение готово к использованию. Микроконтроллер можно программировать используя Arduino IDE.

Пара нюансов при использовании Arduino Uno:

  • На Uno есть выход для 3.3В, но его оказалось недостаточно. При подключении к нему ESP, все вроде работает, индикаторы горят, но связь с COM портом теряется. Поэтому я использовал другой источник питания на 3.3В для ESP.
  • К тому же у UNO не возникло никаких проблем при общении с ESP, с учетом того, что UNO питался от 5В, а ESP от 3В.

После нескольких экспериментов с ESP8266-01, выяснилось, что ESP чувствительны к подключенным к GPIO0 и GPIO2 напряжениям. В момент старта они ни в коем случае не должны быть заземлены, если вы намереваетесь запустить его в штатном режиме. Более подробно о старте микроконтроллера тут. Я этого не знал и мне пришлось слегка менять схему, т.к. в версии ESP-01 присутсвтуют только эти 2 пина и в моей схеме используются оба.

А вот и сама программа для ESP:

Показать программу

#include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> #include <ESP8266HTTPClient.h> extern "C" { // эта часть обязательна чтобы получить доступ к функции initVariant   #include "user_interface.h" }  const char* ssid = "WIFISSID"; // Имя WiFi const char* password = "***************"; // Пароль WiFi const String self_token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // токен для минимальной безопасности связи const String serv_token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // токен для минимальной безопасности связи const String name = "IOT_lamp"; // имя выключателя, читай лампочки const String serverIP = "192.168.1.111"; // внутренний IP WEB сервера  bool lamp_on =  false; bool can_toggle = false; int button_state;  ESP8266WebServer server(80); // веб сервер HTTPClient http; // веб клиент  const int lamp = 2; // Управляем реле через GPIO2 const int button = 0; // "Ловим" выключатель через GPIO0  // функция для пинга лампочки void handleRoot() {    server.send(200, "text/plain", "Hello! I am " + name); }  // функция для недействительных запросов void handleNotFound(){   String message = "not found";   server.send(404, "text/plain", message); }  // Да будет свет void turnOnLamp(){   digitalWrite(lamp, LOW);   lamp_on = true; }  // Да будет тьма void turnOffLamp(){   digitalWrite(lamp, HIGH);   lamp_on = false; }  // Отправляем серверу события ручного вкл./выкл. void sendServer(bool state){   http.begin("http://"+serverIP+"/iapi/setstate");   String post = "token="+self_token+"&state="+(state?"on":"off"); // По токену сервер будет определять что это за устройство   http.addHeader("Content-Type", "application/x-www-form-urlencoded");   int httpCode = http.POST(post);   http.end();   }  // Изменяем состояние лампы void toggleLamp(){   if(lamp_on == true) {     turnOffLamp();     sendServer(false);   } else {     turnOnLamp();     sendServer(true);   } }  // Получаем от сервера команду включить void handleOn(){   String token = server.arg("token");   if(serv_token != token) {     String message = "access denied";     server.send(401, "text/plain", message);     return;   }   turnOnLamp();   String message = "success";   server.send(200, "text/plain", message); }  // Получаем от сервера команду выключить void handleOff(){   String token = server.arg("token");   if(serv_token != token) {     String message = "access denied";     server.send(401, "text/plain", message);     return;   }   turnOffLamp();   String message = "success";   server.send(200, "text/plain", message); }  // Устанавливаем MAC чтобы давать одинаковый IP void initVariant() {   uint8_t mac[6] = {0x00, 0xA3, 0xA0, 0x1C, 0x8C, 0x45};   wifi_set_macaddr(STATION_IF, &mac[0]); }  void setup(void){   pinMode(lamp, OUTPUT);   pinMode(button, INPUT_PULLUP); // Важно сделать INPUT_PULLUP   turnOffLamp();   WiFi.hostname(name);   WiFi.begin(ssid, password);    // Ждем пока подключимся к WiFi   while (WiFi.status() != WL_CONNECTED) {     delay(500);   }    // Назначем функции на запросы   server.on("/", handleRoot);   server.on("/on",  HTTP_POST, handleOn);   server.on("/off", HTTP_POST, handleOff);   server.onNotFound(handleNotFound);    // Стартуем сервер   server.begin(); }  void loop(void){   server.handleClient();    // Проверяем нажатие выключателя   button_state = digitalRead(button);   if (button_state == HIGH && can_toggle) {     toggleLamp();     can_toggle = false;     delay(500);   } else if(button_state == LOW){     can_toggle = true;   } } 

Пару замечаний по коду:

  • Очень важно объявить пин GPIO0 как pinMode(button, INPUT_PULLUP), т.к. в схеме мы не используем резистор для этой кнопки. А у ESP есть свои «вшитые» для этих самых целей.
  • При отлове состояния кнопки желательно установить задержку при считывании чтобы избежать ложного срабатывания в момент нажатия.

Программировании WEB сервера

Тут можно дать волю своей фантазии и использовать любые доступные средства для создания сервиса который будет обрабатывать запросы присылаемые выключателем и отправлять запросы на включение/выключение.

Я использовал для этих целей Yii. Я выбрал этот фреймворк по нескольким причинам, мне нужна была авторазация (т.к. портал доступен в Интернете) и управление ролями (для будущих экспериментов), а еще он мне просто нравится. И теперь мой портал управления выглядит так:

Для управления лампочкой в зоне досегаемости сети, хватило бы и самого сервера на ESP. Но хочется ведь иметь логи, логику и другие устройства в будущем, поэтому лушче все же использовать отдельный серер для управления.

Это всё что касается портала, думаю нет смысла писать о нем больше, но если возникнут вопросы, то с радостью отвечу на них в комментариях.

Вместо заключение

Спасибо, если дочитали статью до конца и, возможно, нашли в ней что либо для себя полезное. Буду рад советам и критике. В целом, мне до сих пор кажется, что узкое место в цепи это Адаптер на 5В и буду рад, если Вы поделитесь своим опытом решения подобных задач. Что касается ESP8266-01, то пока он не вызвал у меня никаких нареканий кроме как особого использования пинов GPIO. Работает пока стабильно вторую неделю. Успехов в проектах.

ссылка на оригинал статьи https://geektimes.ru/post/274869/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *