Skip to content

Instantly share code, notes, and snippets.

@neromatrix
Last active June 4, 2024 17:32
Show Gist options
  • Save neromatrix/6ec812f35418c4b38ebbad4e92cac888 to your computer and use it in GitHub Desktop.
Save neromatrix/6ec812f35418c4b38ebbad4e92cac888 to your computer and use it in GitHub Desktop.
# No Power Wasted 2500 V0.322 ONLY FOR TESTING !!!!
# ESPHome Software für alle gängigen Versionen des Balkonspeichers xy2500.
# Diese Version ist speziell für Verwendung mit dem Home Assistant ausgelegt und
# inkludiert die Kommunikation mit diesem, Regelung für Nulleinspeisung
# und in Zukunft einiges mehr.
# Die Kommunikation mit dem Balkonspeichers xy2500 basiert auf der Arbeit von noone2K.
# Die Hauptseite für neue Entwicklungen, Integration MQTT, openhab usw. findet ihr unter:
# https://gist.github.com/noone2k/2ddea4c9bf116aaaefb8626b064d9a41
#
# Mögen euch die Bits gnädig sein,
# neromatrix
esphome:
name: esphome-npw2500
friendly_name: No Power Wasted 2500
on_boot:
priority: 600
then:
- lambda: |-
id(npw2500_ble_disconnects).publish_state(0);
id(npw2500_wifi_disconnects).publish_state(0);
id(npw2500_api_disconnects).publish_state(0);
id(npw2500_battery_wifi_disconnects).publish_state(0);
id(npw2500_battery_control_status).publish_state("");
id(npw2500_command_sent_count).publish_state(0);
esp32:
board: esp32dev
framework:
type: esp-idf
#ota: #remove '#' to use ota
# Enable wifi
wifi:
id: npw2500_wifi
ssid: !secret wifi_ssid
password: !secret wifi_password
reboot_timeout: 0s
fast_connect: True
# Enable Home Assistant API
api:
id: api_server
# Enable logging
logger:
esp32_ble_tracker:
#web_server: #remove '#' to use web_server
# port: 80
# local: true
# js_include: "./v2/www.js"
# js_url: "/0.js"
# version: 2
ble_client:
# mac address of the batterie from secrets
mac_address: !secret battery_ble_mac
id: npw2500_ble
########## globals ##########
globals:
# - <<: !include developer/globals.yaml
# helper for npw2500_config_limit_nonpersistent_relative name
- id: npw2500_config_limit_nonpersistent_relative
type: std::string
restore_value: yes
initial_value: !secret inverter_rel_power_limit
# communication with all devices ready
- id: npw2500_communication_ready
type: bool
restore_value: no
initial_value: '0'
# communication with all devices just started
- id: npw2500_communication_started
type: bool
restore_value: no
initial_value: '0'
# response 0x03 received
- id: npw2500_response_0x03_data_ready
type: bool
restore_value: no
initial_value: '0'
# response 0x0f received
- id: npw2500_response_0x0f_data_ready
type: bool
restore_value: no
initial_value: '0'
# state for output ch1
- id: npw2500_set_output_state_ch1
type: bool
restore_value: no
initial_value: '0'
# state for output ch2
- id: npw2500_set_output_state_ch2
type: bool
restore_value: no
initial_value: '0'
# flag for pending output update
- id: npw2500_update_output_state
type: bool
restore_value: no
initial_value: 'false'
# output update enabled
- id: npw2500_enable_output_control
type: bool
restore_value: no
initial_value: 'false'
# use gridsensor for home consumption
- id: npw2500_enable_gridsensor
type: bool
restore_value: no
initial_value: 'true' #set to false, if you have no valid grid sensor in secrets.yaml
########## text_sensors ##########
text_sensor:
# - <<: !include developer/text_sensor.yaml
# should report NPW Version, does not work
- platform: version
id: npw2500_version
name: No Power Wasted 2500
hide_timestamp: true
# reports the internal PowerZero Status
- platform: template
id: npw2500_powerzero_status
name: PowerZero Status
# reports the Battery Control Status
- platform: template
id: npw2500_battery_control_status
name: PowerZero Battery Control Status
########## binary_sensors ##########
binary_sensor:
# - <<: !include developer/binary_sensor.yaml
# Bluetooth connected
- platform: template
name: ESP Ble connected
id: npw2500_ble_connected
on_state:
- lambda: |-
static bool ble_first_started = true;
if(!x && !ble_first_started) id(npw2500_ble_disconnects).publish_state(id(npw2500_ble_disconnects).state + 1);
else ble_first_started = false;
# Wifi connected
- platform: template
name: ESP Wifi connected
id: npw2500_wifi_connected
on_state:
- lambda: |-
static bool wifi_first_started = true;
if(!x && !wifi_first_started) id(npw2500_wifi_disconnects).publish_state(id(npw2500_wifi_disconnects).state + 1);
else wifi_first_started = false;
# HA Api connected
- platform: template
name: ESP HA connected
id: npw2500_api_connected
on_state:
- lambda: |-
static bool api_first_started = true;
if(!x && !api_first_started) id(npw2500_api_disconnects).publish_state(id(npw2500_api_disconnects).state + 1);
else api_first_started = false;
# Battery connected to Wifi
- platform: template
name: Battery WiFi connected
id: npw2500_battery_wifi
on_state:
- lambda: |-
if(!x) id(npw2500_battery_wifi_disconnects).publish_state(id(npw2500_battery_wifi_disconnects).state + 1);
# Input Ch1 active
- platform: template
name: Input Ch1 active
id: npw2500_input_ch1_active
# Input Ch2 active
- platform: template
name: Input Ch2 active
id: npw2500_input_ch2_active
# Input Ch1 transparent - Passthrough active/inactive
- platform: template
name: Input Ch1 transparent
id: npw2500_input_ch1_transparent
# Input Ch2 transparent - Passthrough active/inactive
- platform: template
name: Input Ch2 transparent
id: npw2500_input_ch2_transparent
# Output Ch1 active - does not show status in Passthrough Modus
- platform: template
name: Output Ch1 active
id: npw2500_output_ch1_active
# Output Ch1 power out flow
- platform: template
name: Output Ch1 Power Flow
id: npw2500_output_ch1_power_flow
# Output Ch2 power out flow
- platform: template
name: Output Ch2 Power Flow
id: npw2500_output_ch2_power_flow
# Output Ch2 active - does not show status in Passthrough Modus
- platform: template
name: Output Ch2 active
id: npw2500_output_ch2_active
# Battery connected to MQTT
- platform: template
name: Battery MQTT connected
id: npw2500_battery_mqtt
# Status of Passthrough switch
- platform: template
name: PassThrough active
id: npw2500_passthrough_active
# PowerZero enabled/disabled
- platform: template
name: PowerZero active
id: npw2500_zeropower_active
# OpenDTU status of inverter producing
- platform: homeassistant
name: PowerZero Inverter producing
id: npw2500_powerzero_inverter_producing
entity_id: !secret inverter_producing
internal: false
########## sensors ##########
sensor:
# - <<: !include developer/sensor.yaml
- platform: template
name: Command sent count
id: npw2500_command_sent_count
internal: true
accuracy_decimals: 0
# Battery Input Power (Ch1 + Ch2)
- platform: template
name: Input Power
id: npw2500_input_power
unit_of_measurement: W
device_class: power
icon: mdi:solar-power
accuracy_decimals: 0
# Battery Input Power Ch1
- platform: template
name: Input Ch1 Power
id: npw2500_input_power_ch1
unit_of_measurement: W
device_class: power
accuracy_decimals: 0
# Battery Input Power Ch2
- platform: template
name: Input Ch2 Power
id: npw2500_input_power_ch2
unit_of_measurement: W
device_class: power
accuracy_decimals: 0
# Battery Ouput Power (Ch1 + Ch2)
- platform: template
name: Output Power
id: npw2500_output_power
unit_of_measurement: W
device_class: power
accuracy_decimals: 0
# Battery Ouput Power Ch1
- platform: template
name: Output Power Ch1
id: npw2500_output_power_ch1
unit_of_measurement: W
device_class: power
accuracy_decimals: 0
# Battery Ouput Power Ch2
- platform: template
name: Output Power Ch2
id: npw2500_output_power_ch2
unit_of_measurement: W
device_class: power
accuracy_decimals: 0
# Battery InOutput Power (Input power - Output power)
- platform: template
name: Power InOut
id: npw2500_inout_power
unit_of_measurement: W
device_class: power
accuracy_decimals: 0
# Battery SOC
- platform: template
name: Battery SOC
id: npw2500_battery_soc
unit_of_measurement: '%'
device_class: battery
accuracy_decimals: 0
# Battery SOC dynamic
- platform: template
name: Battery SOC dynamic.
id: npw2500_battery_soc_dynamic
unit_of_measurement: '%'
device_class: battery
accuracy_decimals: 1
# Battery remaining capacity
- platform: template
name: Battery remaining capacity
id: npw2500_battery_remaining
unit_of_measurement: Wh
device_class: energy
accuracy_decimals: 0
# Grid Power Import
- platform: template
name: Grid Power Import
id: npw2500_grid_power_import
unit_of_measurement: W
device_class: power
accuracy_decimals: 0
internal: true
# Grid Power Export
- platform: template
name: Grid Power Export
id: npw2500_grid_power_export
unit_of_measurement: 'W'
device_class: power
accuracy_decimals: 0
internal: true
# Grid Power Export
- platform: template
name: Grid Power Average Export
id: npw2500_grid_power_avg_export
unit_of_measurement: 'W'
device_class: power
accuracy_decimals: 0
internal: false
filters:
- sliding_window_moving_average:
window_size: 35
send_every: 1
# Ha Integration import grid power
- platform: homeassistant
name: Grid Power
id: npw2500_grid_power
entity_id: !secret npw2500_grid_power
unit_of_measurement: W
device_class: power
icon: mdi:transmission-tower
accuracy_decimals: 0
internal: false
# Grid Power offset for PowerZero
- platform: template
name: Grid Power Offset
id: npw2500_grid_power_offset
unit_of_measurement: W
device_class: power
accuracy_decimals: 0
# Ha Integration openDTU Power limit rel.
- platform: homeassistant
name: openDTU Power limit rel. actual value
id: npw2500_limit_nonpersistent_relative
entity_id: !secret inverter_rel_power_limit_2
unit_of_measurement: '%'
device_class: power_factor
accuracy_decimals: 0
internal: false
# Internal sensor openDTU Power limit rel. Target value
- platform: template
name: openDTU Power limit rel. target value
id: opendtu_limit_nonpersistent_relative_target_value
unit_of_measurement: '%'
device_class: power_factor
accuracy_decimals: 0
internal: false
# Battery Temperature 1
- platform: template
name: Temperature Sensor 1
id: npw2500_temperature_1
unit_of_measurement: '°C'
device_class: temperature
accuracy_decimals: 0
# Battery Temperature 2
- platform: template
name: Temperature Sensor 2
id: npw2500_temperature_2
unit_of_measurement: '°C'
device_class: temperature
accuracy_decimals: 0
# Battery summation of Cell Voltages
- platform: template
name: Cell Voltage sum
id: npw2500_cell_vsum
unit_of_measurement: V
device_class: voltage
accuracy_decimals: 3
# Battery maximum of all Cell Voltages
- platform: template
name: Cell Voltage max
id: npw2500_cell_vmax
unit_of_measurement: V
device_class: voltage
accuracy_decimals: 3
# Battery maximumminimum of all Cell Voltages
- platform: template
name: Cell Voltage min
id: npw2500_cell_vmin
unit_of_measurement: V
device_class: voltage
accuracy_decimals: 3
# Battery average value of all Cell Voltages
- platform: template
name: Cell Voltage avg
id: npw2500_cell_vavg
unit_of_measurement: V
device_class: voltage
accuracy_decimals: 3
# Battery max difference between all Cell Voltages
- platform: template
name: Cell Voltage diff
id: npw2500_cell_vdiff
unit_of_measurement: V
device_class: voltage
accuracy_decimals: 3
# Battery Discharge threshold
- platform: template
name: Discharge threshold
id: npw2500_discharge_treshold
unit_of_measurement: '%'
device_class: power_factor
accuracy_decimals: 0
# Battery Solar Charge threshold
- platform: template
name: Solar Charge threshold
id: npw2500_solar_charge_treshold
unit_of_measurement: W
device_class: power
accuracy_decimals: 0
# Battery Software Version
- platform: template
name: Battery Version
id: npw2500_device_version
accuracy_decimals: 3
# Home Power usage
- platform: template
name: Home Power Consumption
id: npw2500_home_power_consuption
unit_of_measurement: W
device_class: 'power'
accuracy_decimals: 0
#Ble disconnects
- platform: template
name: ESP Ble disconnects
id: npw2500_ble_disconnects
accuracy_decimals: 0
# Wifi disconnects
- platform: template
name: ESP Wifi disconnects
id: npw2500_wifi_disconnects
accuracy_decimals: 0
# HA Api disconnects
- platform: template
name: ESP HA disconnects
id: npw2500_api_disconnects
accuracy_decimals: 0
# Battery disconnects to Wifi
- platform: template
name: Battery WiFi disconnects
id: npw2500_battery_wifi_disconnects
accuracy_decimals: 0
# Battery Ouput Energy Ch1
- platform: integration
name: Output Ch1 Energy Daily
id: npw2500_output_energy_ch1_daily
sensor: npw2500_output_power_ch1
unit_of_measurement: 'kWh'
state_class: total_increasing
device_class: energy
time_unit: h
accuracy_decimals: 3
integration_method: left
restore: false
filters:
- multiply: 0.001
- skip_initial: 1
- lambda: "return id(npw2500_communication_ready) ? x : 0;"
# Battery Ouput Energy Ch2
- platform: integration
name: Output Ch2 Energy Daily
id: npw2500_output_energy_ch2_daily
sensor: npw2500_output_power_ch2
unit_of_measurement: 'kWh'
state_class: total_increasing
device_class: energy
time_unit: h
accuracy_decimals: 3
integration_method: left
restore: false
filters:
- multiply: 0.001
- skip_initial: 3
- lambda: "return id(npw2500_communication_ready) ? x : 0;"
# Battery Output Energy (Ch1 + Ch2)
- platform: integration
name: Output Energy Daily
id: npw2500_output_energy_daily
sensor: npw2500_output_power
unit_of_measurement: 'kWh'
state_class: total_increasing
device_class: energy
time_unit: h
accuracy_decimals: 3
integration_method: left
restore: false
filters:
- multiply: 0.001
- skip_initial: 1
- lambda: "return id(npw2500_communication_ready) ? x : 0;"
# Battery Input Energy Ch1
- platform: integration
name: Input Ch2 Energy Daily
id: npw2500_input_energy_ch2_daily
sensor: npw2500_input_power_ch2
unit_of_measurement: 'kWh'
state_class: total_increasing
device_class: energy
time_unit: h
accuracy_decimals: 3
integration_method: left
restore: false
filters:
- multiply: 0.001
- skip_initial: 1
- lambda: "return id(npw2500_communication_ready) ? x : 0;"
# Battery Input Energy Ch1
- platform: integration
name: Input Ch1 Energy Daily
id: npw2500_input_energy_ch1_daily
sensor: npw2500_input_power_ch1
unit_of_measurement: 'kWh'
state_class: total_increasing
device_class: energy
time_unit: h
accuracy_decimals: 3
integration_method: left
restore: false
filters:
- multiply: 0.001
- skip_initial: 1
- lambda: "return id(npw2500_communication_ready) ? x : 0;"
# Battery Input Energy (Ch1 + Ch2)
- platform: integration
name: Input Energy Daily
id: npw2500_input_energy_daily
sensor: npw2500_input_power
unit_of_measurement: 'kWh'
state_class: total_increasing
device_class: energy
time_unit: h
accuracy_decimals: 3
integration_method: left
restore: false
filters:
- multiply: 0.001
- skip_initial: 1
- lambda: "return id(npw2500_communication_ready) ? x : 0;"
# Battery Energy
- platform: integration
name: Battery InOut Energy Daily
id: npw2500_inout_energy_daily
sensor: npw2500_inout_power
unit_of_measurement: 'kWh'
state_class: total
device_class: energy
time_unit: h
accuracy_decimals: 3
integration_method: left
restore: false
filters:
- multiply: 0.001
- skip_initial: 1
- lambda: "return id(npw2500_communication_ready) ? x : 0;"
# Home Energy Consumption Daily
- platform: integration
name: Home Energy Consumption Daily
id: npw2500_home_energy_daily
sensor: npw2500_home_power_consuption
unit_of_measurement: kWh
state_class: total_increasing
device_class: energy
time_unit: h
accuracy_decimals: 3
integration_method: left
restore: false
filters:
- multiply: 0.001
- skip_initial: 1
- lambda: "return id(npw2500_communication_ready) ? x : 0;"
# Grid Energy Daily
- platform: integration
name: Grid Energy Daily
id: npw_grid_energy_daily
sensor: npw2500_grid_power
unit_of_measurement: kWh
state_class: total
device_class: energy
time_unit: h
accuracy_decimals: 3
icon: mdi:transmission-tower
integration_method: left
restore: false
filters:
- multiply: 0.001
- skip_initial: 1
- lambda: "return id(npw2500_communication_ready) ? x : 0;"
# Grid Export Energy Daily
- platform: integration
name: Grid Export Energy Daily
id: npw_grid_export_energy_daily
sensor: npw2500_grid_power_export
unit_of_measurement: 'kWh'
state_class: total_increasing
device_class: energy
time_unit: h
accuracy_decimals: 3
icon: mdi:transmission-tower-import
integration_method: left
restore: false
filters:
- multiply: 0.001
- skip_initial: 1
- lambda: "return id(npw2500_communication_ready) ? x : 0;"
# Grid Import Energy Daily
- platform: integration
name: Grid Import Energy Daily
id: npw_grid_import_energy_daily
sensor: npw2500_grid_power_import
unit_of_measurement: 'kWh'
state_class: total_increasing
device_class: energy
time_unit: h
icon: mdi:transmission-tower-export
accuracy_decimals: 3
integration_method: left
restore: false
filters:
- multiply: 0.001
- skip_initial: 1
- lambda: "return id(npw2500_communication_ready) ? x : 0;"
# ESP Bluetooth client
- platform: ble_client
ble_client_id: npw2500_ble
type: characteristic
name: "npw2500Info"
id: npw2500_Info
service_uuid: 'ff00'
characteristic_uuid: 'ff02'
update_interval: never
internal: True
notify: True
lambda: |-
std::vector<char> xdata;
for (auto b : x) { xdata.push_back(b); }
id(ble_parse_response).execute(xdata);
return (float)x[0];
########## button ##########
button:
# - <<: !include developer/button.yaml
# Reset Daily Energy
- platform: template
name: Reset Daily Energy
id: npw2500_reset_daily_energy
on_press:
- script.execute:
id: reset_energy_sensors
# Restart Inverter
- platform: template
name: Restart Inverter
id: npw2500_restart_inverter
icon: mdi:restart
on_press:
- logger.log: Restart Inverter Button Pressed
- script.execute:
id: restart_inverter
# Restart ESP
- platform: restart
name: Restart ESP
id: npw2500_restart_esp
# Restart Batterie
- platform: template
name: Restart Battery
id: npw2500_restart_battery
icon: mdi:restart
on_press:
- logger.log: Restart Battery Button Pressed
- script.execute:
id: restart_battery
########## switches ##########
switch:
# - <<: !include developer/switch1.yaml
# - <<: !include developer/switch2.yaml
# - <<: !include developer/switch3.yaml
# - <<: !include developer/switch4.yaml
# Battery Enable Battery Control
- platform: template
name: Enable Battery Control
id: npw2500_enable_battery_control_switch
icon: mdi:toggle-switch
optimistic: True
restore_mode: RESTORE_DEFAULT_OFF
on_turn_on:
then:
lambda: 'id(npw2500_battery_control_status).publish_state("Battery Control enabled");'
on_turn_off:
then:
lambda: 'id(npw2500_battery_control_status).publish_state("Battery Control disabled");'
# Battery Output switch Ch1
- platform: template
name: Set Power Out Switch Ch1
id: npw2500_powerout_switch_ch1
icon: mdi:toggle-switch
optimistic: True
restore_mode: RESTORE_DEFAULT_OFF
on_turn_on:
then:
- script.execute:
id: ble_switch_powerout
on_turn_off:
then:
- script.execute:
id: ble_switch_powerout
# Battery Output switch Ch2
- platform: template
name: Set Power Out Switch Ch2
id: npw2500_powerout_switch_ch2
icon: mdi:toggle-switch
optimistic: True
restore_mode: RESTORE_DEFAULT_ON
on_turn_on:
then:
- script.execute:
id: ble_switch_powerout
on_turn_off:
then:
- script.execute:
id: ble_switch_powerout
# Battery Output switch Passtrough
- platform: template
name: Set PV2 Passtrough Switch
id: npw2500_powerout_pv2_switch
icon: mdi:toggle-switch
optimistic: True
restore_mode: RESTORE_DEFAULT_ON
on_turn_on:
then:
- script.execute:
id: ble_command
ble_cmd: 0x0D
ble_cmd_parm: 0x00
- script.wait: ble_command
on_turn_off:
then:
- script.execute:
id: ble_command
ble_cmd: 0x0D
ble_cmd_parm: 0x01
- script.wait: ble_command
# PowerZero enable
- platform: template
name: PowerZero enabled
id: npw2500_zeropower_enabled
optimistic: True
restore_mode: RESTORE_DEFAULT_OFF
# ble client enable
- platform: ble_client
ble_client_id: npw2500_ble
name: "Enable Bluetooth"
internal: False
########## numbers ##########
number:
# - <<: !include developer/number.yaml
# Slider Discharge threshold
- platform: template
name: Set Discharge threshold
id: npw2500_discharge_slider
min_value: 10
max_value: 90
step: 10
optimistic: true
initial_value : 90
restore_value : true
unit_of_measurement: '%'
device_class: 'battery'
icon: 'mdi:speedometer'
on_value:
- script.execute:
id: ble_command
ble_cmd: 0x0B
ble_cmd_parm: !lambda 'return x;'
- script.wait: ble_command
# Slider Solar Charge threshold
- platform: template
name: Set Solar Charge threshold
id: npw2500_solar_charge_slider
min_value: 0
max_value: 990
step: 10
initial_value : 990
restore_value : true
optimistic: true
unit_of_measurement: 'W'
device_class: 'energy'
icon: 'mdi:speedometer'
on_value:
- script.execute:
id: ble_command
ble_cmd: 0x0C
ble_cmd_parm: !lambda 'return int(x);'
- script.wait: ble_command
# Slider Power Limit rel.
- platform: template
name: Set Power Limit rel.
id: npw2500_powerlimit_slider
min_value: 2
max_value: 100
step: 1
initial_value: 10
restore_value: true
optimistic: true
unit_of_measurement: '%'
device_class: 'power_factor'
icon: 'mdi:speedometer'
# Slider Max Cell Voltage
- platform: template
name: Set max Cell Voltage
id: npw2500_max_cell_voltage_slider
min_value: 3.2
max_value: 3.6
step: 0.01
initial_value: 3.4
restore_value: true
optimistic: true
unit_of_measurement: 'V'
device_class: 'voltage'
icon: 'mdi:speedometer'
# Slider Set Grid Power Offset
- platform: template
name: Set Grid Power Offset
id: npw2500_power_offset_slider
min_value: -800
max_value: 200
step: 10
initial_value: 0
restore_value: true
optimistic: true
unit_of_measurement: 'W'
device_class: 'power'
icon: 'mdi:speedometer'
# - platform: homeassistant
# id: homeassistant_time
### synchronize ESP time with SNTP time
time:
- platform: sntp
id: sntp_time
timezone: Europe/Berlin
on_time_sync:
then:
- logger.log: "Synchronized system clock"
on_time:
- hours: 23
minutes: 59
seconds: 0
then:
- script.execute:
id: reset_energy_sensors
- logger.log: "Energy Sensors Reset"
########## intervals ##########
interval:
# - <<: !include developer/interval.yaml
- interval: 5 sec
then:
- logger.log: "Auf gehts..."
- lambda: |-
id(npw2500_wifi_connected).publish_state(id(npw2500_wifi).is_connected()); // publish state of wifi
id(npw2500_ble_connected).publish_state(id(npw2500_ble).connected()); // publish state of ble
id(npw2500_api_connected).publish_state(global_api_server->is_connected()); // publish state of HA Api
id(npw2500_communication_ready) = id(npw2500_wifi_connected).state && // set global npw2500_communication_ready
id(npw2500_ble_connected).state && id(npw2500_api_connected).state;
ESP_LOGD("npw2500","service HA api: %d wifi: %d ble: %d", // log values
id(npw2500_api_connected).state,id(npw2500_wifi_connected).state,id(npw2500_ble_connected).state);
- if:
condition:
lambda: 'return id(npw2500_communication_ready);'
then:
- script.execute:
id: ble_command
ble_cmd: 0x03 # Request Command 0x03
ble_cmd_parm: 0x01
- logger.log: "Request command 0x03 sent"
- delay: 1 sec
- script.execute:
id: ble_command
ble_cmd: 0x0f # Request Command 0x0f
ble_cmd_parm: 0x01
- logger.log: "Request command 0x0f sent"
- delay: 1 sec
- script.execute:
id: ble_set_outputs # Set Outputs
- interval: 10 sec # do not change time !!!
then:
- if:
condition:
lambda: 'return id(npw2500_communication_ready);'
then:
- script.execute:
id: power_zero # Call script powerzero
- interval: 10 sec # do not change time !!!
then:
- script.execute:
id: watch_task # Call script watch_task
- interval: 600 sec
then:
- script.execute:
id: check_dod # # Call script check_dod
script:
#- <<: !include developer/script1.yaml
#- <<: !include developer/script2.yaml
- id: ble_parse_response
parameters:
x: char[]
then:
lambda: |-
//ESP_LOG_BUFFER_HEXDUMP("npw2500", &x[0], x.size(), ESP_LOG_ERROR);
//### Cell parser by neromatrix ###
//### Ver. 0.4 ###
//### highlimit now from slider id(npw2500_max_cell_voltage_slider).state ###
if ((std::count (x.begin(), x.end(), '_') == 16) || (std::count (x.begin(), x.begin() + 10, '_') == 3))
{
int pos = 0;
int soc = 0;
int t1 = 0;
int t2 = 0;
float cv = 0.0;
float cmin = std::numeric_limits<float>::max();
float cmax = std::numeric_limits<float>::min();
float ct = 0.0;
int found = -1;
char delimiter = '_';
std::string xstr;
ESP_LOGD("npw2500","Parsing cell information, response of request command 0xf");
id(npw2500_response_0x0f_data_ready) = true;
xstr.assign(x.begin(), x.end()); // copy values from vector into string xstr, deep copy
xstr = xstr + delimiter; // append delimiter to xstr
found = xstr.find(delimiter); // search for position of the first delimiter
while (found != -1) // loop until no more delimiter found
{
if(pos == 0) soc = atoi( xstr.substr(0, found).c_str()); // pos 0 get int value of device SOC
if(pos == 1) t1 = atoi( xstr.substr(0, found).c_str()); // pos 1 get int value of temperature sensor 1
if(pos == 2) t2 = atoi( xstr.substr(0, found).c_str()); // pos 2 get int value of temperature sensor 2
if((pos >= 3) && (pos <= 16)) // pos 3-16 parse pos for the 14 cell voltages
{
ct = atof( xstr.substr(0, found).c_str()); // get float value of pos x
cv += ct; // add actual value to var cv
if(ct > cmax) cmax = ct; // check for higher value as stored in cmax
if(ct < cmin) cmin = ct; // check for lower value as stored in cmin
}
xstr.erase(xstr.begin(), xstr.begin() + found + 1); // remove parsed string part
found = xstr.find(delimiter); // find next delimiter
pos++; // increment pos
}
/* calculate SoC from cell voltages
cell empty = lowlimit = 0% SoC
cell full = highlimit = 100% SoC = id(npw2500_max_cell_voltage_slider).state
*/
float lowlimit = 3.0; // low voltage limit
float highlimit = id(npw2500_max_cell_voltage_slider).state ; // changed V0.4 - high voltage limit from slider
float soccalc = 100*((cv/14000)
- highlimit)/(highlimit - lowlimit) + 100; // equation of line with two points (0,lowlimit) (100,highlimit)
id(npw2500_battery_soc_dynamic).publish_state(soccalc); // id changed V0.4 - dynamic SOC calculated from cell voltages (%)
id(npw2500_temperature_1).publish_state(t1); // Temperature 1 (°C)
id(npw2500_temperature_2).publish_state(t2); // Temperature 2 (°C)
id(npw2500_cell_vsum).publish_state(cv/1000); // sum of cellvoltages = battery Voltage(V)
id(npw2500_cell_vmin).publish_state(cmin/1000); // lowest cellvoltage (V)
id(npw2500_cell_vmax).publish_state(cmax/1000); // highest cellvoltage (V)
id(npw2500_cell_vdiff).publish_state((cmax-cmin)/1000); // difference high-low (V)
id(npw2500_cell_vavg).publish_state(cv/14000); // avarage cellvoltage (V)
}
else if((x[3] == 3))
{
ESP_LOGD("npw2500","Parsing response of request command 0x3");
id(npw2500_response_0x03_data_ready) = true;
// Input power ch1
int inputpower1 = x[6] | x[7] << 8;
id(npw2500_input_power_ch1).publish_state(inputpower1);
// Input power ch2
int inputpower2 = x[8] | x[9] << 8;
id(npw2500_input_power_ch2).publish_state(inputpower2);
// Input power ch1 + ch2
id(npw2500_input_power).publish_state(inputpower1 + inputpower2);
// Output power Ch1
int outputpower1 = x[24] | x[25] << 8;
id(npw2500_output_power_ch1).publish_state(outputpower1);
// Output power Ch2
int outputpower2 = x[26] | x[27] << 8;
id(npw2500_output_power_ch2).publish_state(outputpower2);
// Output power Ch1 + Ch2
id(npw2500_output_power).publish_state(outputpower1 + outputpower2);
// Input-Output power
id(npw2500_inout_power).publish_state(inputpower1 + inputpower2 - outputpower1 - outputpower2);
//int dod_level = x[18];
id(npw2500_discharge_treshold).publish_state(x[18]);
//Solar Treshold
id(npw2500_solar_charge_treshold).publish_state(x[19] | x[20] << 8);
// Battery state of charge %
id(npw2500_battery_soc).publish_state((x[10] | x[11] << 8 ) / 10);
// Battery remaining capacity
id(npw2500_battery_remaining).publish_state(x[22] | x[23] << 8);
// update active and transparent state of input channels
if( x[4] == 0x00 ) { id(npw2500_input_ch1_active).publish_state(false); id(npw2500_input_ch1_transparent).publish_state(false); }
if( x[4] == 0x01 ) { id(npw2500_input_ch1_active).publish_state(true); id(npw2500_input_ch1_transparent).publish_state(false); }
if( x[4] == 0x02 ) { id(npw2500_input_ch1_active).publish_state(true); id(npw2500_input_ch1_transparent).publish_state(true); }
if( x[5] == 0x00 ) { id(npw2500_input_ch2_active).publish_state(false); id(npw2500_input_ch2_transparent).publish_state(false); }
if( x[5] == 0x01 ) { id(npw2500_input_ch2_active).publish_state(true); id(npw2500_input_ch2_transparent).publish_state(false); }
if( x[5] == 0x02 ) { id(npw2500_input_ch2_active).publish_state(true); id(npw2500_input_ch2_transparent).publish_state(true); }
//device software version
float dev_version = x[12];
id(npw2500_device_version).publish_state(dev_version / 100);
// Passthrough stateS
id(npw2500_passthrough_active).publish_state(x[13] == 0);
// update output channels state
if( x[15] == 0x00 ) { id(npw2500_battery_wifi).publish_state(false); id(npw2500_battery_mqtt).publish_state(false); }
if( x[15] == 0x01 ) { id(npw2500_battery_wifi).publish_state(true); id(npw2500_battery_mqtt).publish_state(false); }
if( x[15] == 0x02 ) { id(npw2500_battery_wifi).publish_state(true); id(npw2500_battery_mqtt).publish_state(true); }
if( x[15] == 0x03 ) { id(npw2500_battery_wifi).publish_state(true); id(npw2500_battery_mqtt).publish_state(false); }
ESP_LOGD("npw2500","wifi state = %d ", x[15]);
if( x[16] == 0x00 ) { id(npw2500_output_ch1_active).publish_state(false);}
if( x[16] == 0x01 ) { id(npw2500_output_ch1_active).publish_state(true); }
if( x[17] == 0x00 ) { id(npw2500_output_ch2_active).publish_state(false);}
if( x[17] == 0x01 ) { id(npw2500_output_ch2_active).publish_state(true); }
}
else
{
ESP_LOG_BUFFER_HEXDUMP("npw2500", &x[0], x.size(), ESP_LOG_ERROR);
}
# set ouputs synchronized with other ble commands
- id: ble_set_outputs
then:
lambda: |-
int act_ble_cmd =0;
if( id(npw2500_enable_output_control) && id(npw2500_enable_battery_control_switch).state &&
( (id(npw2500_set_output_state_ch1) != id(npw2500_output_ch1_active).state ) ||
(id(npw2500_set_output_state_ch2) != id(npw2500_output_ch2_active).state)) && id(npw2500_update_output_state))
{
if ( ! id(npw2500_set_output_state_ch1) && ! id(npw2500_set_output_state_ch2)) { act_ble_cmd = 0x00; }
if ( id(npw2500_set_output_state_ch1) && ! id(npw2500_set_output_state_ch2)) { act_ble_cmd = 0x01; }
if ( ! id(npw2500_set_output_state_ch1) && id(npw2500_set_output_state_ch2)) { act_ble_cmd = 0x02; }
if ( id(npw2500_set_output_state_ch1) && id(npw2500_set_output_state_ch2)) { act_ble_cmd = 0x03; }
if(act_ble_cmd !=0)
{ // do not allow setting both outputs to zero
id(ble_command).execute(0x0E, act_ble_cmd); // synchronized with other automatic sent ble commands
ESP_LOGD("npw2500","ble_switch_out_set_state output changed");
}
id(npw2500_update_output_state) = false; // reset global update flag
ESP_LOGD("npw2500","npw2500_powerout_switch cmd = %d ", act_ble_cmd);
}
# get the position of the output switches and calculate the ble_cmd to be sent
# for updating the battery switch states.
- id: ble_switch_powerout
then:
- lambda: |-
if(id(npw2500_communication_ready))
{
int ble_cmd = 0x00;
if ( ! id(npw2500_powerout_switch_ch1).state && ! id(npw2500_powerout_switch_ch2).state ) { ble_cmd = 0x00; }
if ( id(npw2500_powerout_switch_ch1).state && ! id(npw2500_powerout_switch_ch2).state ) { ble_cmd = 0x01; }
if ( ! id(npw2500_powerout_switch_ch1).state && id(npw2500_powerout_switch_ch2).state ) { ble_cmd = 0x02; }
if ( id(npw2500_powerout_switch_ch1).state && id(npw2500_powerout_switch_ch2).state ) { ble_cmd = 0x03; }
id(ble_command).execute(0x0E, ble_cmd);
ESP_LOGD("npw2500","npw2500_powerout_switch cmd = %d ", ble_cmd);
}
else
ESP_LOGD("npw2500","ble_switch_powerout Communication not ready");
# Script for sending ble commands to battery
- id: ble_command
#mode: queued
parameters:
ble_cmd: int
ble_cmd_parm: int
then:
- if:
condition:
lambda: 'return id(npw2500_communication_ready);'
then:
- lambda: 'ESP_LOGD("NPW2500","ble_command cmd = %d parm = %d" ,ble_cmd, ble_cmd_parm); '
- ble_client.ble_write:
id: npw2500_ble
service_uuid: 'ff00'
characteristic_uuid: 'ff01'
value: !lambda |-
int rlen = 0;
int rxor = 0;
std::vector<unsigned char> rdat1{ 0x73,0x06,0x23,(unsigned char)ble_cmd};
if (ble_cmd == 0x0C) {
rdat1.push_back((uint8_t)((ble_cmd_parm >> 0) & 0xFF));
rdat1.push_back((uint8_t)((ble_cmd_parm >> 8) & 0xFF));
} else {
rdat1.push_back((unsigned char)ble_cmd_parm);
}
rlen = rdat1.size();
rdat1.at(1) = rlen+1;
for (int i=0;i<rlen;i++) {
rxor = rxor ^ rdat1[i];
}
rdat1.push_back(rxor);
return rdat1;
else:
- lambda: 'ESP_LOGE("NPW2500","ble_command Communication not ready"); '
#####################################################################
### PowerZero Nulleinspeisung - by neromatrix ###
### Ver. 0.3 ###
## Now includes ChargeControl for ###
### loadvoltage preregulation ###
#####################################################################
- id: power_zero
then:
- lambda: |-
if(id(npw2500_zeropower_enabled).state && id(npw2500_communication_ready) &&
id(npw2500_response_0x03_data_ready) && id(npw2500_response_0x0f_data_ready))
{
int dtu_limit_min_value = 2;
int dtu_limit_max_value = id(npw2500_powerlimit_slider).state;
int dtu_limit_calculated_value = dtu_limit_min_value;
int dtu_max_power = 800;
int grid_to_dtu_limit_npr_ratio = dtu_max_power / 50;
int grid_power_offset_target_value = id(npw2500_power_offset_slider).state;
int dtu_max_slew_rate = 40;
int send_every_number_of_cycles = 6;
bool use_slewrate_limiter = 0;
std::string powerzero_status = "";
static int grid_power_offset_old_value = id(npw2500_power_offset_slider).state;
static int dtu_old_limit_value = dtu_limit_min_value;
static int grid_old_power_value = 100;
static int cycle_counter = 0;
// ************************* NPW ChargeControl ***********************************
// Inputs
float cell_voltage_target_value = id(npw2500_max_cell_voltage_slider).state;
float cell_vmax_act_value = id(npw2500_cell_vmax).state;
float cell_voltage_diff_to_power_ratio = 8000; // cell voltage difference to grid power ratio factor
// Outputs // factor 8000 enables soft regulation
int grid_power_offset_act_value = id(npw2500_power_offset_slider).state;
// Local
int grid_power_offset_new_value = id(npw2500_power_offset_slider).state;
float cell_vmax_diff = cell_vmax_act_value - cell_voltage_target_value; // calculate difference
if(id(npw2500_response_0x0f_data_ready)) // sanity check of response 0x0f
{
if((cell_vmax_act_value > cell_voltage_target_value)) // actual cell voltage higher then traget value
{ // calculate grid power offset for PowerZero
grid_power_offset_new_value = grid_power_offset_old_value - cell_vmax_diff * cell_voltage_diff_to_power_ratio;
grid_power_offset_act_value = round(( id(npw2500_power_offset_slider).state + grid_power_offset_new_value)/2);
powerzero_status = "Loadregulation";
}
else
{
if(cell_vmax_act_value < cell_voltage_target_value) // actual cell voltage lower then traget value
{
if(grid_power_offset_act_value != grid_power_offset_target_value)
{ // calculate grid power offset for PowerZero
grid_power_offset_act_value = round(( id(npw2500_power_offset_slider).state - grid_power_offset_old_value)/2);
}
if(id(npw2500_inout_power).state > 0)
powerzero_status = "Charge";
else
powerzero_status = "Discharge";
}
}
// Limit grid_power_offset_act_value to +- dtu_max_power
if(grid_power_offset_act_value > dtu_max_power) grid_power_offset_act_value = dtu_max_power;
if(grid_power_offset_act_value < - dtu_max_power) grid_power_offset_act_value = - dtu_max_power;
grid_power_offset_old_value = grid_power_offset_act_value;
}
else
ESP_LOGD("npw2500", "NPW Charge control - Cell data not available");
// ************************* End NPW ChargeControl ***************************
// ************************* NPW PowerZero ***********************************
int grid_actual_power_value = int(id(npw2500_grid_power).state);
//limit max grid power
int power_limit = 50000; // enable max +/-50KW grid power
if(abs(grid_actual_power_value) > power_limit) // also filters out HA sensor status message with value of INT_MAX on start
{
if(grid_actual_power_value != INT_MAX)
ESP_LOGE("npw2500", "Grid Power out of limit %d > %d" ,int(grid_actual_power_value),power_limit);
grid_actual_power_value = 0;
}
// calculate new dtu limit
dtu_limit_calculated_value = ((grid_actual_power_value - grid_power_offset_act_value ) / grid_to_dtu_limit_npr_ratio ) + dtu_old_limit_value ;
if(dtu_limit_calculated_value > dtu_limit_max_value) dtu_limit_calculated_value = dtu_limit_max_value; // limit dtu_limit upper limit to dtu_max_value
if(dtu_limit_calculated_value < dtu_limit_min_value) dtu_limit_calculated_value = dtu_limit_min_value; // limit dtu_limit lower limit to dtu_min_value
grid_old_power_value = grid_actual_power_value; //save dtu limit
ESP_LOGD("npw2500","PowerZero dtu old limit %d, dtu new limit %d, Grid value %d ",
dtu_old_limit_value, dtu_limit_calculated_value, grid_actual_power_value);
if(id(npw2500_input_ch1_transparent).state && id(npw2500_input_ch2_transparent).state) // check for 2 channel passthrough
{
dtu_limit_calculated_value = 100; // set dtu relativ power limit 100%
powerzero_status = "2 Channel PT"; // report status
grid_power_offset_act_value = 0; // no function in passthrough
}
else
{
if(id(npw2500_input_ch1_transparent).state || id(npw2500_input_ch2_transparent).state) // check for 1 channel passthrough
{
dtu_limit_calculated_value = 100; // set dtu relativ power limit 100%
powerzero_status = "1 Channel PT"; // report status
grid_power_offset_act_value = 0; // set grid_power_offset_act_value,
} // no function in passthrough
}
id(npw2500_grid_power_offset).publish_state(grid_power_offset_act_value); // publish value of actual grid power offset
id(npw2500_powerzero_status).publish_state(powerzero_status);
if(grid_actual_power_value >= 0)
{
id(npw2500_grid_power_import).publish_state(grid_actual_power_value);
id(npw2500_grid_power_export).publish_state(0);
}
if(grid_actual_power_value <= 0)
{
id(npw2500_grid_power_export).publish_state(-grid_actual_power_value);
id(npw2500_grid_power_import).publish_state(0);
}
id(npw2500_home_power_consuption).publish_state(id(npw2500_output_power).state + grid_actual_power_value );
// ************************* Slew Rate Limiter *************************
// Limits ptu limit power changes to dtu_max_slew_rate / cycle
// default limits battery output power changes to 320W /cycle
// *********************************************************************
if(use_slewrate_limiter)
{
int dtu_limited_value = dtu_limit_calculated_value - dtu_old_limit_value;
if (dtu_limited_value > dtu_max_slew_rate)
dtu_limited_value = dtu_max_slew_rate;
if (dtu_limited_value < -dtu_max_slew_rate)
dtu_limited_value = -dtu_max_slew_rate;
dtu_limit_calculated_value = dtu_old_limit_value + dtu_limited_value;
}
if( id(npw2500_powerzero_inverter_producing).state )
{
if( dtu_old_limit_value != dtu_limit_calculated_value ||
id(npw2500_limit_nonpersistent_relative).state != id(opendtu_limit_nonpersistent_relative_target_value).state || cycle_counter == 0)
{
// cannot use id(npw2500_hm_800_limit_nonpersistent_relative).publish_state(dtu_limit)
// any longer because entity id is a string now from !secret inverter_rel_power_limit
//**** update HA dtu limit value *****/
HomeassistantServiceResponse resp;
HomeassistantServiceMap entity_id_kv;
resp.service = "number.set_value";
entity_id_kv.key = "entity_id";
entity_id_kv.value = id(npw2500_config_limit_nonpersistent_relative);
resp.data.push_back(entity_id_kv);
entity_id_kv.key = "value";
entity_id_kv.value = to_string(dtu_limit_calculated_value);
resp.data.push_back(entity_id_kv);
id(opendtu_limit_nonpersistent_relative_target_value).publish_state(dtu_limit_calculated_value);
ESP_LOGD("npw2500", "Power Zero dtu limit calculated %d ",dtu_limit_calculated_value);
if(cycle_counter == 0) ESP_LOGD("npw2500","Cycle sent");
id(api_server).send_homeassistant_service_call(resp);
//*************************************
dtu_old_limit_value = dtu_limit_calculated_value; // save calculated dtu limit
}
}
if(cycle_counter >= send_every_number_of_cycles)
{
cycle_counter = 0;
}
else
cycle_counter++;
// Report internal PowerZero status
if( !id(npw2500_powerzero_inverter_producing).state)
{
if(id(npw2500_input_ch1_transparent).state && id(npw2500_input_ch2_transparent).state)
powerzero_status = "PT active, waitung for OpenDTU";
else
powerzero_status = "Inverter not producing";
}
else
if(!(id(npw2500_input_ch1_active).state || id(npw2500_input_ch2_active).state))
powerzero_status = "Inputs not active";
}
else
{
ESP_LOGD("npw2500", "PowerZero - Communication not ready");
id(npw2500_response_0x03_data_ready) = 0;
id(npw2500_response_0x0f_data_ready) = 0;
}
// npw switch disabled, but communication ready
if(!id(npw2500_zeropower_enabled).state && id(npw2500_enable_gridsensor) && id(npw2500_communication_ready))
{
id(npw2500_home_power_consuption).publish_state(id(npw2500_output_power).state + int(id(npw2500_grid_power).state));
ESP_LOGD("npw2500", "Home Power Consuption updated");
}
- id: reset_energy_sensors
then:
- sensor.integration.reset: npw2500_output_energy_ch1_daily
- sensor.integration.reset: npw2500_output_energy_ch2_daily
- sensor.integration.reset: npw2500_output_energy_daily
- sensor.integration.reset: npw2500_inout_energy_daily
- sensor.integration.reset: npw2500_input_energy_ch1_daily
- sensor.integration.reset: npw2500_input_energy_ch2_daily
- sensor.integration.reset: npw2500_input_energy_daily
- sensor.integration.reset: npw2500_inout_energy_daily
- sensor.integration.reset: npw2500_home_energy_daily
- sensor.integration.reset: npw_grid_energy_daily
- sensor.integration.reset: npw_grid_export_energy_daily
- sensor.integration.reset: npw_grid_import_energy_daily
- id: restart_inverter
then:
- logger.log: Restart Inverter
- homeassistant.service:
service: button.press
data_template:
entity_id: !secret inverter_restart
- id: restart_battery
then:
lambda: |-
id(ble_command).execute(0x25, 0x01);
ESP_LOGD("npw2500", "Restart Battery Command sent");
- id: check_dod
then:
lambda: |-
// BugFix - Battery Discharge randomly 100%
bool enable_dodfix = true; // set enable_dodfix to false if you dont need bugfix
if(id(npw2500_response_0x03_data_ready) && enable_dodfix)
{
int discharge_state = int(id(npw2500_discharge_slider).state);
if(id(npw2500_discharge_treshold).state != discharge_state) // check for difference between slider value and battery value
{
id(ble_command)->execute(0x0B,discharge_state); // send slidervalue to battery
ESP_LOGE("npw2500", "Watch Task - DOD corrected");
}
}
- id: watch_task
then:
lambda: |-
int batt_out_power_switch_power = 400; // set avarage power breakpoint for switching channels
int min_balancing_value = 50; // if one channel has less power start rebalancing
int max_timecount = 6; // defines the cycle time. One timecount is 10 seconds, 6*10 is one minute, 18*10 is three minutes
static int timecount = 0;
static int chn = 1;
static int batt_out_power = 0;
static bool rebalancing_flag = false;
static int last_channel_state = 0;
int batt_out_power_avg = 0;
int batt_out_power_act = 0;
ESP_LOGD("npw2500", "Watch Task started");
if(id(npw2500_enable_battery_control_switch).state && id(npw2500_communication_ready))
{
//ESP_LOGD("npw2500", "Watch Task - npw2500_enable_battery_control_switch");
batt_out_power_act = id(npw2500_output_power).state; // get actual battery output power
if(batt_out_power_act > 1000) batt_out_power_act = 0; // limit check in case of start up
//id(npw2500_battery_control_status).publish_state("Battery Control enabled");
ESP_LOGD("npw2500", "Watch Task - timecount = %d",timecount);
if(timecount == 0)
{
batt_out_power = 0; // reset values when starting new cycle
batt_out_power_avg = 0;
timecount ++;
}
else if (timecount < max_timecount)
{
batt_out_power += batt_out_power_act; // sum batt_out_power
batt_out_power_avg = batt_out_power / timecount;
ESP_LOGD("npw2500", "Watch Task - timecount avg. power = %d",timecount);
timecount ++;
}
else // we reached max_timecount
{
batt_out_power += batt_out_power_act; // calculate actual values
batt_out_power_avg = batt_out_power / timecount;
bool switch_ch1_on = id(npw2500_powerout_switch_ch1).state; // get state of channel1 switch
bool switch_ch2_on = id(npw2500_powerout_switch_ch2).state; // get state of channel2 switch
timecount = 0; // reset timecount
// Enable if only one output switch is set ON and the other one is set OFF and PT switch is OFF
if(((!switch_ch1_on && switch_ch2_on) || (switch_ch1_on && !switch_ch2_on)) && !id(npw2500_powerout_pv2_switch).state)
{
// check if we are not in pt transparent mode
if(!(id(npw2500_input_ch1_transparent).state || id(npw2500_input_ch2_transparent).state))
{
ESP_LOGD("npw2500", "Watch Task - check output power");
std::string power_str = "";
id(npw2500_command_sent_count).publish_state(0);
id(npw2500_enable_output_control) = true;
// check if the battery output power > output_higher_limit
if(batt_out_power_avg > batt_out_power_switch_power)
{
// check if rebalancing flag is set and rebalancing conditions are met
if( rebalancing_flag && id(npw2500_output_ch1_active).state && id(npw2500_output_ch2_active).state &&
(id(npw2500_output_power_ch1).state <= min_balancing_value || id(npw2500_output_power_ch2).state <= min_balancing_value))
{ // send restart inverter command
id(restart_inverter)->execute();
ESP_LOGD("npw2500", "Inverter restarted for rebalancing");
id(npw2500_command_sent_count).publish_state(4);
rebalancing_flag = false; // reset rebalancing flag
}
else
{
rebalancing_flag = false; // reset rebalancing flag
}
// check for channel switch 1->2
if((last_channel_state == 1) && id(npw2500_output_ch1_active).state && id(npw2500_output_ch2_active).state )
{
rebalancing_flag = true; // set rebalancing flag
last_channel_state = 2; // 2 channels active
id(npw2500_battery_control_status).publish_state("Checking for Rebalancing");
id(npw2500_command_sent_count).publish_state(3);
}
if(!rebalancing_flag) // if rebalancing flag is set, we are already in 2 channel mode
{
id(npw2500_set_output_state_ch1) = true; // turn on both outputs
id(npw2500_set_output_state_ch2) = true;
id(npw2500_update_output_state) = true;
id(npw2500_command_sent_count).publish_state(2);
if(id(npw2500_output_ch1_active).state && id(npw2500_output_ch2_active).state) // if both outputs are on, report 2 Channel mode
{
power_str = "2 Channel avg. power " + std::to_string(batt_out_power_avg) +" W";
id(npw2500_battery_control_status).publish_state(power_str);
ESP_LOGD("npw2500",power_str.c_str());
}
else // we are in switching mode
{
power_str = "Switching Channels avg. power " + std::to_string(batt_out_power_avg) +" W";
id(npw2500_battery_control_status).publish_state(power_str);
ESP_LOGD("npw2500",power_str.c_str());
}
}
}
else // batt_out_power_avg < batt_out_power_switch_power
{
if(!switch_ch1_on && switch_ch2_on) // switch channel 1 off
{
id(npw2500_set_output_state_ch1) = false;
id(npw2500_set_output_state_ch2) = true;
id(npw2500_update_output_state) = true;
}
else // switch channel 2 off
{
id(npw2500_set_output_state_ch1) = true;
id(npw2500_set_output_state_ch2) = false;
id(npw2500_update_output_state) = true;
}
id(npw2500_command_sent_count).publish_state(1);
if(id(npw2500_output_ch1_active).state && id(npw2500_output_ch2_active).state) // if both outputs are on, report switching mode
{
power_str = "Switching Channels avg. power " + std::to_string(batt_out_power_avg) +" W";
id(npw2500_battery_control_status).publish_state(power_str);
ESP_LOGD("npw2500",power_str.c_str());
}
else
{
power_str = "1 Channel avg. power " + std::to_string(batt_out_power_avg) +" W"; // report 1 Channel mode
id(npw2500_battery_control_status).publish_state(power_str);
ESP_LOGD("npw2500",power_str.c_str());
}
rebalancing_flag = false;
last_channel_state = 1; // set 1 channel state
}
}
else
{
id(npw2500_battery_control_status).publish_state("PTMode active");
id(npw2500_enable_output_control) = false;
}
}
else
{
id(npw2500_battery_control_status).publish_state("Both CH1/Ch2 are ON or OFF or PT ON");
id(npw2500_enable_output_control) = false;
}
}
}
else
{
if(!id(npw2500_enable_battery_control_switch).state)
{
id(npw2500_battery_control_status).publish_state("Battery Control disabled");
timecount = 0;
rebalancing_flag = false;
last_channel_state = 0;
id(npw2500_enable_output_control) = false;
}
}
### End of NPW2500.yaml ###
NPWDashboard Setup
Nachdem ihr den ESPNode NPW2500 in den HA integriert habt und unter
Settings->Device&Services->Integrations>ESPhome
das device "No Power Wasted 2500" vorhanden ist,
könnt ihr mit der Vorlage NPWDashboard V0.3 das entsprechende Dashboard erzeugen.
Ihr geht folgend vor:
HA-> Settings -> Dasboards
rechts unten auf das blaue Feld + ADD DASHBOARD drücken und
"New Dashboard" from Scratch" auswählen.
Als Name NPW2500 eingeben und "CREATE" drücken.
In der linken HA Dashboard Auswahlliste sollte dieses nun angezeigt werden.
In der Liste auswählen und öffnen.
Es sollte sich nun eine leeres Dashboard mit dem Namen NPW2500 öffnen.
Rechts oben in der blauen Leiste die 3 senkrechten Punkte clicken und "Edit Dashboard" auswählen .
Nun in der grauen Leiste oben wieder die 3 Punkte anklicken und "RAW CONFIGURATION EDITOR" auswählen.
Es öffnet sich nun ein Editierfenster in das ihr den Inhalt von NPWDashboard V0.3 kopiert. (Die ersten 2 vorgegebenen Zeilen überschreiben)
Wenn ihr fertig seid rechts oben "Save drücken" und den Editor mit dem x links oben verlassen.
Nun sollten die Panels im Dashboard angezeigt werden und oben rechts auf "Done" drücken.
views:
- title: No Power Wasted
badges: []
cards:
- type: entities
entities:
- entity: number.esphome_npw2500_set_discharge_threshold
name: Set Discharge threshold
- entity: sensor.esphome_npw2500_discharge_threshold
name: Discharge threshold
- entity: switch.esphome_npw2500_set_power_out_switch_ch1
name: Set Power Out Switch Ch1
- entity: binary_sensor.esphome_npw2500_output_ch1_active
name: Ouput Ch1 active
- entity: switch.esphome_npw2500_set_power_out_switch_ch2
name: Set Power Out Switch Ch2
- entity: binary_sensor.esphome_npw2500_output_ch2_active
name: Ouput Ch2 active
- entity: switch.esphome_npw2500_set_pv2_passtrough_switch
name: Set PV2 Passtrough Switch
- entity: binary_sensor.esphome_npw2500_passthrough_active
name: PassThrough active
- entity: number.esphome_npw2500_set_solar_charge_threshold
name: Set Solar Charge threshold
- entity: sensor.esphome_npw2500_solar_charge_threshold
name: Solar Charge threshold
- entity: switch.esphome_npw2500_enable_battery_control
name: Enable Battery Control
- entity: sensor.esphome_npw2500_powerzero_battery_control_status
name: Battery Control Status
title: No Power Wasted 2500 V0.322 (Test)
show_header_toggle: false
state_color: true
- type: entities
entities:
- entity: switch.esphome_npw2500_powerzero_enabled
name: PowerZero enabled
- entity: sensor.esphome_npw2500_powerzero_status
name: PowerZero Status
- entity: number.esphome_npw2500_set_power_limit_rel
name: Set Power Limit maximum
- entity: sensor.esphome_npw2500_opendtu_power_limit_rel_target_value
name: openDTU Power Limit target value
- entity: sensor.esphome_npw2500_opendtu_power_limit_rel_actual_value
name: openDTU Power Limit actual value
- entity: number.esphome_npw2500_set_max_cell_voltage
name: Set max Cell Voltage
- entity: sensor.esphome_npw2500_cell_voltage_max
name: Cell Voltage actual
- entity: number.esphome_npw2500_set_grid_power_offset
name: Set Grid Power Offset
- entity: sensor.esphome_npw2500_grid_power_offset
name: Grid Power Offset
- entity: sensor.esphome_npw2500_grid_power
name: Grid Power
- entity: binary_sensor.esphome_npw2500_powerzero_inverter_producing
name: Inverter producing
- entity: button.esphome_npw2500_restart_inverter
name: Inverter Restart
title: NPW PowerZero - Nulleinspeisung
show_header_toggle: false
state_color: true
- type: entities
entities:
- entity: sensor.esphome_npw2500_input_power
name: Battery Solar Input Power
- entity: sensor.esphome_npw2500_output_power
name: Battery DTU Output Power
- entity: sensor.esphome_npw2500_power_inout
name: Battery Power
- entity: sensor.esphome_npw2500_grid_power
name: Grid Power
- entity: sensor.esphome_npw2500_home_power_consumption
name: Home Power Consumption
title: NPW Solar
- type: entities
entities:
- entity: sensor.esphome_npw2500_input_energy_daily
name: Solar
- entity: sensor.esphome_npw2500_battery_inout_energy_daily
name: Battery
- entity: sensor.esphome_npw2500_output_energy_daily
name: Battery Output
- entity: sensor.esphome_npw2500_home_energy_consumption_daily
name: Home Consumption
- entity: sensor.esphome_npw2500_grid_energy_daily
name: Grid
- entity: sensor.esphome_npw2500_grid_export_energy_daily
name: Grid Export
- entity: sensor.esphome_npw2500_grid_import_energy_daily
name: Grid Import
- entity: sensor.esphome_npw2500_input_ch1_energy_daily
name: Solar Ch1
- entity: sensor.esphome_npw2500_input_ch2_energy_daily
name: Solar Ch2
- entity: sensor.esphome_npw2500_output_ch1_energy_daily
name: Battery Output Ch1
- entity: sensor.esphome_npw2500_output_ch2_energy_daily
name: Battery Output Ch2
- entity: button.esphome_npw2500_reset_daily_energy
name: Reset Daily Energy
title: NPW Energy Daily
show_header_toggle: false
- type: entities
entities:
- entity: sensor.esphome_npw2500_input_power
name: Input Power
- entity: sensor.esphome_npw2500_input_ch1_power
name: Input Ch1 Power
- entity: binary_sensor.esphome_npw2500_input_ch1_active
name: Input Ch1 active
- entity: binary_sensor.esphome_npw2500_input_ch1_transparent
name: Input Ch1 transparent
- entity: sensor.esphome_npw2500_input_ch2_power
name: Input Ch2 Power
- entity: binary_sensor.esphome_npw2500_input_ch2_active
name: Input Ch2 active
- entity: binary_sensor.esphome_npw2500_input_ch2_transparent
name: Input Ch2 transparent
title: NPW Inputs
show_header_toggle: false
state_color: true
- type: entities
entities:
- entity: sensor.esphome_npw2500_output_power
name: Output Power
- entity: sensor.esphome_npw2500_output_power_ch1
name: Output Power Ch1
- entity: binary_sensor.esphome_npw2500_output_ch1_active
name: Output Ch1 active
- entity: sensor.esphome_npw2500_output_power_ch2
name: Output Power Ch2
- entity: binary_sensor.esphome_npw2500_output_ch2_active
name: Output Ch2 active
title: NPW Outputs
show_header_toggle: false
state_color: true
- type: entities
entities:
- entity: binary_sensor.esphome_npw2500_battery_wifi_connected
name: Battery WiFi connected
- entity: sensor.esphome_npw2500_battery_wifi_disconnects
name: Battery WiFi disconnects
- entity: binary_sensor.esphome_npw2500_esp_ble_connected
name: ESP Ble connected
- entity: sensor.esphome_npw2500_esp_ble_disconnects
name: Battery Ble disconnects
- entity: binary_sensor.esphome_npw2500_esp_ha_connected
name: ESP HA connected
- entity: sensor.esphome_npw2500_esp_ha_disconnects
name: Battery HA disconnects
- entity: binary_sensor.esphome_npw2500_esp_wifi_connected
name: ESP Wifi connected
- entity: sensor.esphome_npw2500_esp_wifi_disconnects
name: ESP WiFi disconnects
- entity: button.esphome_npw2500_restart_esp
name: Restart ESP
- entity: switch.esphome_npw2500_enable_bluetooth
name: Enable Bluetooth
title: NPW Communication
show_header_toggle: false
state_color: true
- type: entities
entities:
- entity: sensor.esphome_npw2500_cell_voltage_avg
name: Cell Voltage avg
- entity: sensor.esphome_npw2500_cell_voltage_diff
name: Cell Voltage diff
- entity: sensor.esphome_npw2500_cell_voltage_max
name: Cell Voltage max
- entity: sensor.esphome_npw2500_cell_voltage_min
name: Cell Voltage min
- entity: sensor.esphome_npw2500_cell_voltage_sum
name: Cell Voltage sum
title: NPW Battery Cells
show_header_toggle: false
state_color: true
- type: entities
entities:
- entity: sensor.esphome_npw2500_battery_remaining_capacity
name: Battery remaining capacity
- entity: sensor.esphome_npw2500_battery_soc
name: Battery SOC
- entity: sensor.esphome_npw2500_battery_soc_dynamic
name: Battery SOC dynamic
- entity: sensor.esphome_npw2500_temperature_sensor_1
name: Temperature Sensor 1
- entity: sensor.esphome_npw2500_temperature_sensor_2
name: Temperature Sensor 2
- entity: sensor.esphome_npw2500_battery_version
name: Battery Version
- entity: button.esphome_npw2500_restart_battery
name: Restart Battery
title: NPW Battery
show_header_toggle: false
state_color: true
# Secrets V0.3
# sectrets.yaml
# Wi-Fi SSID and password
# use your ssid and password
wifi_ssid: "ssid"
wifi_password: "password"
# mac address of the batterie, you find it in in the App
battery_ble_mac: "e8:8d:a6:56:xx:xx"
# HA Sensor of your actual grid power
# sensor.grid_power is the id of my entity, enter your id
# "sensor.xyz..."
npw2500_grid_power: "sensor.grid_power"
# HA Sensor of your OpenDTU relativ power limit
# number.hm_800_limit_nonpersistent_relative is the id of my entity, enter your id
# '"number.xyz..."'
inverter_rel_power_limit: '"number.hm_800_limit_nonpersistent_relative"'
# "number.xyz..."
inverter_rel_power_limit_2: "number.hm_800_limit_nonpersistent_relative"
# HA Sensor of your OpenDTU inverter producing
# binary_sensor.hm_800_producing is the id of my entity, use your id
# "binary_sensor.xyz..."
inverter_producing: "binary_sensor.hm_800_producing"
# HA Sensor of your OpenDTU restart inverter
# "button.hm_800_restart_inverter" is the id of my entity, use your id
# "button..xyz..."
inverter_restart: "button.hm_800_restart_inverter"
@tbretz65
Copy link

Hallo,
hoffe mir kann jemand helfen.
Habe seit heute die Version 1.38 auf meiner BP2500.
Jetzt sieht mein NoPowerWaste so aus:
grafik

Warum bricht das jetzt andauernd ein ?
Kann mir das jemand sagen.
Danke

@gine78
Copy link

gine78 commented May 22, 2024

Das ist ähnlich wie bei mir gestern. In meinen Tests hatte ich ein ähnliches Verhalten:
image

Einer der Gründe warum ich das erstmal habe sein gelassen

@tbretz65
Copy link

@gine78
ging das auch nach dem Update nicht mehr ?

@gine78
Copy link

gine78 commented May 22, 2024

Ich bin direkt mit der V157 rein, ich habe die V1.2, wie weiter oben schon mal angesprochen. Mit dieser aktuellen Version hier, habe ich leider mehr Probleme als Vorteile. Es müsste sich eine so fitter Coder wie @neromatrix oder @noone2k der einen V1.2 hat.

@tbretz65
Copy link

tbretz65 commented May 22, 2024

So,
hab mal getestet :-)
Scheint was mit dem eingeschaltetem Battery Control zu tun zu haben.
grafik
Denn wenn es aus ist, dann funktioniert die Ausgabe.
Da muss wohl @neromatrix ran .
Die gelbe Anzeige da war BatteryControl aus.

@neromatrix
Copy link
Author

Wenn du nicht unbedingt den 1+1 Betrieb benutzen musst, gibt es keinen Grund Battery Control zu aktivieren.
Ich habe leider keinen V1.2 zur Verfügung um mir das genauer anzuschauen.

@gine78
Copy link

gine78 commented May 23, 2024

Kann ich dir irgendwelche Daten liefern, damit du da mal reinschauen kannst? Wireshark Protoll oder Ähnliches?

@tbretz65
Copy link

Ich hab auch keinen V1.2.
Aber ich hab die 1.38 Version auf dem Akku und da ist das so.
Mit der 1.35 war das noch nicht.

@tbretz65
Copy link

tbretz65 commented May 24, 2024

Hab nochmal eine Frage.
Was bedeutet es, wenn der Akku immer bei 246W auf 0 springt ?
Also wenn ich den Akku entlade sieht das so aus:
Screenshot 2024-05-24 202641

Ist da eine Celle defekt ?
Danke

@JoeBue1
Copy link

JoeBue1 commented May 24, 2024

@tbretz65
Ich würde eher vermuten, dass das BMS nicht ordentlich kalibriert ist.

Aber guck dir mal die Spannungen der Zellen an; ich vermute, das die durchschnittliche Zellenspannung unter 3V gesunken ist.
Im schlimmsten Fall, wenn die Spannungsdifferenz der Zellen aber zu hoch sein sollte, wäre ein Zelle defekt.
Mein maximale Differenz war die Woche 0,025V.

@tbretz65
Copy link

tbretz65 commented May 24, 2024

hier mal ein bild meiner Differenzen:
grafik

Bin aber gerade beim kalibrieren. (zum 3ten mal laden)

@tbretz65
Copy link

so sieht mein min Voltage aus:
Screenshot 2024-05-24 203752

@JoeBue1
Copy link

JoeBue1 commented May 24, 2024

@tbretz65
Die Differenzen sind für mich im grünen Bereich; wenn eine Zelle Defekt wäre, würde ich vermuten, dass die Differenz über 2V wäre.
Und beim Min: alles unter 3V sollte eine Tief-Entladung sein.
Ich schalte bei mir die Ausgänge aus, wenn "Vortage min" unter 3V sinkt um die Tiefentladung zu verhindern.

Schaffst du es denn, beim Kalibrieren 100% SOC zu erreichen?

@tbretz65
Copy link

Ja das geht.
Also denkst Du nicht das der Akku defekt ist ?

@JoeBue1
Copy link

JoeBue1 commented May 24, 2024

jo - das denke ich.

@noone2k
Copy link

noone2k commented May 24, 2024

einen runner gibt es immer ... nach oben und nach unten hin ... sollte aber nicht zuweit auseinander liegen.

habe auch so einen akku, wo nicht alle zellen ordentlich balanciert sind ...
da ist eine bei 2.8 ( und bms schaltet richtigerweise aus ) , während die anderen noch bei 3.0-3.1 sind.
im gegenzug wird die eine zelle niemals richtig voll, weil die anderen ( oder eine davon ) eher die 3.65 erreicht, wo der nachzügler noch bei 3.4 oder liegt.

dadurch kann man natürlich nicht die volle kapazität nutzen.
da würde nur ein ordentliches initial-balancing helfen, ggf. mit nem anschließendem topbalancing.

hatte die kiste schonmal soweit auseinander gebaut, das ich den zellen-block selbst vor mir hatte.
war dann aber schon wieder kurz vor sandmänchen, so das ich besser wieder zusammengebaut hatte
und nicht schlaftrunken da rumhantiere ... bisher noch nicht die zeit gefunden, das zu machen ... 😁

btw. deswegen schalte ich die ausgänge ab, wenn vmin 3.0-3.1V erreicht ... ( weiss gerade nicht mehr, was ich da bei mir eingebaut habe )

@tbretz65
Copy link

Ok.
Danke für Eure Informationen.
Ich werde das mal beobachten.
Mach gerade die 3te voll Ladung.
Danach werde ich mal sehen wie ich das im HA anpasse damit ab 3.0V der Akku abschaltet.
Danke

@neromatrix
Copy link
Author

@tbretz65

Ich hab auch keinen V1.2.
Aber ich hab die 1.38 Version auf dem Akku und da ist das so.
Mit der 1.35 war das noch nicht.

Ich habe jetzt auch die Version 1.38 installiert und kann deine Beobachtung bestätigen.
Bei der Version 1.35 war es kein Problem, einen zweiten Kanal dazu zu schalten oder wieder abzuschalten.
Der eingeschaltete "Hauptkanal" lieferte weiterhin Strom, der Wechselrichter funktionierte durchgehend.

Mit der Version 1.38 ist das nicht mehr möglich.
Beim Einschalten des zweiten Kanales, wird nun immer zuerst der Hauptkanal abgeschalten und erst nach längerer Zeit die Kanäle entsprechend wieder aktiviert.
Dadurch ist aber auch der Wechselrichter stromlos und schaltet manchmal ab. Ebenso dauert es sehr lange, bis die Leistungen an den Ausgängen der Batterie wieder den vollen Wert erreichen.

@neromatrix
Copy link
Author

neromatrix commented May 27, 2024

Quick and dirty Fix der Funktion "Battery Control" für die Batterie Version 1.38
Den oberen Teil der Funktion watch_task (Zeile 1379 bis zur Zeile 1426) durch folgenden Code ersetzen:

  - id: watch_task 
    then:                       
      lambda: |-  
        int batt_out_power_switch_power = 400;                // set avarage power breakpoint for switching channels
        int min_balancing_value = 50;                         // if one channel has less power start rebalancing
        // Fix for version 1.38 set max_timecount to 12
        int max_timecount = 12;                                // defines the cycle time. One timecount is 10 seconds, 6*10  is one minute, 18*10 is three minutes

        static int timecount = 0;
        static int chn = 1;  
        static int batt_out_power = 0;
        static bool rebalancing_flag = false;
        static int last_channel_state = 0;

        int batt_out_power_avg = 0;       
        int batt_out_power_act = 0;
         
        ESP_LOGD("npw2500", "Watch Task started"); 
        if(id(npw2500_enable_battery_control_switch).state && id(npw2500_communication_ready))
        {
          //ESP_LOGD("npw2500", "Watch Task - npw2500_enable_battery_control_switch"); 
          
          batt_out_power_act = id(npw2500_output_power).state;                                    // get actual battery output power  
          if(batt_out_power_act > 1000) batt_out_power_act = 0;                                   // limit check in case of start up

          //id(npw2500_battery_control_status).publish_state("Battery Control enabled");
          ESP_LOGD("npw2500", "Watch Task - timecount = %d",timecount); 
          if(timecount == 0)                                                                      // reset values when starting new cycle 
          {                                                                                       // Fix for version 1.38
            if((id(npw2500_output_ch1_active).state || id(npw2500_output_ch2_active).state) && id(npw2500_powerzero_inverter_producing).state )
            {
               timecount ++;
            }
            batt_out_power = 0;                                                                      
            batt_out_power_avg = 0;    
           
          }
          else if (timecount < max_timecount)
          {
            batt_out_power += batt_out_power_act;                                                 // sum batt_out_power
            //batt_out_power_avg = batt_out_power / timecount;
            batt_out_power_avg = batt_out_power_act;                                              // Fix for version 1.38
            ESP_LOGD("npw2500", "Watch Task - timecount avg. power = %d",timecount); 
            timecount ++;
          }
          else                                                                                    // we reached max_timecount
          {
            batt_out_power += batt_out_power_act;                                                 // calculate actual values
            //batt_out_power_avg = batt_out_power / timecount;
            batt_out_power_avg = batt_out_power_act;                                              // Fix for version 1.38
            bool switch_ch1_on = id(npw2500_powerout_switch_ch1).state;                           // get state of channel1 switch
            bool switch_ch2_on = id(npw2500_powerout_switch_ch2).state;                           // get state of channel2 switch
            timecount = 0;                                                                        // reset timecount
            
            // Enable if only one output switch is set ON and the other one is set OFF and PT switch is OFF

Änderungen:
Zykluszeit auf 2 Minuten erhöht.
Prüfung auf aktive Ausgänge und aktiven Inverter.
Verwendung der momentanen Ausgangsleistung und nicht der durchschnittlichen. (avg. ignorieren)

@helmi55
Copy link

helmi55 commented May 28, 2024

Guten Abend
auf wieviel V kommt ihr bei voller Batterie?
So sieht es bei mir aus
Bildschirmfoto 2024-05-28 um 16 52 58
Batterie Version ist 1.35

Kommt mir wenig vor oder?
Bildschirmfoto 2024-05-28 um 16 55 53

Gruß
Helmut

@noone2k
Copy link

noone2k commented May 28, 2024

@helmi55

kommt darauf an, wie lange der speicher schon "steht" ...
im idealfall, wenn alle zellen balanciert sind, sollte zum zeitpunkt der abschaltung der wert um die ~51V sein ...
da gehe ich aber von aus, das das sogut wie bei keinem erreicht wird ;)

ein guter/akzeptabler wert, wie gesagt, zum zeitpunkt der abschaltung, sollte bei ~ 49 liegen ..

ABER: umso länger keine energy mehr zugeführt wird, umso mehr normalisieren sich die einzelnen zellen.
wenn man bei einer vollgeladenen zelle, nach einer ausreichenden ruhephase , von ca. 3.3V ausgeht, sollte der wert bei ~ 46.5V liegen.

die werte bei dir, wenn man von einer entsprechend langen ruhephase ausgeht, sind im norm-bereich ...

@helmi55
Copy link

helmi55 commented May 28, 2024

@noone2k
Servus und guten Abend.
Ja die Batterie ist seit Dezember in Betrieb (Abstellraum neben der Garage - nie unter 5 Grad)
Im Winter war das beladen etwas "mau". Jetzt schaffe ich es bei schönem Wetter die Batterie täglich voll zu bekommen.
Die letzten 2 Tage waren wieder nicht optimal und die Befüllung dauerte halt 2 Tage
Ich werde es weiter beobachten
Danke und schönen Abend
Helmut

@noone2k
Copy link

noone2k commented May 28, 2024

sorry, ungünstig ausgedrückt ..
mit "batterie steht", meine ich nicht den dauerhaften standort :) ( nur weil du ihn erwähnt hast )

sondern stillstand im ab- und zufluss von energy ... also keine energy mehr zu- oder abgeführt wird.
nur nochmal zur sicherheit, falls wir uns da missverstehen g

// mal etwas genauer , mit konkreten zahlen..
habe mal bei mir von einer leicht unbalancierten batterie die werte genommen ...

zum zeitpunkt wo der bms abschaltet, weil EINE zelle 3.65V hat: ~ 49.5V ...
eine stunde später ~ 47
zwei stunden später ~ 46.8
drei stunden später ~ 46.7

@shruxx
Copy link

shruxx commented Jun 1, 2024

Hi,

EDIT: mittlerweile ist der ESP per MQTT verbunden, jedoch erstellt mir der HA keine Entitäten dafür. Ist das so gewollt?

@buck3003
Copy link

buck3003 commented Jun 3, 2024

Hi zusammen,
erst mal ein ganz dickes DANKE an den/die Coder von dem Projekt, MEGA!
Ich habe den B2500 von Marstek mit der SW 1.63 am laufen und habe folgendes Problem. Der ESP pollt nur einmalig die Werte danach nicht mehr, anbei mal ein Screenshot vom LOG
Screenshot_log
Habt ihr sowas auch schon gehabt oder wisst ihr woran das liegen könnte?

EDIT: Problem gelöst, liegt anscheinend daran, wenn's mit framework: -> type: arduino gebaut wird...

Gruß Christian

@shruxx
Copy link

shruxx commented Jun 3, 2024

Auch hier wieder EDITA EDIT: mein copy paste hatte offenbar gestern etwas falsches drin, weswegen der Sensor komplett falsch eingerichtet war. Funktioniert wieder :D

@Tom-48
Copy link

Tom-48 commented Jun 4, 2024

Hallo,
bin relativ neu hier und Neuling in ESPHome.
Ich besitze ein B2500 seit einer Woche und ich möchte die Werte über ESP auslesen, aber ich benötige nicht die Null Einspeisung,
die ich hier im Code gelesen habe. Ich weiss nicht ob man nur die Codzeilen rauslöschen kann oder ob es noch Anpassungen benötigt.
In Yaml bin ich auch noch Anfänger, vielleicht könnt ihr mir helfen?
Ich setze eine ESP32 D1 mini ein und Home Assistent ESP Home.

Vielen Dank für in voraus
Tom-48

@JoeBue1
Copy link

JoeBue1 commented Jun 4, 2024

@Tom-48
Du kannst das yaml ohne Änderung verwenden; die Null-Einspeisung kann im Dashboard ein/ausgeschaltet werden.
Ich verwende NPW auch ohne Null-Einspeisung.

@fefi-byte
Copy link

@Tom-48
Du kannst die sensor in der seecret.yaml einfach ignorieren. Nur wifi und MAC Adresse anpassen.

@Tom-48
Copy link

Tom-48 commented Jun 4, 2024

@JoeBue1 @fefi-byte
Danke euch beiden! Es läuft, nun kann ich es in Nod-Red nutzen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment