Організація аварійного освітлення в під’їзді

Привіт усім! Хочу поділитися досвідом мого друга та колеги Влада Хоменчука зі створення системи аварійного освітлення в під’їзді. Це рішення стане в пригоді під час блекаутів або у випадках, коли з якоїсь причини в під’їзді відсутнє освітлення. Така система допомагає підсвітити шлях біля ніг, щоб не доводилося рухатися наосліп. Усі деталі можна придбати на AliExpress.

Дві світлодіодні стрічки 5В споживають 115 мА·год. При використанні UPS на 10 000 мА·год такого освітлення має вистачити на 86 годин.

Наявність електроенергії визначається за допомогою фотодіода. Mini UPS має світлодіод, який відображає статус живлення: зелений (світло є) і червоний (світла немає). Фоторезистор має максимальну чутливість до зеленого кольору, тоді як на червоний колір його чутливість майже нульова. Мікроконтролер фіксує різницю в чутливості до цих кольорів і визначає стан наявності електроенергії.

Серверна частина обраховує час сходу заходу сонця, надає час, та подає MQTT команди на ESP. Сервери зараз коштують не дорого, а цей проєкт Влад запускав на безкоштовній VPS від Oracle. Від себе також пораджу безкоштовний план Render (750 год безкоштовної роботи (31 доба) та 100 Гб вихідного трафіку. Машина 512 МБ RAM та 0.1 CPU).

  • Block 1 Стрічка не реагує на зміну кольору, у проміжку часу дня та комендантської години.
  • Block 0 дозволяє вмикати та вимикати стрічку в залежності від наявності електроенергії.
  • Block 3 (запускається від команди від MQTT клієнта) світлодіодна стрічка минає двічі і потім запитує у сервера поточний статус блоку щоб повернутись до 0 чи до 1.
  • Block 4 (запускається від команди від MQTT клієнта) вмикає світлодіодну стрічку. Block 4

Система складається з:

DC Mini UPS 5v 18650 (10 000 мА·год)
Фоторезистор
Node MCU ESP8266
Одноканальне реле 5V
Резистор 1 кОм
Cвітлодіодна стрічка 5V (fairy lights) — 30 м — 2 шт
Micro USB-DC кабелю для живлення ESP
Та USB A кабелю подовжувача

Arduino код на ESP8266

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// Update these with values suitable for your network.
const char* ssid = "****";
const char* password = "****";
const char* mqtt_server = "***.**.***.***";
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
unsigned long lastMsg2 = 0;
uint8_t block = 99;
void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  randomSeed(micros());
}
void callback(char* topic, byte* payload, unsigned int length) {
  if ((char)payload[0] == '0') block = 0;
  if ((char)payload[0] == '1') { block = 1; digitalWrite(D5,LOW); } 
  if ((char)payload[0] == '2') block = 2;
  if ((char)payload[0] == '3') block = 3;
}
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      client.subscribe("moonlight/block");
      while (block == 99)
      {   delay(500);
          client.publish("moonlight/wakeup", "wakeup");
          client.loop();
      }
    } else {
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
void setup() {
  pinMode(D5, OUTPUT);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}
void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  unsigned long now = millis();
  if (now - lastMsg > 250) {
    lastMsg = now;
    if (block == 0){ // Розблокувати і вмикати відносно значання A0
        
        if (analogRead(A0)>590)
        {
          digitalWrite(D5,HIGH);
        }else
        {
          digitalWrite(D5,LOW);
        }
        
    }
    if (block == 2){ // мигнути
        digitalWrite(D5,HIGH);
        delay(500);
        digitalWrite(D5,LOW);
        delay(500);
        digitalWrite(D5,HIGH);
        delay(500);
        digitalWrite(D5,LOW);
        delay(500);
        client.publish("moonlight/wakeup", "wakeup");
    }
        
    if (block == 3){  // горіти
        digitalWrite(D5,HIGH);
    }
  }
  if (now - lastMsg2 > 600000) {
    lastMsg2 = now;
    client.publish("moonlight/wakeup", "wakeup");
  }
}

Python код, що запускається на сервері

#!/usr/bin/python3
import paho.mqtt.subscribe as subscribe
import paho.mqtt.publish as publish
import ephem, datetime

def datetime_to_cron(ts):
    dt = datetime.datetime.fromtimestamp(ts)
    return f"{dt.minute} {dt.hour} * * * "

x = 0.01

kyiv = ephem.city('Kiev')
obs = ephem.Observer()
obs.lat = kyiv.lat
obs.long= kyiv.long

sun = ephem.Sun()

obs.date = (datetime.datetime.now() - datetime.timedelta(days=1))

rise_time = obs.next_rising(sun)
set_time = obs.next_setting(sun)

suntime = ephem.localtime(set_time).timestamp()-ephem.localtime(rise_time).timestamp()
end     = int(ephem.localtime(rise_time).timestamp()-suntime*x)
start   = int(ephem.localtime(set_time).timestamp()+suntime*x)

def on_wakeup():
    #print("wakeup")

    global end
    global start

    # комендантська година
    if datetime.datetime.now().hour in range(5): # 00:00-4:59
        publish.single("moonlight/block", "1", hostname="localhost")
        return

    if datetime.datetime.now().timestamp() > end and datetime.datetime.now().timestamp() < start:
        publish.single("moonlight/block", "1", hostname="localhost")
    else:
        publish.single("moonlight/block", "0", hostname="localhost")

def on_change_time():
    #print("change_time")

    global end
    global start
    global obs
    global x

    obs.date = datetime.datetime.now()

    rise_time = obs.next_rising(sun)
    set_time = obs.next_setting(sun)

    suntime = ephem.localtime(set_time).timestamp()-ephem.localtime(rise_time).timestamp()
    end     = int(ephem.localtime(rise_time).timestamp()+suntime*x)
    start   = int(ephem.localtime(set_time).timestamp()-suntime*x)

    with open("/var/spool/cron/crontabs/moonlight", "w") as file1:
        file1.write(datetime_to_cron(end)+"mosquitto_pub -t moonlight/block -m 1\n")
        file1.write(datetime_to_cron(start)+"mosquitto_pub -t moonlight/block -m 0\n")

        #  комендантська година!

        file1.write("10 0 * * * mosquitto_pub -t moonlight/block -m 1\n")
        file1.write("50 4 * * * mosquitto_pub -t moonlight/block -m 0\n")

def on_req(client, userdata, message):
    if "/wakeup" in str(message.topic.encode('utf-8')):
        on_wakeup()
    if "/time" in str(message.topic.encode('utf-8')):
        on_change_time()

subscribe.callback(on_req, "moonlight/#", hostname="localhost", userdata={"message_count": 0})
👍ПодобаєтьсяСподобалось9
До обраногоВ обраному2
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

ESP, сервер, повербанк — о боже навіщо?
свинцовий аккамулятор, блок живлення і фотрорезистор на мофсет.
якщо потрібна економія то ще додати датчик руху, щоб вмикалось тільки коли реально потрібно

Вибачте за офтоп, але це так гарно 🙂 Дуже затишно виглядає під’їзд з такою підсвіткою))

а не можна було зробити все на одному фотодіоді, який би фіксував наявність сонячного світла достатньої яскравості або наявність загального освітлення достатньої ясркавості

без всяких ардуіно. розрахувати потужність блока живлення з урахування максимальної тривалості «ночі» — 16 годин
виходить, що 5000 вистачить.
Встановити його як ДБЖ і на вихідний контур вже поставити ділянку з фотодіодом, який би фіксував не діод на УПС, а наявність чи відсутність загального освітлення

ніяких ардуіно, ніяких серверів, все набагато простіше і дешевле

на цьому принципі «садові» ліхтарі з фотопанелями працюють — щось я там не бачив серверної частини

але як іграшка погратись в ардуіно — можна ще ускладнювати. додати датчики руху, наприклад

Прикольніше було б, якби кожен сходовий проліт самостійно освітлювався, коли по ньому хтось йде, за умови відсутності мережевого живлення. Правда доведеться мін по 1 геркону на проліт ставити.

ну я не сільон в харді, «датчик присутності» чи щось таке

є ж готові лампочки на акумуляторах...

Звичайно є. Але їх можуть швидко повикручувати.

Взагалі не розумію, для чого тут сервер і Wi-Fi.
Було б цікавіше, якби був датчик у квартирі, під’єднаний до розетки і посилав сигнал, коли немає світла і по датчику, при умові що немає живлення, вмикалося світло.
А взагалі, тут і датчик освітлення не потрібен, просто отримати дані із сх/зх сонця.
Датчик освітлення був би доцільний, коли живлення нема, темно і хтось йде. Але тоді їх потрібно встановлювати на кожному поверсі

P.S. є якісні лампи з датчиками і сонячними панелями. Тримають довго і світять нормально, а не як у статті. У мене такі на дворі висять. Зі США по $3 за штуку вийшло. Якщо 10 брати то біля $4 вийде.
Гадаю це навіть дешевше вийде, ніж витратив автор статті. Принаймні, точно елегантніше.
А є ще китай

Якась нездорова історія. Зарядна станція + лампочка 12в7а х (кількість поверхів) + кабель і патрони шоб то все змонтувать.

Вже пів року працює. Нормальне світло, а не як на фото вище.

Оверкілл як на мене )))

Для себе вирішив дуже просто. На розпродажі взяв декілька ліхтарів для шаф по 1 долару (як приклад www.aliexpress.com/...​t_main.108.482c1802fDZler саме той де перемикач а не кнопка)
він вмикається коли є рух і у приміщенні темно.
ставлю на підзарядку раз на місяць і то не через те що він перестав світитися

А чи не можна забити таблицю сходів/заходів для Києва у esp8266, та й по всьому? Ні сервер не треба, живлення менше.

Було вже таке питання. Трохи нижче є відповідь. А так, ми не шукаємо простих рішень.

Мені страшно за інженерію в Київстарі...

Купується Mean Well DRC-60A, підключається по інструкції до свинцевого акумулятора, вішається світлодіодна стрічка на 12 вольт, готово.

Хочеться покроїти подешевше — береться б/в APC Back-UPS CS350 або будь-що інше, що може заряжати свинцевий акумулятор в буферному режимі струмом біля 1А, вішається та сама світлодіодна стрічка.

Спадна вольт-амперна характеристика світлодіодів буде автоматично знижувати струм розряду по мірі наближення напруги до 10 вольт, заряд в буферному режимі буде тримати акумулятор зарядженим на 100% коли електрика є.

Якась автоматизація включення-виключення — якщо порахувати, ціна компонентів на цю автоматизацію тупо не окуповує ціну зекономленої електроенергії.

Ще простіше — галимий powerbank, що може або заряжати або виддавити, USB зарядка + лампа

Павербанк може не стартувати автоматично після глибокого розряду, не гарантоване рішення, яке треба тестувати. Але так, може бути ще дешевше.

Може,

треба тестувати.

та вибирати

powerbank

Дякую за ваш інтерес.
Витрати на цей проєкт:
УПС для роутера — 1000 грн (роутер + 2 стрічки)
ESP 8266 — 200 грн
Реле + фоторезистор + USB розгалужувач = 100грн
2 стрічки по 30м (для 5 поверхів). 2×170 = 340 грн
Сервер 0 грн

І того:
Живлення 2х срічок та роутера за 1640 грн.

Автоматизація потрібна не тільки власнику, а й всім жителям під’їзду.
Тому сидіти і слідкувати цілодобово ніхто не буде.

Ну, а скільки в грошах воно електроенергії споживатиме за рік роботи?

Але навіть якщо автоматизовувати, то підхід максимально дивний, для чого цілий вайфай (який ще має якось бути енергонезалежним) і сторонній сервер? RTC з таблицею сходів-заходів сонця працюватиме автономно і економічно.

Тут проблема не в грошах. Це просто цікавий проект для себе. Люди витрачають тисячі не тільки гривень на свої хобі.

Стосовно енергонезалежності, то в мене GPON гарантований до 72 годин.

RTC гарний варіант, але нудний. Хотів трохи попрацювати з MQTT як на клієнтській частині, так і на серверній. Також гарний досвід з роботою сторонніх бібліотек та їх форматами даних.

Цей топік не для вихваляння, а передачі досвіду роботи з кодом та інше бачення на проблему.
Така архітектура може згодитись не тільки в домашніх проектах, і не тільки з часом.

в мене GPON гарантований до 72 годин.

Але треба ще його роздати вайфаєм на ESP8266, а значить десь поблизу вже є ДБЖ.

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

Думаю, вибір компонентів був на основі того, що вже у автора було і не треба купувати.
Сам маю свинцеві тягові акумулятори (чорненькі), то не довговічний солюшн.

LiFePO4 прекрасно працює в буферному режимі, якщо BMS відпрацьовує по порогу, без додаткової перевірки на струм заряду.

Людина запропонувала блок живлення на 12В, вірогідно, можна накрутити до 13В. Але для зарядки літію треба хоча б 13.8В.

Підписатись на коментарі