Сторінка 1 з 1

Felicity FLA48100UG1 та інтеграція в Home Assistant

Додано: 25 квітня 2026, 16:16
bootuse
Особливості акумулятора Felicity FLA48100UG1:
  • - відсутня система Pre-discharge (використовується для заряджання конденсаторів інвертора при першому під'єднанні) (це не точно);
    - відсутній Current Limiter - функція яка обмежує струм при паралельному підключенні акумулятора якщо у них різний стан заряду;
    - має вбудований аерозольний вогнегасник;
    - вбудований DC Breaker з функцією керування та запобіжник;
    - простий алгоритм обмеження струму при заряджанні;
    - протокол Pylontech.
Для моніторингу з ПК використовується програма EDMS.

EDMSv2.zip
EDMS 2.24.0528
(19.77 МіБ) Завантажено 92 разів

Re: Felicity FLA48100UG1

Додано: 25 квітня 2026, 16:27
bootuse
В батареї є 2 комунікаційні порти, в кожному з них є RS485.
Тож один з ро'зємів можна використовувати для моніторингу в Home Assistant.

Для підключення потрібен RS485-TTL адаптер та esp32 (я використовую esp32c6 але правильну).
Живлення RS485-TTL адаптера - 5В, підключення до інвертора - лише лінії А та В (без GND).
RS485-TTL - https://s.click.aliexpress.com/e/_c3yN9U9d
esp32c6 - https://s.click.aliexpress.com/e/_c3HYdofD

RS485-USB - https://s.click.aliexpress.com/e/_c4KYqcVz

Увага! В програмі лише частина регістрів витягується, якщо потрібно ще якість регістри, то тут вже додавайте їх самостійно.
Про всяк випадок додав кілька логів Serial Port Monitor, щоб за потреби ви додали регістри які вас цікавлять.
При написанні використовував ШІ Gemini.

Код: Виділити все

substitutions:
  device_name: Felicity
  device_description: "Esphome for Felicity"
  modbus_update_interval: 10s
  tx_pin: GPIO19  
  rx_pin: GPIO20

esphome:
  name: felicityfla48100
  friendly_name: Felicity

esp32:
  board: esp32-c6-devkitm-1
  framework:
    type: esp-idf

# Enable Home Assistant API
api:
  encryption:
    key: #insert your data

ota:
  - platform: esphome
    password: #insert your data

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Rs232Battery Fallback Hotspot"
    password: "Kj9hbVNQxKzr"

captive_portal:

# Enable logging
logger:
  baud_rate: 0
  level: DEBUG
  
 uart:
  id: uart_bus
  rx_pin: ${rx_pin}
  tx_pin: ${tx_pin}
  baud_rate: 9600
  rx_buffer_size: 256
  debug:
      direction: both
      
modbus:
  id: modbus1
  uart_id: uart_bus

modbus_controller:
  - id: felicity_bms
    address: 1
    modbus_id: modbus1
    setup_priority: -10
    update_interval: 10s

sensor:
  # Напруга (Працює!)
  - platform: modbus_controller
    modbus_controller_id: felicity_bms
    name: "Battery Voltage"
    address: 4870
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "V"
    accuracy_decimals: 2
    filters:
      - multiply: 0.01

  # SOC (Працює!)
  - platform: modbus_controller
    modbus_controller_id: felicity_bms
    name: "Battery SOC"
    address: 4875
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "%"

  # 4. Температура MOSFET (Працює!)
  - platform: modbus_controller
    modbus_controller_id: felicity_bms
    name: "MOSFET Temperature"
    address: 4874
    register_type: holding
    value_type: S_WORD
    unit_of_measurement: "°C"

  # 5. Цикли (Працює!)
  - platform: modbus_controller
    modbus_controller_id: felicity_bms
    name: "Battery Cycles"
    address: 4865
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 0
    state_class: total_increasing 
    filters:
      - round: 0

  # Max Cell Voltage (Тепер точно на 4896)
  - platform: modbus_controller
    modbus_controller_id: felicity_bms
    name: "Max Cell Voltage"
    address: 4896
    id: cell_max
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "V"
    accuracy_decimals: 3
    filters:
      - multiply: 0.001

  # Min Cell Voltage (Він іде наступним після номера макс. комірки)
  - platform: modbus_controller
    modbus_controller_id: felicity_bms
    name: "Min Cell Voltage"
    address: 4898
    id: cell_min
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "V"
    accuracy_decimals: 3
    filters:
      - multiply: 0.001

  # Дельта (Різниця)
  - platform: template
    name: "Cell Delta"
    unit_of_measurement: "V"
    accuracy_decimals: 3
    lambda: |-
      return id(cell_max).state - id(cell_min).state;
    update_interval: 10s

  - platform: modbus_controller
    modbus_controller_id: felicity_bms
    name: "Battery Temp Sensor"
    address: 4902 # Це адреса відразу після Min Cell Number
    register_type: holding
    value_type: S_WORD
    unit_of_measurement: "°C"

  - platform: modbus_controller
    modbus_controller_id: felicity_bms
    name: "Battery Current"
    address: 4871
    register_type: holding
    value_type: S_WORD
    unit_of_measurement: "A"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1
      - multiply: -1.0  # Оцей рядок змінить + на -


Re: Felicity FLA48100UG1 та інтеграція в Home Assistant

Додано: 26 червня 2026, 13:14
bootuse
Якщо нема можливості підключитись по RS485, то з батареї можна зчитувати інформацію через CAN.
Для цього я використав плату Weact CAN485 - https://fas.st/xpwGa

Але по CAN можна отримувати лише частину інформації.

Код: Виділити все

# --- CAN BUS: тільки прослуховування (батарея сама шле дані щосекунди) ---
# GPIO27 = CTX (TX), GPIO26 = CRX (RX) — піни Weact CAN485
canbus:
  - platform: esp32_can
    id: can_bus
    tx_pin: GPIO27
    rx_pin: GPIO26
    can_id: 0
    bit_rate: 500kbps
    mode: LISTENONLY
    on_frame:
 
      # --- 0x351: Ліміти заряду/розряду ---
      - can_id: 0x351
        use_extended_id: false
        then:
          - lambda: |-
              if (x.size() >= 8) {
                float charge_v_limit    = ((x[1] << 8) | x[0]) * 0.1f;
                float charge_a_limit    = ((x[3] << 8) | x[2]) * 0.1f;
                float discharge_a_limit = ((x[5] << 8) | x[4]) * 0.1f;
                float discharge_v_limit = ((x[7] << 8) | x[6]) * 0.1f;
                id(charge_voltage_limit).publish_state(charge_v_limit);
                id(charge_current_limit).publish_state(charge_a_limit);
                id(discharge_current_limit).publish_state(discharge_a_limit);
                id(discharge_voltage_limit).publish_state(discharge_v_limit);
              }
 
      # --- 0x355: SOC / SOH ---
      - can_id: 0x355
        use_extended_id: false
        then:
          - lambda: |-
              if (x.size() >= 4) {
                float soc = (x[1] << 8) | x[0];
                float soh = (x[3] << 8) | x[2];
                id(battery_soc).publish_state(soc);
                id(battery_soh).publish_state(soh);
              }
 
      # --- 0x356: Напруга / Струм / Температура ---
      - can_id: 0x356
        use_extended_id: false
        then:
          - lambda: |-
              if (x.size() >= 6) {
                int16_t raw_v = (x[1] << 8) | x[0];
                int16_t raw_a = (x[3] << 8) | x[2];
                int16_t raw_t = (x[5] << 8) | x[4];
                float voltage = raw_v * 0.01f;
                float current = raw_a * 0.1f;
                float temperature = raw_t * 0.1f;
                id(battery_voltage).publish_state(voltage);
                id(battery_current).publish_state(current);
                id(battery_temperature).publish_state(temperature);
              }
 
      # --- 0x359: Прапори помилок/попереджень ---
      - can_id: 0x359
        use_extended_id: false
        then:
          - lambda: |-
              if (x.size() >= 4) {
                bool has_error   = (x[0] != 0x00) || (x[1] != 0x00);
                bool has_warning = (x[2] != 0x00) || (x[3] != 0x00);
                id(battery_error).publish_state(has_error);
                id(battery_warning).publish_state(has_warning);
              }
 
      # --- 0x35C: Дозвіл заряду/розряду (0xC0 = обидва дозволені) ---
      - can_id: 0x35c
        use_extended_id: false
        then:
          - lambda: |-
              if (x.size() >= 1) {
                bool charge_enabled    = (x[0] & 0x80) != 0;
                bool discharge_enabled = (x[0] & 0x40) != 0;
                id(charge_enabled_sensor).publish_state(charge_enabled);
                id(discharge_enabled_sensor).publish_state(discharge_enabled);
              }
 
      # --- 0x35E: Ім'я виробника (текстовий рядок) ---
      - can_id: 0x35e
        use_extended_id: false
        then:
          - lambda: |-
              std::string name(x.begin(), x.end());
              // прибираємо нульові байти в кінці рядка
              size_t pos = name.find('\0');
              if (pos != std::string::npos) name = name.substr(0, pos);
              id(manufacturer_name).publish_state(name);
 
      # --- 0x373: Min/Max напруга та температура комірок (BYD CellInfo) ---
      # ПІДТВЕРДЖЕНО: формат температури — Кельвіни (K), не 0.1°C!
      # Реальний приклад з BYD-документації: 1F 01 = 287K = 14°C.
      # Для ваших даних (2C 01 = 300K = 27°C) це збіглося з показником
      # загальної температури батареї з кадру 0x356 — гіпотеза підтверджена.
      # УВАГА: для паралельного банку з 2+ батарей це min/max ПО ВСЬОМУ БАНКУ,
      # а не для кожної батареї окремо — CAN-протокол не розрізняє окремі батареї.
      - can_id: 0x373
        use_extended_id: false
        then:
          - lambda: |-
              if (x.size() >= 8) {
                float cell_v_min = ((x[1] << 8) | x[0]) * 0.001f;
                float cell_v_max = ((x[3] << 8) | x[2]) * 0.001f;
                float cell_t_min = ((x[5] << 8) | x[4]) - 273.0f;
                float cell_t_max = ((x[7] << 8) | x[6]) - 273.0f;
                id(cell_voltage_min).publish_state(cell_v_min);
                id(cell_voltage_max).publish_state(cell_v_max);
                id(cell_temp_min).publish_state(cell_t_min);
                id(cell_temp_max).publish_state(cell_t_max);
              }
 
sensor:
  - platform: template
    name: "Battery SOC"
    id: battery_soc
    unit_of_measurement: "%"
    device_class: battery
    state_class: measurement
    accuracy_decimals: 0
 
  - platform: template
    name: "Battery SOH"
    id: battery_soh
    unit_of_measurement: "%"
    state_class: measurement
    accuracy_decimals: 0
 
  - platform: template
    name: "Battery Voltage"
    id: battery_voltage
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 2
 
  - platform: template
    name: "Battery Current"
    id: battery_current
    unit_of_measurement: "A"
    device_class: current
    state_class: measurement
    accuracy_decimals: 1
 
  - platform: template
    name: "Battery Temperature"
    id: battery_temperature
    unit_of_measurement: "°C"
    device_class: temperature
    state_class: measurement
    accuracy_decimals: 1
 
  - platform: template
    name: "Charge Voltage Limit"
    id: charge_voltage_limit
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 1
 
  - platform: template
    name: "Charge Current Limit"
    id: charge_current_limit
    unit_of_measurement: "A"
    device_class: current
    state_class: measurement
    accuracy_decimals: 1
 
  - platform: template
    name: "Discharge Current Limit"
    id: discharge_current_limit
    unit_of_measurement: "A"
    device_class: current
    state_class: measurement
    accuracy_decimals: 1
 
  - platform: template
    name: "Discharge Voltage Limit"
    id: discharge_voltage_limit
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 1
 
  # Обчислювана потужність (Вт) = напруга * струм
  - platform: template
    name: "Battery Power"
    id: battery_power
    unit_of_measurement: "W"
    device_class: power
    state_class: measurement
    accuracy_decimals: 0
    lambda: |-
      return id(battery_voltage).state * id(battery_current).state;
    update_interval: 5s
 
  - platform: template
    name: "Cell Voltage Min"
    id: cell_voltage_min
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 3
 
  - platform: template
    name: "Cell Voltage Max"
    id: cell_voltage_max
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 3
 
  - platform: template
    name: "Cell Voltage Delta"
    id: cell_voltage_delta
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 3
    lambda: |-
      return id(cell_voltage_max).state - id(cell_voltage_min).state;
    update_interval: 5s
 
  - platform: template
    name: "Cell Temperature Min"
    id: cell_temp_min
    unit_of_measurement: "°C"
    device_class: temperature
    state_class: measurement
    accuracy_decimals: 1
 
  - platform: template
    name: "Cell Temperature Max"
    id: cell_temp_max
    unit_of_measurement: "°C"
    device_class: temperature
    state_class: measurement
    accuracy_decimals: 1
 
binary_sensor:
  - platform: template
    name: "Battery Error"
    id: battery_error
    device_class: problem
 
  - platform: template
    name: "Battery Warning"
    id: battery_warning
    device_class: problem
 
  - platform: template
    name: "Charge Enabled"
    id: charge_enabled_sensor
 
  - platform: template
    name: "Discharge Enabled"
    id: discharge_enabled_sensor
 
text_sensor:
  - platform: template
    name: "Manufacturer"
    id: manufacturer_name