Сервер для лампочки

Всем здрям! Хочу поделиться своей реализацией «умного» (на самом деле очень «тупого», но практичного) освещения.

Давным-давно, в тридесятом царстве, делал в жилище ремонт, и по задумке исключил из обстановки люстру. Вместо нее прицепил 10 метров светодиодной ленты под потолком по длинным стенам (по 5 метров на каждую). Пользовался, радовался, но всё не выходила из головы мысль, что лентой можно управлять не только при помощи аналогового выключателя на стене. Так шли годы, сменялись ленты на более яркие и блоки питания на более мощные, а по управлению ничего не менялось.

Отдельное отступление по поводу «умного дома».

До сих пор не могу придумать реального применения системы «умный дом» в условиях квартиры. Если в отдельном частном доме еще более понятно (управление отоплением, поливом, светом на участке, датчики температуры и прочее) , но в квартире не вижу смысла городить что то сложнее умной подсветки в отдельно взятом уголке. Ну или какие либо датчики температуры (что бы просто посмотреть что ЖКХ не справляются, и почему тебе дома холодно), или датчики затопления (полезно конечно, но только для одной этой функции городить что то не вижу смысла, если нет какого то комплекса).

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

И вот это время однажды наступило. Обрисовал на клочке бумаги задачу для себя, прикинул паяльник к носу, и собственно сотворил.

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

С моими скудными познаниями в программировании Ардуино и ESP, взялся за задачу начав с замечательной программы Flprog, нарисовав в ней WEB-интерфейс для непосредственного управления светом через браузер.

Скриншот интерфейса.

14816469ba0121c042c388744264c987.jpg

Тут все просто. Отображение уровня яркости по шкале от 0 до 255 (переменная byte для ШИМ), увеличение/уменьшение яркости c шагом 10 единиц. Кнопка активации «заката» — плавное уменьшение яркости в течении приблизительно 7-ми минут (запас для гигиенических процедур, и укладывания себя в постель). Кнопка «рассвета» — плавное нарастание яркости в течении 20-ти минут (собственно основное предназначение управление светом, функция «Будильник-рассвета»). И кнопка «ночное освещение» — активирует яркость света приблизительно на 10% от полной мощности (чтобы включать ночью сходить до холодильника/санузла, не выжигая при этом себе глаза), светит около 3-х минут и гаснет (как раз хватает на исполнение своих потребностей).

Собственно интерфейс и управление через него готово в Flprog, переходим в ArduinoIDE для более тонкой настройки и добавлению функций управления через HTTP.

Поскольку одной из задач была универсальность управления с любого устройства без заморочек, был выбран именно HTTP, просто, надёжно, быстро. Можно управлять как просто через адресную строку бразузера на любом доступном устройстве, так и через команды из Терминала Linux/Командную строку Windows (а это уже путь к какой-никакой автоматизации).

Да, конечно, код Сгенерированный Flprog громоздок, избыточен, но главное разбираться с написанием собственного интерфейса в ArduinoIDE не было ни желания, ни надобности.

Поэтому просто взял сгенерированную основу, и добавил несколько функций HTTP сервера для непосредственного управления без использования WEB-морды.

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

Переменные:

 bool _gtv1 = 0; //статус ручного управления

byte _gtv2 = 255; //Уровень яркости

bool _gtv3 = 0; //Включить рассвет

bool _gtv4 = 0; //включить закат

bool _gtv5 = 0; //ночное освещение

int timerManage =0;

int valueGet =0;

uint32_t tmr1;

uint32_t tmr2;

Команды GET для активации функий:

ESPControllerWifi_tspWebServer.on("/commands", runcommand);
//вызов функций через GET из сети

ESPControllerWifi_tspWebServer.on("/manual", ManualValue);
//вызов функций через GET из сети

Добавленные функции:

void rise(){ //Активация рассвета

  if (_gtv3==true && _gtv1==true){

    if (millis()-tmr1 > 5000){

      tmr1=millis();

      if (_gtv2<255) {

        _gtv2++;

      }

      else {

        timerManage =0;

        _gtv3=false;

        _gtv1=false;

      }

    }

  }

} 

void getsleep(){ //Активация заката

  if (_gtv4==true && _gtv1==true){

    if (millis()-tmr2 > 2000){

      tmr2=millis();

      if (_gtv2>2) {

        _gtv2--;

      }

      else {

        _gtv2=0;   

        _gtv4=false;

      }

    }

  }

} 

void nightlight(){ //Активация ночного освещения

  if (_gtv5==true && _gtv1==true){

    _gtv2=50;

    if (millis()-tmr2 > 1000){

      tmr2=millis();

      timerManage++;

      if (timerManage>180){

      timerManage=0;

      _gtv5=false;

      _gtv2=0;//  

      }

    }

  }

} 

void runcommand(){ //Приём команд  

String com = ESPControllerWifi_tspWebServer.arg("com");

  if (com == "rise") {

    _gtv3= true;

    ESPControllerWifi_tspWebServer.send(200, "text/plain", "rise");

  } 

  if (com == "sleep") {

    _gtv4= true;

    ESPControllerWifi_tspWebServer.send(200, "text/plain", "sleep");

  } 

  if (com == "light") {

    _gtv5= true;

    ESPControllerWifi_tspWebServer.send(200, "text/plain", "light");

  } 

  if (com == "manon") {

    _gtv1= true;

    ESPControllerWifi_tspWebServer.send(200, "text/plain", "manual on");

  } 

  if (com == "manoff") {

    _gtv1= false;

    ESPControllerWifi_tspWebServer.send(200, "text/plain", "manual off");

  } 

  if (com == "reset") {

    _gtv3 = false;

    _gtv4 = false;

    _gtv5 = false;

    ESPControllerWifi_tspWebServer.send(200, "text/plain", "reset all task");

  } 

  } 

 void ManualValue() { //Прием команд для выставления уровня яркости  

String valueHands = ESPControllerWifi_tspWebServer.arg("value");

  valueGet = valueHands.toInt();

  if (valueGet < 1) {

    _gtv2 = 0; //

     ESPControllerWifi_tspWebServer.send(200, "text/plain", "min");

  }

    if (valueGet > 254) {

    _gtv2 = 255;

     ESPControllerWifi_tspWebServer.send(200, "text/plain", "max");

    }

    if ((valueGet > 0) && (valueGet <255)) {

    _gtv2 = valueHands.toInt();

    ESPControllerWifi_tspWebServer.send(200, "text/plain", valueHands);

  }

 }

У AlexGyver подсмотрел как работать с millis и ШИМ, а так же об управлении МOSFETами и реле. А так же плавным управлением яркостью светодиодов.

Поигрался со встроенным на плате светодиодом. Дальше переходим к электронной части.

Тут пришлось покурить мануалы, гайды, даташиты и прочую литературу и видосики.

Однозначно решил что у платы управления будет два режима. Первый — это прямая подача напряжения с блока питания на светодиодную ленту. Дабы не напрягать лишний раз мосфеты. И второй режим собственно управление через ШИМ. Для этого установленно переключающее реле на одну из ног NodeMCU.

Реле и мосфеты удачно нашлись в стареньком списанном ИБП IPPON Back Power Pro 600.

Ага, вот этот парень.

7801bec5b89a8b77bfa81cd93a82a7a4.jpg

Один мосфет на управление реле. И два мосфета параллельно на управление лентой (хоть в даташите и было указано что они способны выдерживать до 10А при управляющем напряжении 3,3V, на всякий случай перестраховался). Потребление ленты — 8А. То есть два 5-и метровых отрезка по 4А. Изначально хотел на каждый отрезок по своему отдельному мосфету, но потом забил на это, поскольку даже в голову не приходило зачем мне это может понадобиться. Мы же делаем практично, а не красиво. Поэтому просто запараллелил (заранее скажу, мосфеты не греются совершенно. Даже не тёплые).

Дополнительно на плате вывел контакты для подключения ИК-приёмника. Это так, на будущее, пока что нет даже пульта с которого планируется управление. Потом собираюсь приобрести какой нибудь ИК-пульт-брелок. Но кроме функции активации ночного освещения, пока что не могу придумать более широкое его применение.

Плюс парочка резисторов, клемников и текстолит.

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

Несколько фоток процесса и результата:

(и при первом же включении я спалил стабилизатор напряжения и преобразователь ch340g на плате NodeMCU, поскольку плата оказалась не способна принимать в качестве питания 12V, как было указано в на странице продавца. Поэтому на плату был припаян еще понижающий преобразователь на 3,3V для питания ESP)

Впихиваем всё это чудо в коробку с блоком питания, и наслаждаемся своим успехом.

Фото коробки:

Основная самая сложная часть окончена. Играемся с режимами, выделываемся перед гостями.

Запросы get

http://ip/commands? com=rise //активация рассвета

http://ip/commands? com=sleep //активация заката

http://ip/commands? com=light //активация ночного режима

http://ip/commands? com=manon //активация режима управления

http://ip/commands? com=manoff //деактивация режима управления

http://ip/commands? com=reset //перезагрузка ESP

http://ip/manual? value=0…255 //установка уровня яркости

Сразу после включения (а включение/выключение осталось прежним, аналоговым, через банальный выключатель на стене) управление деактивировано. Реле стоит в положении прямой подачи тока на светодиодную ленту. Режим управления включается либо вручную по надобности, либо при активации заката. (лёгкий щелчок реле, как побочный бонус, сигнализирует о том, что пора бы уже баиньки укладываться). Выключается управление так же вручную, либо после завершения режима рассвета. Собственно при выходе из дома мы просто щелкаем выключателем и обесточиваем всю схему, ибо зачем оно мне нужно если меня нет дома. А удаленное управление я вижу как бессмысленным, так и небезопасным в виду моей паранойи и на коленке собранной схемы .

Итог: Закат

0b5aa74d29719c1c5c4616fe31b363ee.gif

Итог: Рассвет

12429d9aaad4a3b4f51ec70c84327bf9.gif

Теперь об автоматизации. Собственно возвращаемся к заголовку и читаем «Сервер для лампочки».

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

И поскольку у нас есть «рассветный» режим, было бы неплохо к нему прикрутить и будильник. Давно вынашивал эту идею. Но не знал как лучше всего реализовать. У того же AlexGyver было видео с созданием подобной лампы из сантеха и Ардуино, но то был просто светильник. Но раз умный управляемый свет уже есть, то и работать мы будем с ним, не прибегая к отдельным девайсам. Добавим только звуковой будильник. И чтобы играл не абы что, а любимую интернет радиостанцию. Собственно исходя из этой хотелки и вырос отдельный сервер.

Изначально Сервер представлял собой старенький планшет, с установленными на нём MacroDroid и PocketBell (планшет с MarcoDroid и сейчас иногда используется для активации ночного режима, вывел на главный экран кнопку кидающую GET запрос на ESP), но мне показалось это слишком усложненным и костыльным. Во-первых, это нужно качать приложения и настраивать каждое по отдельности. Во-вторых, просто неудобно и не отвечает требованиям универсальности.

Поэтому под сервер выделяем отдельную железку и прячем с глаз долой.

А под рукой оказался старенький тонкий клиент HP t510.

HP Thin Client T510

e96c0eb7955eedd6eb4a4da238b7bfe0.jpg

С него были сняты все лишние корпусные пластиковые детали, так он стал даже симпатичнее на мой взгляд. Вместо установленного там накопителя IDE (который объемом аж целый Гигабайт!!!) был установлен маленький SSD объемом 8 Гигабайт (когда то давно заказывал несколько штук), благо в тонком клиенте разъем SATA присутствует. С помощью смекалки и пассатижей впихиваем накопитель в корпус, и вот с этим уже можно работать.

Hidden text

0ff66c1679cbbbb2045c94e4854b2d62.jpeg7c35f729c3ba4f6a955dccf45368a142.jpeg

Вешаем этот девайс за монитором и на него же вешаем колонки. В качестве колонок использована неисправная Bluetooth колонка, из которой была выкинута вся электроника и вместо неё установлена плата усилителя с питанием от USB. (собственно силы на написание этой статьи нашлись после комментария под статьёй о переделке колонки https://habr.com/ru/post/724440/. Спасибо sergey-antonov).

Фоток процесса к сожалению не делал, поэтому только фото конечного результата.

Вид «сервера»:

2baba938318604ec6142fc6f29451fdb.jpeg

Устанавливаем на это чудо Debian 11 без GUI (работаем с ним через SSH), устанавливаем MPD и MPC (и забиваем адрес любимой радиостанции)

Добавляем радиостанцию в MPC:

mpc add https://radiorecord.hostingradio.ru/rmx96.aacp

И пишем несколько простеньких Bash скриптов (что полностью удовлетворяет условию универсальности.

Hidden text

Будильник:

 #!/bin/bash mpc volume 1 //устанавливаем громкость плеера на минимум 

mpc play //включаем проигрывание  

wget http://192.168.10.103/commands?com=rise -O /dev/null //кидаем команду на активацию рассвета 

sleep 600  for vol in 5 10 15 20 25 // потихоньку прибавляем громкости музыке   

   do        

     sleep 30       

      mpc volume $vol

   done 

Ложимся спать:

#!/bin/bash  wget http://192.168.10.103/commands?com=manon -O /dev/null 

sleep 5 

wget http://192.168.10.103/commands?com=sleep -O /dev/null  

Выключаемся (и двигаем на работу):

 #!/bin/bash  


/sbin/shutdown now  

Настраиваем Cron

0 6 * * 1–5 /usr/rise.sh

40 6 * * 1–5 /usr/shut.sh

0 9 * * 6,0 /usr/rise.sh

30 21 * * 0–4 /usr/sleep.sh

15 23 * * 5–6 /usr/sleep.sh

Собственно вот и всё. Теперь наслаждаемся тёплым рассветом и приятной музыкой в холодные зимние утра. И еще больше понтуемся перед гостями. И получаем чувство удовлетворения от успеха в начинаниях создания «умного дома» (главное что бы на этом всё и не закончилось).

Всем спасибо за прочтение, комментируйте, критикуйте!

© Habrahabr.ru