- Цена: 150руб
Поделюсь простенькой поделкой, которая может будет полезна кому-нибудь из читателей муськи)
Удосужился сделать контроль аккумуляторов домашнего УПС-а. Это древнючий Liebert GXT2-1500RT230, работает со свицовыми аккумуляторами, 4шт по 12В. Аккумы прицеплены уже не тяговые, а стартерные, SOLITE 65B24. Часов на 6 хватает.
Было задействовано пять копеешных платок:
ESP8266 WEMOS D1 — уже оскомину набила всем.
OLED 0.66″ SSD1306 64×48 крохотный, для оперативного контроля самый то!
ADC ADS1115 4-канальный измеритель напряжения аналог-цифра, что про него говорить)
DC-DC XL7015 вообще массовка… ну не совсем)
INA219 тоже ADC, только серьезно специализированный, для блоков питания, уже три раза обозревался.
монтажная плата, провода, канифоль, припой, паяльник — да что-ж такое, все куплено на алишке!
Реализовано в лучших традициях «очумелых ручек»)))
Все это запущено в надстройке ESPHome на базе Home Assistant, который живет на Raspberry Pi 4.
В целом, меня Home Assistant устраивает. Народ всякие междумордия лепят, хабы, шлюзы, сценарии и др и пр. По мне, свешивая все на центральный модуль, весьма понижаем надежность, но не об этом сегодня речь. Я только добавил информации.
ESP8266. Почему WEMOS? Для поделок самый то. УСБ есть для побыстрому прошить, запитать. Стаб 3.3В есть. На маленькие брэд-борды встает норм. Еще этажеркой ставится экранчик. Няшка)
Отдельная история с INA219. Почему она, а не например ACS712? Да я просто все запустил на 3.3В, а ей надо 5В.
Да и ESPHome заявляет INA219 поддержку, чего отказываться? И в целом она сильно круче — прикольно-же! Копейки стоит.
esphome.io/components/sensor/ina219.html?highlight=ina219
Запустил и удивился! Программисты сляпали на скорую руку. Результаты операций при измерении отрицательных значений тока выдавались какие-то мильоны. Еще криво насдвигали байтики и в итоге жуткая пила на графиках.
Вот тут и захотелось переделать на ACS712. Но не сдамся без боя) Может на досуге разворошу эту тему. Да! Родной шунт до 3А — мне маловато, поэтому добавил в параллель около пол метра ,75 медного провода, смотал бифиляром. Получилось 5мОм — самое то.
DC-DC XL7015 выбрана не случайно. Питать весь этот контроль от одного из аккумуляторов нельзя — будет сильная разбалансировка. Втыкаться на выход УПС-а блоком питания — как-то не спортивно) Поэтому берем со всей батареи — а это 55В. К такому высокому входному напряжению выбор DC-DC оказался весьма скудным. Тут тоже не без приключений. Купленые готовые платки при подаче на вход более 35В сразу испустили электронный дух! Купил отдельно микрашки, заменил, работает нормально. Подстроечник заменил на постоянный, так надежней.
ADS1115 обвязан по босяцки и поэтому ловит кучу шума. Зашунтировал входа кондерчиками — амплитуда помехи снизилась с 1В до 0,1В — уже терпимо. Да, знаю, это очень много. Резисторный делитель с простенькой грубой(ну очень грубой) подстройкой дает еще ошибку порядка 0,1В. Да и ладно, все равно пока это показометр))) Куплю точные резисторы и выкину подстроечники.
Аккумуляторы несколько по разному разряжаются-заряжаются, несмотря на то, что вроде из одной партии. Раз в год полный тренировочный цикл покажет слабого. Вот графики напряжения аккумуляторов при отключении сети на 2,5часа.
OLED 0.66″ SSD1306 64×48 да, крохотный, но циферки видать норм! Сделал бегущую строку непойми как. Выгорать не должно(и пофиг). В верхнем ряду по очереди напряжения батарей, в нижнем температуру и ток.
Еще прицепил DS18B20 так, формально, пусть будет — запихнул под ручку аккумулятора.
Сама ESP8266 доступна по сети и имеет свою страничку
Код в ESPHome:
name: battery1
esp8266:
board: d1_mini
logger:
api:
ota:
password:
wifi:
networks:
— ssid:
password:
ap:
ssid:
password:
captive_portal:
i2c:
sda: D2
scl: D1
dallas:
— pin: GPIO14
ads1115:
— address: 0x48
sensor:
— platform: ads1115
multiplexer: ‘A0_GND’
gain: 6.144
filters:
— lambda: return x * 20;
name: «UPS battery 1»
id: UPS_battery_1
update_interval: 10s
— platform: ads1115
multiplexer: ‘A1_GND’
gain: 6.144
id: UPS_battery_2
filters:
— lambda: return x * 20 — id(UPS_battery_1).state;
name: «UPS battery 2»
update_interval: 10s
— platform: ads1115
multiplexer: ‘A2_GND’
gain: 6.144
filters:
— lambda: return x * 20 — id(UPS_battery_1).state — id(UPS_battery_2).state;
id: UPS_battery_3
name: «UPS battery 3»
update_interval: 10s
— platform: ads1115
multiplexer: ‘A3_GND’
gain: 6.144
filters:
— lambda: return x * 20 — id(UPS_battery_1).state — id(UPS_battery_2).state — id(UPS_battery_3).state;
id: UPS_battery_4
name: «UPS battery 4»
update_interval: 10s
— platform: ads1115
multiplexer: ‘A3_GND’
gain: 6.144
filters:
— lambda: return x * 20;
id: UPS_battery
name: «UPS battery»
update_interval: 10s
— platform: dallas
address: 0x7c031397792a3b28
name: «Battery Temperature»
id: Battery_Temperature
— platform: ina219
address: 0x40
shunt_resistance: 0.0049 ohm
current:
name: «INA219 Current»
id: INA219_Current
filters:
— lambda: return id(INA219_Shunt_Voltage).state / 0.0049;
power:
name: «INA219 Power»
id: INA219_Power
filters:
— lambda: return id(UPS_battery).state * id(INA219_Current).state;
bus_voltage:
name: «INA219 Bus Voltage»
id: INA219_Bus_Voltage
shunt_voltage:
name: «INA219 Shunt Voltage»
id: INA219_Shunt_Voltage
filters:
— offset: 0.00069
update_interval: 10s
— platform: wifi_signal
name: «Battery WiFi Signal Sensor»
update_interval: 60s
web_server:
port: 80
globals:
— id: coords
type: int
restore_value: no
initial_value: ‘0’
— id: length
type: int
restore_value: no
initial_value: ‘260’
interval:
— interval: 30ms
then:
lambda: |-
if (id(coords) < -(id(length))) {
id(coords) = 0;
}
else {
id(coords) -= 2;
}
font:
— file: «SFDigitalReadout.ttf»
id: sfdigital
size: 36
— file: «SFDigitalReadout.ttf»
id: sfdigital1
size: 15
display:
— platform: ssd1306_i2c
model: «SSD1306 64×48»
address: 0x3C
update_interval: 30ms
# scan: true
lambda: |-
it.printf(id(coords), 0, id(sfdigital), » %.1f %.1f %.1f %.1f «, id(UPS_battery_1).state, id(UPS_battery_2).state, id(UPS_battery_3).state, id(UPS_battery_4).state );
it.printf(id(coords), 24, id(sfdigital), » %.1f° %.3fA «, id(Battery_Temperature).state, id(INA219_Current).state );