-
Notifications
You must be signed in to change notification settings - Fork 0
ESPHome
stefanschoemaker edited this page May 14, 2025
·
1 revision
Use this guide to connect to the inverter: https://github.com/klatremis/esphome-for-growatt#wiring-of-generic-esp32--ttl-module
I had success using this RS485 adapter: https://www.amazon.nl/dp/B09VGJCJKQ
Replace all values with ###SOMETHING####
esphome:
name: growatt
friendly_name: Omvormer
esp8266:
board: d1_mini
# Enable logging
logger:
baud_rate: 0
# Enable Home Assistant API
api:
encryption:
key: ###YOURAPIKEY###
ota:
- platform: esphome
password: ###YOURPASSWORD###
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Growatt Fallback Hotspot"
password: ###WIFIPASSWORD###
captive_portal:
substitutions:
name: growatt
device_name: Omvormer #name for all sensors in Home assistant
device_description: "Esphome for growatt"
modbus_controller_id: controller1
modbus_update_interval: 15s #normal update
skip_updates_slow: "6" #how many times to skip normal update for slow updating sensors
update_fast: 8s
update_slow: 60s
uart:
id: mod_bus
tx_pin: RX
rx_pin: TX
baud_rate: 9600
stop_bits: 1
modbus:
id: modbus1
# flow_control_pin: 4 #for use when you use a rs485 board without auto flow control. Like the rs485 max board.
modbus_controller:
- id: ${modbus_controller_id}
address: 0x1
modbus_id: modbus1
setup_priority: -10
update_interval: ${modbus_update_interval}
sensor:
- platform: modbus_controller
name: ${device_name} status_code
skip_updates: $skip_updates_slow
address: 0
register_type: "read"
internal: true
accuracy_decimals: 0
id: status
- platform: modbus_controller
name: "${device_name} Input Power"
address: 1
register_type: "read"
unit_of_measurement: kW
device_class: power
state_class: measurement
icon: mdi:solar-power-variant
value_type: U_WORD
accuracy_decimals: 3
filters:
- multiply: 0.0001
- platform: modbus_controller
name: "${device_name} PV1 voltage"
address: 3
register_type: "read"
unit_of_measurement: V
device_class: voltage
icon: mdi:flash
value_type: U_WORD
accuracy_decimals: 0
filters:
- multiply: 0.1
- platform: modbus_controller
name: "${device_name} PV1 current"
address: 4
register_type: "read"
unit_of_measurement: A
device_class: current
icon: mdi:flash
value_type: U_WORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
name: "${device_name} PV1 power"
id: pv1_power
address: 5
register_type: "read"
unit_of_measurement: kW
device_class: power
icon: mdi:flash
value_type: U_DWORD
accuracy_decimals: 3
filters:
- multiply: 0.0001
- platform: modbus_controller
name: "${device_name} PV2 voltage"
address: 7
register_type: "read"
unit_of_measurement: V
device_class: voltage
icon: mdi:flash
value_type: U_WORD
accuracy_decimals: 0
filters:
- multiply: 0.1
- platform: modbus_controller
name: "${device_name} PV2 current"
address: 8
register_type: "read"
unit_of_measurement: A
device_class: current
icon: mdi:flash
value_type: U_WORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
name: "${device_name} PV2 power"
id: pv2_power
address: 9
register_type: "read"
unit_of_measurement: kW
device_class: power
icon: mdi:flash
value_type: U_DWORD
accuracy_decimals: 3
filters:
- multiply: 0.0001
- platform: template
id: pv_power
name: "${device_name} PV Power"
unit_of_measurement: kW
device_class: power
state_class: measurement
icon: mdi:solar-power-variant
accuracy_decimals: 3
lambda: |-
return float((id(pv1_power).state + id(pv2_power).state));
filters:
# - throttle_average: 30s
- filter_out: nan
- platform: modbus_controller
name: "${device_name} Output power"
address: 35
register_type: "read"
unit_of_measurement: kW
device_class: power
state_class: measurement
icon: mdi:solar-power
value_type: U_DWORD
accuracy_decimals: 3
filters:
- multiply: 0.0001
# - throttle_average: 30s
- filter_out: nan
- platform: modbus_controller
name: "${device_name} Energy total"
skip_updates: $skip_updates_slow
address: 55
register_type: "read"
unit_of_measurement: kWh
state_class: total_increasing
device_class: energy
icon: mdi:solar-power
value_type: U_DWORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
name: "${device_name} PV1 energy total"
skip_updates: $skip_updates_slow
id: pv1_energy_total
address: 61
register_type: "read"
unit_of_measurement: kWh
state_class: total_increasing
device_class: energy
icon: mdi:solar-power
value_type: U_DWORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
name: "${device_name} PV2 energy total"
skip_updates: $skip_updates_slow
id: pv2_energy_total
address: 65
register_type: "read"
unit_of_measurement: kWh
state_class: total_increasing
device_class: energy
icon: mdi:solar-power
value_type: U_DWORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: template
id: pv_energy_total
name: "${device_name} PV Energy Total"
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
icon: mdi:solar-power-variant
accuracy_decimals: 1
lambda: |-
return float((id(pv1_energy_total).state + id(pv2_energy_total).state));
update_interval: ${update_slow}
- platform: modbus_controller
name: "${device_name} Temperature"
address: 93
register_type: "read"
unit_of_measurement: °C
device_class: temperature
entity_category: diagnostic
icon: mdi:thermometer
value_type: U_WORD
accuracy_decimals: 1
filters:
- multiply: 0.1
skip_updates: $skip_updates_slow
- platform: modbus_controller
name: "${device_name} Battery Discharging Power"
address: 1009
register_type: "read"
unit_of_measurement: kW
device_class: power
icon: mdi:battery-arrow-down
value_type: U_DWORD
accuracy_decimals: 3
filters:
- multiply: 0.0001
- platform: modbus_controller
name: "${device_name} Battery Charging Power"
address: 1011
register_type: "read"
unit_of_measurement: kW
device_class: power
icon: mdi:battery-arrow-up-outline
value_type: U_DWORD
accuracy_decimals: 3
filters:
- multiply: 0.0001
- platform: modbus_controller
name: "${device_name} Battery SoC"
skip_updates: $skip_updates_slow
address: 1014
register_type: "read"
unit_of_measurement: "%"
icon: mdi:home-battery
value_type: U_WORD
accuracy_decimals: 0
- platform: modbus_controller
name: "${device_name} AC Power to User Total"
address: 1021
register_type: "read"
unit_of_measurement: kW
device_class: power
state_class: measurement
icon: mdi:transmission-tower-export
value_type: U_DWORD
accuracy_decimals: 3
filters:
- multiply: 0.0001
- platform: modbus_controller
name: "${device_name} AC Power to Grid Total"
address: 1029
register_type: "read"
unit_of_measurement: kW
device_class: power
state_class: measurement
icon: mdi:transmission-tower-import
value_type: U_DWORD
accuracy_decimals: 3
filters:
- multiply: 0.0001
- platform: modbus_controller
name: "${device_name} INV Power to Local Load Total"
address: 1037
register_type: "read"
unit_of_measurement: kW
device_class: power
state_class: measurement
icon: mdi:home-import-outline
value_type: U_DWORD
accuracy_decimals: 3
filters:
- multiply: 0.0001
- platform: modbus_controller
name: "${device_name} Battery Temperature"
address: 1040
register_type: "read"
unit_of_measurement: °C
device_class: temperature
state_class: measurement
icon: mdi:thermometer
skip_updates: $skip_updates_slow
value_type: U_WORD
accuracy_decimals: 1
- platform: modbus_controller
name: "${device_name} Battery State"
skip_updates: $skip_updates_slow
address: 1041
register_type: "read"
icon: mdi:home-battery
value_type: U_WORD
- platform: modbus_controller
name: "${device_name} Energy to User Total"
skip_updates: $skip_updates_slow
address: 1046
register_type: "read"
unit_of_measurement: kWh
state_class: total_increasing
device_class: energy
icon: mdi:transmission-tower-export
value_type: U_DWORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
name: "${device_name} Energy to Grid Total"
skip_updates: $skip_updates_slow
address: 1050
register_type: "read"
unit_of_measurement: kWh
state_class: total_increasing
device_class: energy
icon: mdi:transmission-tower-import
value_type: U_DWORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
name: "${device_name} Battery Discharge Total"
skip_updates: $skip_updates_slow
address: 1054
register_type: "read"
unit_of_measurement: kWh
state_class: total_increasing
device_class: energy
icon: mdi:battery-arrow-down
value_type: U_DWORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
name: "${device_name} Battery Charge Total"
skip_updates: $skip_updates_slow
address: 1058
register_type: "read"
unit_of_measurement: kWh
state_class: total_increasing
device_class: energy
icon: mdi:battery-arrow-up-outline
value_type: U_DWORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
name: "${device_name} Local Load Total"
skip_updates: $skip_updates_slow
address: 1062
register_type: "read"
unit_of_measurement: kWh
state_class: total_increasing
device_class: energy
icon: mdi:home-import-outline
value_type: U_DWORD
accuracy_decimals: 1
filters:
- multiply: 0.1
number:
- platform: modbus_controller
name: "${device_name} Discharge SoC"
address: 1071
value_type: U_WORD
min_value: 0
max_value: 100
step: 1
skip_updates: $skip_updates_slow
- platform: modbus_controller
name: "${device_name} Discharge Power Rate Percentage"
address: 1070
value_type: U_WORD
min_value: 0
max_value: 100
step: 1
skip_updates: $skip_updates_slow
- platform: modbus_controller
name: "${device_name} Charge SoC"
address: 1091
value_type: U_WORD
min_value: 0
max_value: 100
step: 1
skip_updates: $skip_updates_slow
- platform: modbus_controller
name: "${device_name} Charge Power Rate Percentage"
address: 1090
value_type: U_WORD
min_value: 0
max_value: 100
step: 1
# - platform: modbus_controller
# name: "${device_name} Export Limit Power Rate Percentage"
# address: 123
# value_type: S_WORD
# min_value: -100.0
# max_value: 100.0
# step: 0.1
# lambda: |-
# // Convert the raw value (e.g., 1000) to a percentage (100.0)
# return x / 10.0;
# write_lambda: |-
# // Convert the percentage back to the raw value for Modbus (e.g., 100.0 to 1000)
# return x * 10;
- platform: modbus_controller
name: "Export Limit Power Rate Percentage"
address: 3
value_type: U_WORD
min_value: 0
max_value: 100
step: 1
- platform: modbus_controller
id: bat_first_start
address: 1100
value_type: U_WORD
internal: true
- platform: modbus_controller
id: bat_first_stop
address: 1101
value_type: U_WORD
internal: true
- platform: modbus_controller
id: bat_first_enable
address: 1102
value_type: U_WORD
internal: true
- platform: modbus_controller
id: grid_first_start
address: 1080
value_type: U_WORD
internal: true
- platform: modbus_controller
id: grid_first_stop
address: 1081
value_type: U_WORD
internal: true
- platform: modbus_controller
id: grid_first_enable
address: 1082
value_type: U_WORD
internal: true
- platform: modbus_controller
id: load_first_enable
address: 122
value_type: U_WORD
internal: true
select:
- platform: modbus_controller
name: "${device_name} AC Charging"
icon: mdi:battery-charging-100
address: 1092
value_type: U_WORD
optionsmap:
"Disabled": 0
"Enabled": 1
skip_updates: $skip_updates_slow
- platform: modbus_controller
name: "${device_name} Inverter Priority"
icon: mdi:arrow-decision-outline
id: inverter_priority
address: 1044
value_type: U_WORD
optionsmap:
"Load First": 0
"Battery First": 1
"Grid First": 2
skip_updates: $skip_updates_slow
- platform: modbus_controller
name: "Save Export limit to memory"
icon: mdi:memory
address: 2
value_type: U_WORD
optionsmap:
"Save to RAM": 0
"Save to EEPROM": 1
skip_updates: $skip_updates_slow
text_sensor:
- platform: template
name: "${device_name} Status state"
icon: mdi:eye
entity_category: diagnostic
lambda: |-
if ((id(status).state) == 1) {
return {"Normal"};
} else if ((id(status).state) == 0) {
return {"Standby"};
} else if ((id(status).state) == 2) {
return {"Discharge"};
} else if ((id(status).state) == 3) {
return {"Fault"};
} else if ((id(status).state) == 4) {
return {"Flash"};
} else if ((id(status).state) == 5) {
return {"PV Charging"};
} else if ((id(status).state) == 6) {
return {"AC Charging"};
} else if ((id(status).state) == 7) {
return {"Combined Charging"};
} else if ((id(status).state) == 8) {
return {"Combined Charging & Bypass"};
} else if ((id(status).state) == 9) {
return {"PV Charging & Bypass"};
} else if ((id(status).state) == 10) {
return {"AC Charging & Bypass"};
} else if ((id(status).state) == 11) {
return {"Bypass"};
} else if (id(status).state == 12) {
return {"PV Charge and Discharge"};
} else {
return {"Unknown"};
}
- platform: modbus_controller
name: "${device_name} Fault code"
skip_updates: $skip_updates_slow
address: 105
register_type: "read"
icon: mdi:eye
entity_category: diagnostic
raw_encode: HEXBYTES
lambda: |-
uint16_t value = modbus_controller::word_from_hex_str(x, 0);
switch (value) {
case 0: return std::string("No error");
case 24: return std::string("Auto test failed");
case 25: return std::string("No AC connection");
case 26: return std::string("PV isolation low");
case 27: return std::string("Residual I high");
case 28: return std::string("Output high DCI");
case 29: return std::string("PV voltage high");
case 30: return std::string("AC voltage out of range");
case 31: return std::string("AC frequency out of range");
case 32: return std::string("Module too hot");
// case 1~23 " Error: 99+x
default: return std::string("Fault code: " + to_string(value));
}
return x;
switch:
- platform: template
name: "${device_name} Battery First Mode"
icon: mdi:battery-clock
lambda: |-
return id(inverter_priority).state == "Battery First";
turn_on_action:
- number.set:
id: grid_first_start
value: 0
- delay: 100ms
- number.set:
id: grid_first_stop
value: 0
- delay: 100ms
- number.set:
id: grid_first_enable
value: 0 # Disable
- number.set:
id: bat_first_start
value: 1 # 00:01
- delay: 100ms
- number.set:
id: bat_first_stop
value: 5947 # 23:59
- delay: 100ms
- number.set:
id: bat_first_enable
value: 1 # Enable
turn_off_action:
- number.set:
id: bat_first_start
value: 0 # 00:00
- delay: 100ms
- number.set:
id: bat_first_stop
value: 0 # 00:00
- number.set:
id: bat_first_enable
value: 0 # Disable
optimistic: false
- platform: template
name: "${device_name} Grid First Mode"
icon: mdi:battery-clock
lambda: |-
return id(inverter_priority).state == "Grid First";
turn_on_action:
- number.set:
id: bat_first_start
value: 0 # 00:00
- delay: 100ms
- number.set:
id: bat_first_stop
value: 0 # 00:00
- number.set:
id: bat_first_enable
value: 0 # Disable
- number.set:
id: grid_first_start
value: 1 # 00:01
- delay: 100ms
- number.set:
id: grid_first_stop
value: 5947 # 23:59
- delay: 100ms
- number.set:
id: grid_first_enable
value: 1 # Enable
turn_off_action:
- number.set:
id: grid_first_start
value: 0
- delay: 100ms
- number.set:
id: grid_first_stop
value: 0
- delay: 100ms
- number.set:
id: grid_first_enable
value: 0 # Disable
optimistic: false
- platform: template
name: "${device_name} Load First Mode"
icon: mdi:battery-clock
lambda: |-
return id(inverter_priority).state == "Load First";
turn_on_action:
- number.set:
id: bat_first_start
value: 0 # 00:00
- delay: 100ms
- number.set:
id: bat_first_stop
value: 0 # 00:00
- number.set:
id: bat_first_enable
value: 0 # Disable
- number.set:
id: grid_first_start
value: 0 # 00:01
- delay: 100ms
- number.set:
id: grid_first_stop
value: 0 # 23:59
- delay: 100ms
- number.set:
id: load_first_enable
value: 1 # Enable
turn_off_action:
- number.set:
id: load_first_enable
value: 0 # Disable
optimistic: false