Skip to content

Instantly share code, notes, and snippets.

@gilankpam
Created December 22, 2023 06:31
Show Gist options
  • Save gilankpam/d47555970d2e67f41ab062a30347a100 to your computer and use it in GitHub Desktop.
Save gilankpam/d47555970d2e67f41ab062a30347a100 to your computer and use it in GitHub Desktop.
ESPHome Epever
esphome:
name: solar-monitor
friendly_name: solar-monitor
platformio_options:
## larger stack size required with all registers enable_load_test
## reduce registers or wait for integration of 2.0.0 arduinoespressif32
## not yet working needs 2.0
build_flags:
- -DCONFIG_ARDUINO_LOOP_STACK_SIZE=32768
on_boot:
## configure controller settings at setup
## make sure priority is lower than setup_priority of modbus_controller
priority: -100
then:
- lambda: |-
// get local time and sync to controller
time_t now = ::time(nullptr);
struct tm *time_info = ::localtime(&now);
int seconds = time_info->tm_sec;
int minutes = time_info->tm_min;
int hour = time_info->tm_hour;
int day = time_info->tm_mday;
int month = time_info->tm_mon + 1;
int year = time_info->tm_year % 100;
esphome::modbus_controller::ModbusController *controller = id(epever);
// if there is no internet connection localtime returns year 70
if (year != 70) {
// create the payload
std::vector<uint16_t> rtc_data = {uint16_t((minutes << 8) | seconds), uint16_t((day << 8) | hour),
uint16_t((year << 8) | month)};
// Create a modbus command item with the time information as the payload
esphome::modbus_controller::ModbusCommandItem set_rtc_command =
esphome::modbus_controller::ModbusCommandItem::create_write_multiple_command(controller, 0x9013, 3, rtc_data);
// Submit the command to the send queue
epever->queue_command(set_rtc_command);
ESP_LOGI("ModbusLambda", "EPSOLAR RTC set to %02d:%02d:%02d %02d.%02d.%04d", hour, minutes, seconds, day, month,
year + 2000);
}
std::vector<uint16_t> battery_settings1 = {
0, // 9000 Battery Type 0 = User
0x0064, // 9001 Battery Cap == 100AH
0x012C, // 9002 Temp compensation -3V /°C/2V
0x155E, // 9003 0x5DC == 1367 Over Voltage Disconnect Voltage 54,7
0x150E, // 9004 0x58C == 1350 Charging Limit Voltage 53,9
0x150E, // 9005 Over Voltage Reconnect Voltage 53,9
0x14E6, // 9006 Equalize Charging Voltage 53,5
0x14E6, // 9007 Boost Charging Voltage 53,5
0x14B4, // 9008 Float Charging Voltage 53
0x13C4, // 9009 Boost Reconnect Charging Voltage 50,6
0x12C0, // 900A Low Voltage Reconnect Voltage 48
0x13B0, // 900B Under Voltage Warning Reconnect Voltage 50,4
0x1360, // 900c Under Volt. Warning Volt 49,6
0x11F8, // 900d Low Volt. Disconnect Volt. 46
0x11D0 // 900E Discharging Limit Voltage 45,6
};
// Boost and equalization periods
std::vector<uint16_t> battery_settings3 = {
0x0000, // 906B Equalize Duration (min.) 0
0x0075 // 906C Boost Duration (aka absorb) 117 mins
};
esphome::modbus_controller::ModbusCommandItem set_battery1_command =
esphome::modbus_controller::ModbusCommandItem::create_write_multiple_command(controller, 0x9000, battery_settings1.size() ,
battery_settings1);
// esphome::modbus_controller::ModbusCommandItem set_battery2_command =
// esphome::modbus_controller::ModbusCommandItem::create_write_multiple_command(controller, 0x900A, battery_settings2.size() ,
// battery_settings2);
esphome::modbus_controller::ModbusCommandItem set_battery3_command =
esphome::modbus_controller::ModbusCommandItem::create_write_multiple_command(controller, 0x906B, battery_settings3.size(),
battery_settings3);
delay(200) ;
controller->queue_command(set_battery1_command);
//delay(200) ;
// controller->queue_command(set_battery2_command);
// delay(200) ;
//controller->queue_command(set_battery3_command);
ESP_LOGI("ModbusLambda", "EPSOLAR Battery set");
esp32:
board: esp32dev
framework:
type: arduino
time:
- platform: sntp
id: sntp_time
servers: "pool.ntp.org"
uart:
id: mod_bus
tx_pin: GPIO17
rx_pin: GPIO16
baud_rate: 115200
stop_bits: 1
modbus:
#flow_control_pin: 23
send_wait_time: 200ms
id: mod_bus_epever
modbus_controller:
- id: epever
## the Modbus device addr
address: 0x1
modbus_id: mod_bus_epever
command_throttle: 200ms
setup_priority: -10
update_interval: 5s
sensor:
- platform: template
accuracy_decimals: 0
name: "Generated Charge today"
id: generated_charge_today
unit_of_measurement: "Ah"
- platform: wifi_signal
name: "WiFi Signal"
update_interval: 5s
# Realtime data
- platform: modbus_controller
modbus_controller_id: epever
id: pv_input_voltage
name: "PV array input voltage"
address: 0x3100
unit_of_measurement: "V" ## for any other unit the value is returned in minutes
register_type: read
value_type: U_WORD
accuracy_decimals: 1
filters:
- multiply: 0.01
device_class: voltage
- platform: modbus_controller
modbus_controller_id: epever
id: pv_input_current
name: "PV array input current"
address: 0x3101
unit_of_measurement: "A" ## for any other unit the value is returned in minutes
register_type: read
value_type: U_WORD
accuracy_decimals: 2
filters:
- multiply: 0.01
device_class: current
- platform: modbus_controller
modbus_controller_id: epever
id: pv_input_power
name: "PV array input power"
address: 0x3102
unit_of_measurement: "W" ## for any other unit the value is returned in minutes
register_type: read
value_type: U_DWORD_R
accuracy_decimals: 1
filters:
- multiply: 0.01
device_class: power
- platform: modbus_controller
modbus_controller_id: epever
id: charging_voltage
name: "Charging voltage"
address: 0x3104
unit_of_measurement: "V"
register_type: read
value_type: U_WORD
accuracy_decimals: 1
filters:
- multiply: 0.01
device_class: voltage
- platform: modbus_controller
modbus_controller_id: epever
id: charging_current
name: "Charging current"
address: 0x3105
unit_of_measurement: "A"
register_type: read
value_type: U_WORD
accuracy_decimals: 1
filters:
- multiply: 0.01
device_class: current
- platform: modbus_controller
modbus_controller_id: epever
id: charging_power
name: "Charging power"
address: 0x3106
unit_of_measurement: "W"
register_type: read
value_type: U_DWORD_R
accuracy_decimals: 1
filters:
- multiply: 0.01
device_class: power
# Temps
- platform: modbus_controller
modbus_controller_id: epever
id: battery_temperature
name: "Battery temperature"
address: 0x3110
unit_of_measurement: °C
register_type: read
value_type: S_WORD
accuracy_decimals: 1
filters:
- multiply: 0.01
- platform: modbus_controller
modbus_controller_id: epever
id: device_temperature
name: "Device temperature"
address: 0x3111
unit_of_measurement: °C
register_type: read
value_type: S_WORD
accuracy_decimals: 1
filters:
- multiply: 0.01
- platform: modbus_controller
modbus_controller_id: epever
id: power_components_temperature
name: "Power components temperature"
address: 0x3112
unit_of_measurement: °C
register_type: read
value_type: S_WORD
accuracy_decimals: 1
filters:
- multiply: 0.01
# Battery
- platform: modbus_controller
modbus_controller_id: epever
id: battery_soc
name: "Battery SOC"
address: 0x311A
unit_of_measurement: "%"
register_type: read
value_type: U_WORD
accuracy_decimals: 0
device_class: battery
- platform: modbus_controller
modbus_controller_id: epever
id: battery_voltage
name: "Battery voltage"
address: 0x331A
register_type: read
value_type: U_WORD
accuracy_decimals: 1
unit_of_measurement: "V"
filters:
- multiply: 0.01
device_class: voltage
- platform: modbus_controller
modbus_controller_id: epever
id: battery_current
name: "Battery current"
address: 0x331B
register_type: read
value_type: S_DWORD_R
register_count: 2
accuracy_decimals: 2
unit_of_measurement: "A"
filters:
- multiply: 0.01
device_class: current
- platform: modbus_controller
modbus_controller_id: epever
id: Battery_status_temp
name: "Battery status temperature"
address: 0x3200
register_type: read
value_type: U_WORD
bitmask: 0x38 #(Bits 4-7)
accuracy_decimals: 0
# Tracers
- platform: modbus_controller
modbus_controller_id: epever
id: max_pv_voltage_today
name: "Maximum PV voltage today"
address: 0x3300
register_type: read
value_type: U_WORD
accuracy_decimals: 1
unit_of_measurement: "V"
filters:
- multiply: 0.01
device_class: voltage
- platform: modbus_controller
modbus_controller_id: epever
id: min_pv_voltage_today
name: "Minimum PV voltage today"
address: 0x3301
register_type: read
value_type: U_WORD
accuracy_decimals: 1
unit_of_measurement: "V"
filters:
- multiply: 0.01
device_class: voltage
- platform: modbus_controller
modbus_controller_id: epever
id: max_battery_voltage_today
name: "Maximum battery voltage today"
address: 0x3302
register_type: read
value_type: U_WORD
accuracy_decimals: 1
unit_of_measurement: "V"
filters:
- multiply: 0.01
device_class: voltage
- platform: modbus_controller
modbus_controller_id: epever
id: min_battery_today
name: "Minimum battery voltage today"
address: 0x3303
register_type: read
value_type: U_WORD
accuracy_decimals: 1
unit_of_measurement: "V"
filters:
- multiply: 0.01
device_class: voltage
- platform: modbus_controller
modbus_controller_id: epever
id: generated_energy_today
name: "Generated energy today"
address: 0x330C
register_type: read
value_type: U_DWORD_R
accuracy_decimals: 0
unit_of_measurement: "Wh"
on_value:
then:
- sensor.template.publish:
id: generated_charge_today
state: !lambda "return x/12.0;"
filters:
- multiply: 10.0
device_class: energy
- platform: modbus_controller
modbus_controller_id: epever
id: generated_energy_month
name: "Generated energy month"
address: 0x330E
register_type: read
value_type: U_DWORD_R
accuracy_decimals: 0
unit_of_measurement: "Wh"
filters:
- multiply: 10.0
device_class: energy
- platform: modbus_controller
modbus_controller_id: epever
id: generated_energy_year
name: "Generated energy year"
address: 0x3310
register_type: read
value_type: U_DWORD_R
accuracy_decimals: 1
unit_of_measurement: "kWh"
filters:
- multiply: 0.01
device_class: energy
- platform: modbus_controller
modbus_controller_id: epever
id: generated_energy_total
name: "Generated energy total"
address: 0x3312
register_type: read
value_type: U_DWORD_R
accuracy_decimals: 1
unit_of_measurement: "kWh"
device_class: "energy"
state_class: "total_increasing"
filters:
- multiply: 0.01
# Setting values
- platform: modbus_controller
modbus_controller_id: epever
id: battery_type
address: 0x9000
name: "Battery Type"
register_type: holding
value_type: U_WORD
skip_updates: 50
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: battery_capacity
address: 0x9001
name: "Battery Capacity"
unit_of_measurement: "Ah"
register_type: holding
value_type: U_WORD
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: temperature_compensation_coefficient
address: 0x9002
name: "Temperature compensation coefficient"
unit_of_measurement: "mV/°C/2V"
register_type: holding
value_type: U_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: high_voltage_disconnect
address: 0x9003
name: "High Voltage disconnect"
unit_of_measurement: "V"
accuracy_decimals: 1
register_type: holding
value_type: U_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: charging_limit_voltage
address: 0x9004
name: "Charging limit voltage"
unit_of_measurement: "V"
accuracy_decimals: 1
register_type: holding
value_type: U_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: over_voltage_reconnect
address: 0x9005
name: "Over voltage reconnect"
unit_of_measurement: "V"
accuracy_decimals: 1
register_type: holding
value_type: U_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: equalization_voltage
address: 0x9006
name: "Equalization voltage"
unit_of_measurement: "V"
accuracy_decimals: 1
register_type: holding
value_type: U_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: boost_voltage
address: 0x9007
name: "Boost voltage"
unit_of_measurement: "V"
accuracy_decimals: 1
register_type: holding
value_type: U_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: float_voltage
address: 0x9008
name: "Float voltage"
unit_of_measurement: "V"
accuracy_decimals: 1
register_type: holding
value_type: U_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: boost_reconnect_voltage
address: 0x9009
name: "Boost reconnect voltage"
unit_of_measurement: "V"
accuracy_decimals: 1
register_type: holding
value_type: U_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: low_voltage_reconnect
address: 0x900A
name: "Low voltage reconnect"
unit_of_measurement: "V"
accuracy_decimals: 1
register_type: holding
value_type: U_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: under_voltage_recover
address: 0x900B
name: "Under voltage recover"
unit_of_measurement: "V"
accuracy_decimals: 1
register_type: holding
value_type: U_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: under_voltage_warning
address: 0x900C
name: "Under voltage warning"
unit_of_measurement: "V"
accuracy_decimals: 1
register_type: holding
value_type: U_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: low_voltage_disconnect
address: 0x900D
name: "Low voltage disconnect"
unit_of_measurement: "V"
accuracy_decimals: 1
register_type: holding
value_type: U_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: discharging_limit_voltage
address: 0x900E
name: "Discharging limit voltage"
unit_of_measurement: "V"
accuracy_decimals: 1
register_type: holding
value_type: U_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: battery_temperature_warning_upper_limit
address: 0x9017
name: "Battery temperature warning upper limit"
unit_of_measurement: "°C"
register_type: holding
value_type: S_WORD
# new range add 'skip_updates' again
skip_updates: 50
filters:
- multiply: 0.01
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: battery_temperature_warning_lower_limit
address: 0x9018
name: "Battery temperature warning lower limit"
unit_of_measurement: "°C"
register_type: holding
value_type: S_WORD
filters:
- multiply: 0.01
entity_category: "diagnostic"
# - platform: modbus_controller
# modbus_controller_id: epever
# id: controller_inner_temperature_upper_limit
# address: 0x9019
# name: "Controller inner temperature upper limit"
# unit_of_measurement: "°C"
# register_type: holding
# value_type: S_WORD
# filters:
# - multiply: 0.01
# - platform: modbus_controller
# modbus_controller_id: epever
# id: controller_inner_temperature_upper_limit_recover
# address: 0x901A
# name: "Controller inner temperature upper limit recover"
# unit_of_measurement: "°C"
# register_type: holding
# value_type: S_WORD
# filters:
# - multiply: 0.01
# - platform: modbus_controller
# modbus_controller_id: epever
# id: power_component_temperature_upper_limit
# address: 0x901B
# name: "Power component temperature upper limit"
# unit_of_measurement: "°C"
# register_type: holding
# value_type: S_WORD
# filters:
# - multiply: 0.01
# - platform: modbus_controller
# modbus_controller_id: epever
# id: power_component_temperature_upper_limit_recover
# address: 0x901C
# name: "Power component temperature upper limit recover"
# unit_of_measurement: "°C"
# register_type: holding
# value_type: S_WORD
# filters:
# - multiply: 0.01
- platform: modbus_controller
modbus_controller_id: epever
id: length_of_night_minutes
address: 0x9065
internal: true
bitmask: 0xFF
unit_of_measurement: "m"
name: "Length of night-mins"
register_type: holding
value_type: U_WORD
entity_category: "diagnostic"
- platform: modbus_controller
modbus_controller_id: epever
id: length_of_night
address: 0x9065
bitmask: 0xFF00
unit_of_measurement: "m"
name: "Length of night"
register_type: holding
value_type: U_WORD
skip_updates: 50
filters:
- lambda: return id(length_of_night_minutes).state + ( 60 * x);
entity_category: "diagnostic"
binary_sensor:
- platform: modbus_controller
modbus_controller_id: epever
id: charging_input_volt_failure
name: "Charging Input Volt Failure"
register_type: read
address: 0x3201
bitmask: 0xC000
entity_category: "diagnostic"
switch:
- platform: modbus_controller
modbus_controller_id: epever
id: manual_control_load
register_type: coil
address: 2
name: "manual control the load"
bitmask: 1
- platform: modbus_controller
modbus_controller_id: epever
id: default_control_the_load
register_type: coil
address: 3
name: "default control the load"
bitmask: 1
- platform: modbus_controller
modbus_controller_id: epever
id: enable_load_test
register_type: coil
address: 5
name: "enable load test mode"
bitmask: 1
- platform: modbus_controller
modbus_controller_id: epever
id: force_load
register_type: coil
address: 6
name: "Force Load on/off"
bitmask: 1
text_sensor:
- platform: modbus_controller
modbus_controller_id: epever
name: "rtc_clock"
id: rtc_clock
internal: true
register_type: holding
address: 0x9013
register_count: 3
raw_encode: HEXBYTES
response_size: 6
# /*
# E20 Real time clock 9013 D7-0 Sec, D15-8 Min
# E21 Real time clock 9014 D7-0 Hour, D15-8 Day
# E22 Real time clock 9015 D7-0 Month, D15-8 Year
# */
on_value:
then:
- lambda: |-
ESP_LOGV("main", "decoding rtc hex encoded raw data: %s", x.c_str());
uint8_t h=0,m=0,s=0,d=0,month_=0,y = 0 ;
m = esphome::modbus_controller::byte_from_hex_str(x,0);
s = esphome::modbus_controller::byte_from_hex_str(x,1);
d = esphome::modbus_controller::byte_from_hex_str(x,2);
h = esphome::modbus_controller::byte_from_hex_str(x,3);
y = esphome::modbus_controller::byte_from_hex_str(x,4);
month_ = esphome::modbus_controller::byte_from_hex_str(x,5);
// Now check if the rtc time of the controller is ok and correct it
time_t now = ::time(nullptr);
struct tm *time_info = ::localtime(&now);
int seconds = time_info->tm_sec;
int minutes = time_info->tm_min;
int hour = time_info->tm_hour;
int day = time_info->tm_mday;
int month = time_info->tm_mon + 1;
int year = time_info->tm_year % 100;
// correct time if needed (ignore seconds)
if (d != day || month_ != month || y != year || h != hour || m != minutes) {
// create the payload
std::vector<uint16_t> rtc_data = {uint16_t((minutes << 8) | seconds), uint16_t((day << 8) | hour),
uint16_t((year << 8) | month)};
// Create a modbus command item with the time information as the payload
esphome::modbus_controller::ModbusCommandItem set_rtc_command = esphome::modbus_controller::ModbusCommandItem::create_write_multiple_command(epever, 0x9013, 3, rtc_data);
// Submit the command to the send queue
epever->queue_command(set_rtc_command);
ESP_LOGI("ModbusLambda", "EPSOLAR RTC set to %02d:%02d:%02d %02d.%02d.%04d", hour, minutes, seconds, day, month, year + 2000);
}
char buffer[20];
// format time as YYYY-mm-dd hh:mm:ss
sprintf(buffer,"%04d-%02d-%02d %02d:%02d:%02d",y+2000,month_,d,h,m,s);
id(template_rtc).publish_state(buffer);
- platform: template
name: "RTC Time Sensor"
id: template_rtc
- platform: modbus_controller
modbus_controller_id: epever
name: "rtc clock test 2"
id: rtc_clock_test2
internal: true
register_type: holding
address: 0x9013
register_count: 3
raw_encode: HEXBYTES
response_size: 6
- platform: modbus_controller
modbus_controller_id: epever
id: Battery_status_volt_text
bitmask: 7
register_type: read
address: 0x3200
raw_encode: HEXBYTES
name: Battery status voltage
lambda: |-
uint16_t value = modbus_controller::word_from_hex_str(x, 0);
switch (value) {
case 0: return std::string("Normal");
case 1: return std::string("Overvolt");
case 2: return std::string("Undervolt");
case 3: return std::string("Low Volt Disconnect");
case 4: return std::string("Fault");
default: return std::string("Unknown");
}
return x;
- platform: modbus_controller
modbus_controller_id: epever
id: Charger_status
name: "Charger status"
address: 0x3201
register_type: read
raw_encode: HEXBYTES
lambda: |-
uint16_t value = modbus_controller::word_from_hex_str(x, 0);
switch (value) {
case 0: return std::string("Standby");
case 1: return std::string("Running");
default: return std::string("Unknown");
}
return x;
# Enable logging
logger:
level: ERROR
# Enable Home Assistant API
api:
encryption:
key: "OiY201niA0wjIuFkhlnVsJ9lreslzLf1JnKowhlRQbg="
ota:
password: "dd593f1b767f8cc60b84844fd908d703"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
fast_connect: true
domain: .lan
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Solar-Monitor Fallback Hotspot"
password: "WAsnG7i7NOrM"
captive_portal:
@gilankpam
Copy link
Author

gilankpam commented Dec 22, 2023

Based on https://devices.esphome.io/devices/epever_mptt_tracer_an, added measure units & set view only settings as diagnostic
Settings are cleared upon restart, you need to edit the battery parameters on the on_boot section.

@wanball
Copy link

wanball commented Apr 23, 2024

Hello. Do you have any information about 24v 115A battery to recommend to me?

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