Умный 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. Работает пока стабильно вторую неделю. Успехов в проектах.
    Поделиться публикацией
    Комментарии 29
      +1
      Реле на 40А — вы прожектор на пару киловатт коммутировать планируете? Симистора на монете 5 рублей в качестве радиатора хватит за глаза для освещения.
      Или вообще все это безобразие выкинуть и взять готовый модуль — https://www.itead.cc/smart-home.html. И оголенным проводом никого не убъет и пожара не будет. И прошивочку еще в него от homes-smart залить. Правда романтики никакой не останется… :)
        –1
        Правда романтики никакой не останется
        Именно :)
        Реле на 40А
        Стояли они так же как и на 10А, поэтому решил перестраховаться, мало ли что буду подключать через него
        и взять готовый модуль
        Они, как правило, не отлавливают ручное выключение
          0
          От 10А и меньше твердотельные реле есть в мелких корпусах.
          GPIO, как отметили ниже, там выведены. Есть вариант RF с пультом, что еще веселее. Либо вообще переходник в патрон лампочки, тогда и подрозетник не надо ковырять :)
            0
            Шайба больно здоровая, даже не знаю в какой светильник оно войдёт, чтобы гармонично смотрелось…
              0
              Можно проще сделать — корпус выкинуть, а плата вполне войдет в основание почти любой люстры :)
              0
              А вот в мелких корпусах дешевых твердотельных релешек не нашел, буду рад если поделитесь ссылкой.
              GPIO, как отметили ниже, там выведены
              да, было бы здорово)
              Но если запихнуть все в патрон лампочки, то придется проводить выключатель на стену ;)
                0
                Можно повесить пульт от RF версии на стену :)
                Ссылку сходу не подскажу, т.к. видел в магазине электротоваров. На витрине рядом с фотеками были релешки раза в два меньше их, но черные и на токи 1,3,5,10А. Плюс подобные тоже были: http://www.chipdip.ru/product/esr2002400300/
                Думаю в онлайне найти не проблема будет.
                  0
                  Ну почему твердотельное реле а не симистор с опторазвязкой? они до 1$ все
            0
            Если реле не поместилось в подрозетник, то хоть какой-нибудь корпус для него придумайте — сейчас поделка выглядит уж слишком колхозно. И может у «понижателя» есть другое общепринятое название?
              0
              ну ладно… вот критика
              1) вы всегда для управления лампочкой стреляете из пушки на 40 Ампер? хватило бы и обычной малогабаритной реле для ардуинки коих в интернете валом на каждом шагу как грязи. среднестатистически 10 Ампер на группу контактов подавать можно. но это уже надо подсчитать что за нагрузка и от этого уже подобрать реле.
              2) вместо реле можно сделать диммер. даже лучше чем реле для управления освещением. вот пример: https://www.youtube.com/watch?v=-YyuncOGa1U
              код управления им трёхкопеечный. затолкать этот код в есп и учесть в нём режимы управления. т.е. работа как реле (для не диммируемых или плоходиммируемых ламп) и работа как диммер.
                0
                1) Про реле ответил чуть выше
                2) Проблема в том, что обычно у меня LED лампы, с ними всё сложнее :(
                  0
                  LED лампы бывают и диммируемые, например: http://www.ikea.com/ru/ru/catalog/products/30305976/
                    0
                    Надо будет попробовать, спасибо за наводку.
                      0
                      Только прочитайте про них сначала, у них есть свои особенности (минимум светового потока может быть несколько высоковатым; возможно мерцание; возможен шум — в общем, надо смотреть отзывы\тесты по конкретным дампам, чтобы выбрать адекватную, но это как всегда).
                +1
                Скажите, а почему вы решили не использовать Sonoff за $5? Плата 65х34 вроде должна убраться.
                https://www.itead.cc/sonoff-wifi-wireless-switch.html
                  0
                  Хотелось еще ловить и нажатие кнопкой, т.е. самим ручным выключаетелем, чтобы в логах оставалось. Не всегда ведь удобно выключать свет через девайс.
                    0
                    Я так понял, там выведены GPIO ESP-шки.
                      0
                      Если так, то это здорово, в следующий раз попробую заказать, разобрать и перепрагроммировать :)
                        +2
                        Обязательно статью напишите про это, если руки дойдут.
                      0
                      Не в курсе про API у этой системы (сам всё собираюсь купить и попробовать, но жалко платить за доставку дороже прибора), но в крайнем случае можно просто считывать состояние модуля с некой периодичностью записать включение через кнопку.
                      Зато у этого варианта целых 2 плюса: цена в 2 раза ниже, чем у вас и размер платы позволит запихнуть её куда надо.
                      Хотя 40 ампер оно точно не обеспечит, но для лампочки, а тем более светодиодной это вообще не критично.
                        0
                        Её размер больше чем у релешки на фото. 6 x 4.5 x 2.2 см. против 8.8 x 3.8 х 2.3. Сама плата конечно чуть меньше, 6.5, но и она не влезет, посреди сокета для розетки еще есть сама проводка.
                    +1
                    Зарядка для телефона 1A —
                      0
                      Коммент пользователя съелся. Вот полный текст:

                      Зарядка для телефона 1A — <$1 — Вскрывается очень легко, подпаяться к двум контактам тоже не сильно сложно. Ну или просто взять старый usb кабель и воткнуть в разьём.
                      OMRON G3MB-202P — $1 — Хватит для нагрузки до 100W.
                      AMS1117-3.3 — За вашу цену можно взять 10шт уже распаянных.
                      ESP-07 — Керамическая антенна + возможность подключить внешнюю для удалённых уголков дома + больше ног выведено.
                      Всё брал на Али. Итого уложился в 5 баксов.
                      0
                      Для света и обычное реле+mosfet пойдет, TRU-3VDC-SB-CL, например — 3V 120ma. Ключ — любой малогобаритный мосфет от 200 мА. Стоить будет меньше одного евро.
                        0
                        Я бы использовал, ESP более поздней версии, т.к. их удобнее программировать и подключаться. Есть небольшие БП 220В — 3.3В, съэкономим ещё чуть-чуть места.
                        А по сути вменяемого способа сделать wifi-выключатель с ручным управлением, умещающийся в подрозетник как не было так и нету. Сам ищу варианты.
                          0
                          Я понимаю что Гиктаймс не Хабр, но, все-таки, ни строчки кода в статье с тегом DIY печально «наблюдать». Вы привели схему и фото. На фото есть кнопка, которой нет на схеме (маленькая черненькая), для чего она и как подключали? И не совсем понятно на каком железе работает сревер? Вы его не на ESP подняли, как я понял? Очень интересен код и на чем для «Умного дома» сервер держите.
                            0
                            Пожалуйста, прежде чем писать коммент, ознакомьтесь со статьей. Код, как правило, скрывают под спойлером.
                            Что касается кнопки. Она есть на схеме, это «включатель». Подключена так же как показано на схеме и это кнопка потому, что GPIO не должны быть заземлены при старте. Таким образом, если зажать кнопку при рестарте всей системы, то ESP просто напросто не запустится в нормальном режиме. Касательно железа серсера, в статье уже сказано что это на вкус и цвет… хоть на ESP можно поднять если хотите. У меня, например, роль сервера выполняет старенький ноутбук с веб сервером на борту. Код для серверной части пока давать бессмыслено, т.к. в нем пока только что реализованы роли и несколько запросов типа включить, выключить. Как только это перерастет в нечто большее и стоящее внимания, то напишу про это отдельную статью.
                              0
                              Спасибо за ответ. Глаза, видно, к вечеру устали и спойлер пропустил во время чтения статьи. А с кнопкой смутило наличие выключателя с желтой изолентой. Я его принял за «кнопку»
                            0
                            Как совет: в код добавить ArduinoOTA модуль, чтобы если приспичит что-то ещё прикрутить — не вынимать всё и не подрубаться к RX-TX! Тем паче — на модулях «первых», где контактов не особо много и многие RX-TX под свои нужды забирают…

                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                            Самое читаемое