Живу в новостройке и пока тут идут ремонты, изредка, но бывает, что отключается электричество. Чтобы умный дом продолжал работать (а вместе с ним и домашний интернет), купил себе мобильный UPS на AliExpress и немного его доработал.
У безымянного устройства (у меня 18 ваттная младшая модель) следующие характеристики:
Емкость: 10400 мАч
Входное напряжение: AC85–265В 50/60 Гц
Выход: USB 5В 2A
Выход: 5В 1A, 9В 1A, 12В 1A
Выход POE: 15В 0.6А, 24В 0.6А
Обзоры на это устройство можно найти в сети.
Итак, дано:
Роутер Archer AX53 (питание 12В)
Абонентский терминал SNR ONU-EPON-1G-mini (питание 12В)
Raspberry Pi4 (питание USB)
Именно эти устройства я запланировал подключить через этот ИБП.
Вся слаботочка у меня находится на антресольной полке и чтобы, например, перезагрузить RPi4 или роутер приходится ставить стремянку, неудобно.
Решено было доработать устройство: первое чтобы UPS сообщал о своем уровне заряда и статус подключения к сети 220В, второе это возможность перезагружать по внешнему сигналу подключенное к USB выходу устройство, в моем случае - Raspberry Pi4 с установленным на нем умным домом, если вдруг он зависнет.
В заначке у меня нашлось: wemos d1 mini - будущие мозги, Pololu LV - микро цифровая кнопка, hw-384 - dc dc преобразователь, DHT11 - датчик температуры и влажности.
Использовал комплектующие, которые уже были у меня в наличии, поэтому некоторые подключения могут быть не совсем верными (без подтягивающих резисторов и фильтрующих конденсаторов). Возможно можно было использовать другие датчики и реле для отключения USB, вместо DCDC преобразователя использовать простой USB разъем. Но имеем, что имеем.
Спасибо нашим китайским друзьям, которые оставили нераспаенный разъем со всеми нужными сигналами от UPS (снизу вверх): Земля, питание 3.3 В, D25 - сигнал со светодиода 25%; W50, C75, 100 - сигнал со светодиодов 50%, 75%, 100% соответственно. R - красный светодиод, сигнал об отсутствии сети 220В, G - зеленый светодиод, сигнал о наличии 220В.
Первым делом выкидываем плату PoE-инжектора (она мне все равно не нужна, нет таких устройств), на его место отлично встает wemos d1:
Пропилил отверстие для будущего нового управляемого USB разъема:
Припаял сигнальные провода к основной плате:
И все вместе в сборке:
Принципиальная схема проапгреженного устройства:
Схема очень простая: Wemos питается от главной платы напряжением 3.3В, инвертированные сигналы 25%-100% и Red передаются на вход микрокомпьютера и считываются с определённой периодичностью. Питанием 8В (раньше туда подключался инжектор PoE) поступает на вход цифрового микровыключателя Pololu LV и через управляющий сигнал Cntrl включает или выключает свои мосфеты, соответственно подавая 8В на вход DC-DC преобразователя hw-384 (на выходе USB получаем 5В). Ну и еще подключен цифровой датчик температуры и влажности DHT11 (на всякий пожарный), у которого, для уменьшения толщины, я снял корпус и приклеил поверх аккумуляторов.
При обращении по IP адресу устройства можно посмотреть его состояние и вручную "перезагрузить" подключенное к новому USB разъему устройство. Так же эти данные рассылаются по протоколу MQTT в умный дом.
Также устройством можно управлять через телеграм бот.
Полный код для управления UPS
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <PubSubClient.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <UniversalTelegramBot.h>
const char* ssid = "ВАШАСЕТЬ"; // Имя вашей Wi-Fi сети
const char* password = "ПАРОЛЬWIFI"; // Пароль для вашей Wi-Fi сети
const char* mqttServer = "IP"; // IP-адрес MQTT-сервера
const char* mqttUsername = "mqtt"; // Логин MQTT-сервера
const char* mqttPassword = "mqtt"; // Пароль MQTT-сервера
const char* mqttClientID = "ups"; // Идентификатор клиента MQTT
const char* mqttTopic = "battery/charge"; // Топик MQTT для публикации данных о батарее
const char* mqttTopicH = "battery/health"; // Топик MQTT для публикации данных о температуре
const int mqttPort = 1883; // Порт MQTT-сервера
const char* botToken = "TOKEN"; // Токен для телеграм бота
const char* chatId = "CHATID"; // чат бота
const unsigned long BOT_MTBS = 1000; // интервал обработки сообщений от бота
unsigned long botLasttime;
#define DHTPIN D4 // Пин, к которому подключен датчик DHT11
#define DHTTYPE DHT11 // Тип датчика DHT
const int batteryPin1 = D1; // Пин входа для первого инвертированного сигнала 25%
const int batteryPin2 = D2; // Пин входа для второго инвертированного сигнала 50%
const int batteryPin3 = D5; // Пин входа для третьего инвертированного сигнала 70%
const int batteryPin4 = D6; // Пин входа для четвертого инвертированного сигнала 100%
const int noPowerPin = D7; // Пин входа для сигнала об отсутствии напряжения 220В
const int outputPin = D8; // Пин вывода для отправки сигнала отключения линии USB
int battery=0;
bool noPower=false;
unsigned int unsuccessfullAttempts = 0;
float humidity;
float temperature;
const int maxAttempt = 25;
const unsigned long MQTT_SEND_INTERVAL = 8000;
unsigned long previousMillis = 0;
X509List cert(TELEGRAM_CERTIFICATE_ROOT);
WiFiClientSecure secureClient;
WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE);
ESP8266WebServer server(80);
UniversalTelegramBot bot(botToken, secureClient);
// перезагрузка устройства (прерывание питания USB) через Pololu Switch LV
void restartUSBdevice() {
String html = "<html><head><meta charset=\"utf-8\"></head><body>";
html += "Идет перезагрузка USB устройства...</body>";
bot.sendMessage(chatId, "Идет перезагрузка устройства подключенного к USB", "");
digitalWrite(outputPin, LOW);
delay(2000);
digitalWrite(outputPin, HIGH);
server.sendHeader("Location", String("/"), true);
server.send( 302, "text/html", html);
}
// обработка сообщений от Телеграм бота
void handleNewMessages(int numNewMessages)
{
for (int i = 0; i < numNewMessages; i++){
String chat_id = bot.messages[i].chat_id;
String text = bot.messages[i].text;
if (bot.messages[i].type == "callback_query"){
text = bot.messages[i].text;
}
if (text == "/health") {
String text = "Состояние UPS:\n";
if (noPower) text +="Сеть 220 отсутствует\n";
else text +="Сеть 220 подключена\n";
text +="Уровень заряда - "+String(battery)+"%\n";
text +="Температура - "+String(temperature)+"\n";
text +="Влажность - "+String(humidity)+"%";
bot.sendMessage(chat_id, text, "Markdown");
}
if (text == "/rebootUSB"){
restartUSBdevice();
}
}
}
// Функция обработчика HTTP запроса
void handleRoot() {
String html = "<html><head><meta charset=\"utf-8\"><meta http-equiv=\"refresh\" content=\"15\"></head><title>Умный UPS</title><body>";
html += "<h3>Уровень заряда:</h1>";
html += "<p>" + String(battery) + "%</p>";
if (noPower){
html += "<h3 style=\"color:red;\">Нет сети 220В</h3>";
}
if (unsuccessfullAttempts>0)
html += "<h3>Попытка " + String(unsuccessfullAttempts) + " соединиться с MQTT</h3>";
else
html += "<h3>Соединение с MQTT OK</h3>";
html += "<p>Температура: " + String(temperature) + "</p>";
html += "<p>Влажность: " + String(humidity) + "</p>";
html +="<form action=\"/restart\">";
html += "<button type=\"submit\">Перезагрузить устройство подключенное к USB</button>";
html +="</form>";
html += "</body></html>";
server.send(200, "text/html", html);
}
void setup() {
pinMode(batteryPin1, INPUT); // Инвертированный вход
pinMode(batteryPin2, INPUT); // Инвертированный вход
pinMode(batteryPin3, INPUT); // Инвертированный вход
pinMode(batteryPin4, INPUT); // Инвертированный вход
pinMode(noPowerPin, INPUT); // Инвертированный вход
pinMode(outputPin, OUTPUT); // Установка пина вывода как выход
digitalWrite(outputPin, HIGH); // Включаем питание на USB
Serial.begin(115200);
delay(10);
WiFi.begin(ssid, password); // Подключение к Wi-Fi сети
secureClient.setTrustAnchors(&cert);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("Connected to WiFi!");
Serial.print("Retrieving time: ");
configTime(0, 0, "pool.ntp.org"); // get UTC time via NTP
time_t now = time(nullptr);
while (now < 24 * 3600)
{
Serial.print(".");
delay(100);
now = time(nullptr);
}
Serial.println(now);
server.on("/", handleRoot);
server.on("/restart", restartUSBdevice);
server.begin();
client.setServer(mqttServer, mqttPort);
bot.sendMessage(chatId, "Умный UPS запущен", "");
}
void loop() {
client.loop();
server.handleClient();
unsigned long currentMillis = millis();
// обработка вх сообщений от бота
if (currentMillis - botLasttime > BOT_MTBS) {
botLasttime = currentMillis;
int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
while (numNewMessages){
Serial.println("got response");
handleNewMessages(numNewMessages);
numNewMessages = bot.getUpdates(bot.last_message_received + 1);
}
}
// основная обработка
if (currentMillis - previousMillis > MQTT_SEND_INTERVAL) {
previousMillis = currentMillis;
if (!client.connected()) {
// Переподключение к MQTT-серверу при разрыве соединения
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect(mqttClientID, mqttUsername, mqttPassword)) {
Serial.println("connected");
unsuccessfullAttempts=0;
} else {
unsuccessfullAttempts++;
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" retrying in 5 seconds");
delay(5000);
}
}
}
//_______________________________________________________________________
//_____________________проверка уровня заряда UPS________________________
//_______________________________________________________________________
bool charge25 = !digitalRead(batteryPin1);
bool charge50 = !digitalRead(batteryPin2);
bool charge70 = !digitalRead(batteryPin3);
bool charge100 = !digitalRead(batteryPin4);
noPower = !digitalRead(noPowerPin);
char payload[50];
if (charge100) {
battery = 100;
} else if (charge70) {
battery = 70;
} else if (charge50) {
battery = 50;
} else if (charge25) {
battery = 25;
}
snprintf(payload, sizeof(payload), "{\"noPower\":\"%s\",\"battery\":%d}", noPower ? "true" : "false", battery); // Форматирование данных в формат JSON
Serial.println("Publishing data to MQTT...");
client.publish(mqttTopic, payload); // Отправка данных на MQTT-сервер
Serial.println("Data published to MQTT");
//_____________________________________________________
//________________датчик температуры___________________
//_____________________________________________________
humidity = dht.readHumidity(); // Чтение влажности
temperature = dht.readTemperature(); // Чтение температуры по Цельсию
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Failed to read from DHT sensor!");
}
Serial.println("Publishing data to MQTT...");
snprintf(payload, sizeof(payload), "{\"humidity\":%.2f,\"temperature\":%.2f}", humidity, temperature); // Форматирование данных в формат JSON
client.publish(mqttTopicH, payload); // Отправка данных на MQTT-сервер
Serial.println("Data published to MQTT");
if (unsuccessfullAttempts > maxAttempt){
String keyboardJson = "[[{ \"text\" : \"Перезагрузить USB устройство\", \"callback_data\" : \"/rebootUSB\" }]]";
bot.sendMessageWithInlineKeyboard(chatId, "Похоже, что HA не отвечает", "", keyboardJson);
}
}
}
Комментарии (41)
NikaLapka
16.07.2023 20:51+2Почему нельзя было купить, какой-нить AccordTec ББП-10 и любой 12В аккумулятор под нужный размер? Вышло бы в два раза дешевле и всё было бы хотя бы сертифицировано в соответствии с нормативными документами, а не чудо Китайской электроники с алиэкспресс.
iig
16.07.2023 20:51+1Для питания роутера от 12 В нужна специальная сертификация? ;)
Конечно, 100500 способов решения задачи можно придумать. Повербанк, DC-DC преобразователь, пара ключей и esp, как же без него в умном доме ;) А тут все в одном корпусе. Удобно.AlexanderS
16.07.2023 20:51+4Сертификация нужна чтобы ненароком не вернуться в свой сгоревший дом. Я бы тоже сильно подумал оставлять ли включенным на постоянку ИБП на литии.
red_dragon
16.07.2023 20:51Сертификация не является панацеей от пожаров, наводнений и прочих неприятностей, к сожалению. Буквально две недели назад, в конторе у нас, загорелся сертифицированный ИБП с кислотным аккумулятором (горел именно последний). И даже будучи засунутым в ведро с водой долго ещё чадил ядовитым дымом и заметно нагрел холодную воду.
AlexanderS
16.07.2023 20:51Конечно не является. Но это хоть какой-то фильтр от всякого китайского поделия, собираемого непонятно на чём и управляемого непонятно какими алгоритмами.
SpiderEkb
16.07.2023 20:51Ну вообще приличный ИБП стоит сильно дороже.
Правда, я с квартирой не сталкивался, делал у себя в доме. И он тянет куда больше чем просто роутер. Фактически - насос в скважине (работает в паре с ГА т.е. в импульсном режиме), аэратор в ЛОС (там мощность порядка 60Вт и розетки в кабинете (три ноута, два внешних монитора, роутер, коммутатор, настольные лампы, можно зарядки гаджетов подключить).
Так вот все это (инвертор с чистым синусом 3000ВА + 2 AGP АКБ 12В 100Ач + балансир для последовательно подключенных АКБ) не сказать чтобы очень бюджетно вышло.
Но надежно и тянет 6-8 часов без проблем.
jo_b1ack
16.07.2023 20:51пожалуй плюсану за ББП, свинец проверен годами, а китайский литий под напряжением не особо
xSVPx
16.07.2023 20:51+1Вскрыв десяток брендовых сертифицированных и не самых дешёвых ups могу поделиться: несмотря на бумажки это говна куски, нет ничего удивительного, что батареи служат по нескольку лет, некоторые адски перезаряжают, другие недозаряжают итд итп.
В целом "полный бардак и никакого доверия".
Боитесь обычного лития - есть lto... Но в целом при нормальных балансирах итп опасности он не представляет, особенно в виде "банок".
Kill_Voice
16.07.2023 20:51Хм, откуда там 10400? Это ж обычный повербанк с преобразователем. В целом ИБП на литиевых аккумуляторах выглядит весьма опасно, так как при скачке напряжения может и бахнуть так, что не потушите
buldo
16.07.2023 20:51В поисках готового ups на 12В на lifepo4.
Если кто знает варианты - напишите, плиз
p0isk
16.07.2023 20:51Рекомендую посмотреть на ноутбуки, у которых батарея 4s. Плюсы:
полный контроль за уровнем заряда
ёмкость батареи можно увеличть, подключив дополнительные банки
из п.1: возможность интеграции в умный дом
Минусы:
батарея на Li-Ion. Не видел ноутбуков на LiFePO4
1CHer
16.07.2023 20:51Эти батареи используются для стационарных устройств с длительным циклом работы. Ёмкость меньше чем у классических литий ионных, вес выше. В сети есть ролики переделки классического ИБП на литий железо. По идее если переделать то можно о обслуживании ИБП вообще забыть.
dephonica
16.07.2023 20:51CTECHi GT200 и старше или аналоги. Пользуюсь таким, запитан от мелкой солнечной панели, заряжает гаджеты. Если запитать от сети, то может в on-line режиме тянуть разнообразные (12V, USB QC/PD, 220 вольт синус) нагрузки до 60 (120) ватт.
buldo
16.07.2023 20:51То есть его можно считать полноценным UPS? Он точно подходит для работы 24/7?
dephonica
16.07.2023 20:51Здесь у меня статистики нет. Схемотехника в нём обычная для китайских устройств среднего уровня - стандартные DC-DC преобразователи и контроллеры USB. Если не использовать преобразователь DC/AC с его активным охлаждением, то не вижу причин, почему устройство не может работать 24/7.
p0isk
16.07.2023 20:51+2Можете посмотреть, что китайцы предлагают:
https://docs.google.com/spreadsheets/d/1WIIdczQSsjFlOcGYJvY7Nui4Ds2VxIuO/
N1Tron1X
16.07.2023 20:51Насколько такая идея в принципе реальна? Ячейка lifepo4 в заряженном состоянии выдаёт 3.65 В, т.е. 4 ячейки - 14.6 В. Оборудование скорее всего не будет против такого напряжения, я вот мозги какого-то ИБП - вполне. Есть высокая вероятность получить постоянно недозаряженные АКБ.
Лично я собрал бы такой сэтап:
-
Блок переключения питания с зарядным устройством
https://tahion.spb.ru/product/blok-pereklyucheniya-pitaniya-s-zaryadnym-ustrojstvom-bpzu-12/
-
Аккумуляторная батарея Delta HR 12-7.2 (12V / 7.2Ah)
https://www.delta-battery.ru/catalog/hr/delta-hr-12-7.2/
Ёмкость АКБ под свои нужды и кошелёк, в качестве ИБП можно найти решение под любой бюджет- дороже UPS от mini-box.com , дешевле - не имею опыта использования, советовать не буду
buldo
16.07.2023 20:51Какая разница, какое напряжение ячейки? DC/DC преобразователи же не просто так существуют.
Так-то есть батареи lifepo4 в форм-факторе свинцовых - внутри ячейки и схемы заряда и защиты.
-
Harwest
16.07.2023 20:51Raspberry Pi4 с установленным на нем умным домом, если вдруг он зависнет.
Улыбнуло про 'зависнет'.
Года три назад отказался от малинок совсем и навсегда в пользу нормальных одноплатников с еММС/SSD. Сейчас рабочий комплект работает на x64 аппарате Aaeon Up Squared, на нем же поднят LTE роутер плюс локальный файрвол плюс dnsmasq. Резервный инстанс- на Banana pi M5 4/32. Оба одноплатника тянут LMS media server c несколькими сетевыми плеерами.
foxyrus Автор
16.07.2023 20:51Отлично работает, HA установлен на внешнем SSD. Для сетевого плеера есть NAS.
randomsimplenumber
16.07.2023 20:51+1Подумалось. Мозги умного дома под бесперебойником. - это хорошо, да. И роутер тоже хорошо. Но в доме нет света, не работает котел, холодильник, комп, насос.. Чего то в этом решении не хватает.
foxyrus Автор
16.07.2023 20:51+1У меня "перерывы света" 1-5 секундные (редко до 30 минут), но вот после такого перерыва что навороченный роутер, что умный дом "поднимаются" несколько минут.
randomsimplenumber
16.07.2023 20:51Если поднимается автоматически, не вижу проблемы. Ну + лишних несколько минут без интернета.
olartamonov
16.07.2023 20:51+1Угу. Например, в середине вебинара или делового разговора.
SpiderEkb
16.07.2023 20:51Тогда инет тоже резревировать надо.
Основной канал оптика + горячий резерв LTE с направленной на вышку внешней антенной. И роутер сам должен уметь переключаться туда-сюда.
SpiderEkb
16.07.2023 20:51+1Это уже совсем другого порядка вещи. Написал выше. Там нужен нормальный мощный инвертор 3-5 КВА, с чистым синусом на входе и достаточное количество батарей (исходя из того, сколько по времени нужно поддерживать "хозяйство" и какова его суммарная мощность).
Все это для дома - да. Для квартиры может быть избыточно. И габариты там не для полочки в кладовке.
Ну и цены будут от 50тр начинаться...
anonymous
НЛО прилетело и опубликовало эту надпись здесь
foxyrus Автор
В алгоритм работы устройства я не вмешиваюсь (само по себе оно не умное), только считываю показания заряда и управляю отельным портом USB.
alexval2007
Попробуйте Аккумуляторы LiFePO4 считаются почти безопасными от пожара
foxyrus Автор
Да, посмотрел. Сварочный аппарат минимум стоит 2000 руб.
Tomatos
Дешевле нового шкафа =)
foxyrus Автор
Это да, сейчас температура на батареях, в закрытом шкафу 38.30