Skip to content

mhl221135/DIY-Inverter-Battery-monitoring-and-overdischarge-protection-system-with-XH-M609-ESP32-pzem-017

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DIY Система інвертора + акумулятора + моніторинг та захист від перерозрядки з XH-M609, ESP32 та PZEM-017

Цей проект демонструє систему DIY інвертора, акумулятора та моніторингу із захистом від перерозрядки. Використовується контролер акумулятора XH-M609, DC-DC стабілізатор і енергомонітор PZEM-017, підключений до ESP32 через перетворювач RS485-to-TTL. Система включає реле, яке керує живленням інвертора, забезпечуючи автоматичне вмикання та вимикання на основі стану акумулятора.

Огляд системи

  • Контролер акумулятора XH-M609: Керує зарядом і розрядом акумулятора, а також забезпечує захист від перерозрядки. Керує реле, яке живить інвертор.
  • DC-DC стабілізатор: Перетворює напругу на стабільні 12В для керування реле.
  • PZEM-017: Моніторить електричні параметри, такі як струм, напруга та потужність. Підключений до ESP32 для збереження даних і моніторингу.
  • ESP32: Збирає дані з PZEM-017 та інтегрується з ESPHome для віддаленого моніторингу та керування.
  • Реле: Вмикає/вимикає інвертор залежно від стану акумулятора, як це контролюється XH-M609.

Особливості

  • Керування реле на основі стану акумулятора (автоматичне вмикання/вимикання інвертора).
  • Енергомоніторинг за допомогою PZEM-017.
  • Інтеграція з ESPHome для віддаленого моніторингу та керування за допомогою настроюваних конфігурацій.
  • Modbus комунікація для налаштування діапазону струму системи на основі використовуваного шунта.

Схема підключень

Схема підключень

Фрагмент коду для конфігурації ESPHome

Наступний код YAML використовує бібліотеку pzemdc для ESPHome і забезпечує зв'язок з PZEM-017:

esphome:
  name: agm-bms
  platform: ESP32
  board: lolin32

wifi:
  networks:
    - ssid: "ssidname"
      password: "passwordforwifi"

captive_portal:

ota:
  platform: esphome
  password: "optionalpassword"  

logger:

web_server:
  port: 80

uart:
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 9600

sensor:
  - platform: uptime
    name: "Uptime"
    update_interval: 5s

  - platform: wifi_signal
    name: "WiFi strenght"
    update_interval: 5s

  - platform: pzemdc
    address: 0x01 # Адреса пристрою pzemdc
    voltage:
      name: "DC-Voltage"
      id: DC_Voltage
      accuracy_decimals: 3
    current:
      name: "DC-Current"
      id: DC_Current
      accuracy_decimals: 3
    power:
      name: "DC-Power"
      id: DC_Power
      accuracy_decimals: 2
    energy:
      name: "DC-Energy"
      id: DC_Energy
      accuracy_decimals: 3
    id: pzemdc_1
    update_interval: 1s

  # Датчик відсотка заряду акумулятора
  - platform: template
    name: "Battery SOC %"
    id: Battery_Percentage
    lambda: |-
      if (id(DC_Voltage).state < 10.5) return 0.0;
      if (id(DC_Voltage).state > 12.9) return 100.0;
      return (id(DC_Voltage).state - 10.5) / (12.9 - 10.5) * 100.0;
    unit_of_measurement: "%"
    accuracy_decimals: 1

button:
  - platform: template
    name: "Reset energy count"
    icon: "mdi:restart"
    id: pzemdc_reset_energy
    on_press:
      then:
        - pzemdc.reset_energy: pzemdc_1

Наступний код YAML використовує лише Modbus для зв'язку з PZEM-017 замість бібліотеки pzemdc для ESPHome. Ось приклад того, як змінити діапазон струму шунта на 300A (може бути змінено залежно від використовуваного шунта):

esphome:
  name: agm-bms-modbus
  platform: ESP32
  board: lolin32

wifi:
  networks:
    - ssid: "ssidname"
      password: "passwordforwifi"

captive_portal:

ota:
  platform: esphome
  password: "optionalpassword"  

logger:

web_server:
  port: 80

uart:
  id: uart4
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 9600
  stop_bits: 2

modbus:
  id: modbus1
  uart_id: uart4

modbus_controller:
  - id: modbus_device
    address: 0x01   # Адреса Modbus пристрою на шині
    modbus_id: modbus1
    setup_priority: -10

sensor:
  - platform: modbus_controller
    modbus_controller_id: modbus_device
    id: pzem_high_voltage_alarm
    name: "High Voltage Alarm Threshold"
    address: 0x0000
    unit_of_measurement: "V"
    register_type: holding
    value_type: U_WORD
    filters:
      - multiply: 0.01

  - platform: modbus_controller
    modbus_controller_id: modbus_device
    id: pzem_low_voltage_alarm
    name: "Low Voltage Alarm Threshold"
    address: 0x0001
    unit_of_measurement: "V"
    register_type: holding
    value_type: U_WORD

  - platform: modbus_controller
    modbus_controller_id: modbus_device
    id: pzem_slave_address
    name: "Slave Address"
    address: 0x0002
    unit_of_measurement: ""
    register_type: holding
    value_type: U_WORD

  - platform: modbus_controller
    modbus_controller_id: modbus_device
    id: pzem_current_range
    name: "Current Range"
    address: 0x0003
    unit_of_measurement: "A"
    register_type: holding
    value_type: U_WORD
    filters:
      - lambda: |-
          if (x == 0) return 100;
          else if (x == 1) return 50;
          else if (x == 2) return 200;
          else if (x == 3) return 300;
          else return x;

  - platform: modbus_controller
    modbus_controller_id: modbus_device
    name: "Current Range Setting"
    address: 0x0003
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "bit"

switch:
  - platform: modbus_controller
    modbus_controller_id: modbus_device
    name: "Reset Energy"
    address: 0x42
    register_type: holding
    write_lambda: |-
      return 1;

button:
  - platform: template
    name: "Set Current Range to 300A"
    on_press:
      then:
        - lambda: |-
            std::vector<uint16_t> current_range_payload = {0x0003};  // 300A значення, змінити для вашого шунта

            esphome::modbus_controller::ModbusController *controller = id(modbus_device);
            esphome::modbus_controller::ModbusCommandItem set_current_range_command =
                esphome::modbus_controller::ModbusCommandItem::create_write_single_command(controller, 0x0003, current_range_payload[0]);

            controller->queue_command(set_current_range_command);
            ESP_LOGI("ModbusLambda", "Set Current Range to 300A");

  - platform: template
    name: "Set ADRESS"
    on_press:
      then:
        - lambda: |-
            std::vector<uint16_t> current_range_payload = {0x01};  // команда зміни адреси

            esphome::modbus_controller::ModbusController *controller = id(modbus_device);
            esphome::modbus_controller::ModbusCommandItem set_current_range_command =
                esphome::modbus_controller::ModbusCommandItem::create_write_single_command(controller, 0x0002, current_range_payload[0]);

            controller->queue_command(set_current_range_command);
            ESP_LOGI("ModbusLambda", "Set ADRESS");

###############################################

DIY Inverter + Battery + Monitoring and Overdischarge Protection System with XH-M609, ESP32, and PZEM-017

This project demonstrates a DIY inverter, battery, and monitoring system with overdischarge protection. It utilizes the XH-M609 battery controller, a DC-DC stabilizer, and a PZEM-017 energy monitor connected to an ESP32 via an RS485-to-TTL converter. The system includes a relay that controls the power to the inverter, ensuring automatic power-on and power-off based on battery status.

System Overview

  • XH-M609 Battery Controller: Manages battery charging, discharging, and provides overdischarge protection. It controls the relay that powers the inverter.
  • DC-DC Stabilizer: Converts voltage to a stable 12V for relay control.
  • PZEM-017: Monitors electrical parameters like current, voltage, and power. It is connected to the ESP32 for data logging and monitoring.
  • ESP32: Collects data from the PZEM-017 and integrates with ESPHome for remote monitoring and control.
  • Relay: Powers the inverter on/off depending on the battery status as monitored by the XH-M609 controller.

Features

  • Relay control based on battery state (automatically powers on/off the inverter).
  • Energy monitoring with PZEM-017.
  • ESPHome integration for remote monitoring and control via customizable configuration.
  • Modbus communication for adjusting the current range of the system based on the shunt used.

Wiring Diagram

Wiring Diagram

Code Snippet for ESPHome Configuration

The following YAML code use pzemdc esphome library and comunicate with pzem017

esphome:
  name: agm-bms
  platform: ESP32
  board: lolin32

wifi:
  networks:
    - ssid: "ssidname"
      password: "passwordforwifi"

captive_portal:

ota:
  platform: esphome
  password: "optionalpassword"  

logger:


web_server:
  port: 80


uart:
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 9600

sensor:
  - platform: uptime
    name: "Uptime"
    update_interval: 5s

  - platform: wifi_signal
    name: "WiFi strenght"
    update_interval: 5s

  - platform: pzemdc
    address: 0x01 #adress of pzemdc device 
    voltage:
      name: "DC-Voltage"
      id: DC_Voltage
      accuracy_decimals: 3
    current:
      name: "DC-Current"
      id: DC_Current
      accuracy_decimals: 3
    power:
      name: "DC-Power"
      id: DC_Power
      accuracy_decimals: 2
    energy:
      name: "DC-Energy"
      id: DC_Energy
      accuracy_decimals: 3
    id: pzemdc_1
    update_interval: 1s

  # Battery Percentage Sensor
  - platform: template
    name: "Battery SOC %"
    id: Battery_Percentage
    lambda: |-
      if (id(DC_Voltage).state < 10.5) return 0.0;
      if (id(DC_Voltage).state > 12.9) return 100.0;
      return (id(DC_Voltage).state - 10.5) / (12.9 - 10.5) * 100.0;
    unit_of_measurement: "%"
    accuracy_decimals: 1

button:
  - platform: template
    name: "Reset energy count"
    icon: "mdi:restart"
    id: pzemdc_reset_energy
    on_press:
      then:
        - pzemdc.reset_energy: pzemdc_1

The following YAML code use just modbus for comunication with pzem017 instead of esphome pzemdc library here you can see how to change schunt current range to 300A (adjustable based on the shunt value in use):

esphome:
  name: agm-bms-modbus
  platform: ESP32
  board: lolin32

wifi:
  networks:
    - ssid: "ssidname"
      password: "passwordforwifi"

captive_portal:

ota:
  platform: esphome
  password: "optionalpassword"  

logger:

web_server:
  port: 80

uart:
  id: uart4
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 9600
  stop_bits: 2

modbus:
  id: modbus1
  uart_id: uart4

modbus_controller:
  - id: modbus_device
    address: 0x01   # Address of the Modbus slave device on the bus
    modbus_id: modbus1
    setup_priority: -10

sensor:
  - platform: modbus_controller
    modbus_controller_id: modbus_device
    id: pzem_high_voltage_alarm
    name: "High Voltage Alarm Threshold"
    address: 0x0000
    unit_of_measurement: "V"
    register_type: holding
    value_type: U_WORD
    filters:
      - multiply: 0.01

  - platform: modbus_controller
    modbus_controller_id: modbus_device
    id: pzem_low_voltage_alarm
    name: "Low Voltage Alarm Threshold"
    address: 0x0001
    unit_of_measurement: "V"
    register_type: holding
    value_type: U_WORD

  - platform: modbus_controller
    modbus_controller_id: modbus_device
    id: pzem_slave_address
    name: "Slave Address"
    address: 0x0002
    unit_of_measurement: ""
    register_type: holding
    value_type: U_WORD

  - platform: modbus_controller
    modbus_controller_id: modbus_device
    id: pzem_current_range
    name: "Current Range"
    address: 0x0003
    unit_of_measurement: "A"
    register_type: holding
    value_type: U_WORD
    filters:
      - lambda: |-
          if (x == 0) return 100;
          else if (x == 1) return 50;
          else if (x == 2) return 200;
          else if (x == 3) return 300;
          else return x;

  - platform: modbus_controller
    modbus_controller_id: modbus_device
    name: "Current Range Setting"
    address: 0x0003
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "bit"

switch:
  - platform: modbus_controller
    modbus_controller_id: modbus_device
    name: "Reset Energy"
    address: 0x42
    register_type: holding
    write_lambda: |-
      return 1;

button:
  - platform: template
    name: "Set Current Range to 300A"
    on_press:
      then:
        - lambda: |-
            std::vector<uint16_t> current_range_payload = {0x0003};  // 300A value change to your schunt

            esphome::modbus_controller::ModbusController *controller = id(modbus_device);
            esphome::modbus_controller::ModbusCommandItem set_current_range_command =
                esphome::modbus_controller::ModbusCommandItem::create_write_single_command(controller, 0x0003, current_range_payload[0]);

            controller->queue_command(set_current_range_command);
            ESP_LOGI("ModbusLambda", "Set Current Range to 300A");

  - platform: template
    name: "Set ADRESS"
    on_press:
      then:
        - lambda: |-
            std::vector<uint16_t> current_range_payload = {0x01};  // adress change command

            esphome::modbus_controller::ModbusController *controller = id(modbus_device);
            esphome::modbus_controller::ModbusCommandItem set_current_range_command =
                esphome::modbus_controller::ModbusCommandItem::create_write_single_command(controller, 0x0002, current_range_payload[0]);

            controller->queue_command(set_current_range_command);
            ESP_LOGI("ModbusLambda", "Set ADRESS");


About

DIY Inverter + Battery + monitoring and discharge protection system with XH-M609, ESP32, pzem-017

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published