I need to enhance my YAML ESP32 EspHome configuration file bmssolar.yaml
(see the code below) with two functions (ideally, declared within the single existing YAML configuration file).
Context
-
My electricity provider only allows to feed in 4000W, and the inverter is also set to a feed-in power of 4000W. Therefore, I only want to charge the battery when the feed-in power reaches a value close to 4000W.
-
My battery charging current is a value read via Modbus „Netz-Leistung“ (“grid power”), and ranges from a minimum of 1A to a maximum of 25A. Currently, it is hardcoded in the YAML config file at 25.
Function 1
Variables:
- Be a global constant
feed_in_power_threshold
equal to4000W * 0.975
.
I want the Modbus „Netz-Leistung“ value to be periodically (every 30 seconds) compared with a decimal value equal to feed_in_power_threshold
.
While the Modbus „Netz-Leistung“ value is greater than the threshold, the variable should be increased by a delta 0.2A as long as it hasn’t reached the max constant value of 25A.
While the Modbus „Netz-Leistung“ value is less than the threshold, the variable should be decreased by a delta 0.2A as long as it hasn’t reached the min constant value of 1A.
I would also like to see the Modbus „Netz-Leistung“ value to be logged or printed out under ESPHome.
Function 2
Variables:
-
Be a global constant
battery_soc_threshold
equal to80%
. -
Be a global constant
high_power_threshold
equal to4000W * 0.9875
. -
Be a global constant
low_power_threshold
equal to4000W * 0.875
.
The value read via Modbus „SOC“ should be periodically (every 30 seconds) compared with battery_soc_threshold
.
While the Modbus „SOC“ is greater than battery_soc_threshold
, then:
-
While the Modbus „Netz-Leistung“ is greater than a numeric
high_power_threshold
, a GPIO should be set to high (a consumer should switch on) and remain high for at least 10 minutes. No new control should be performed within that sleep time. -
While the Modbus „Netz-Leistung“ is less than a numeric
low_power_threshold
, the GPIO should go low (the consumer should switch off) and remain low for at least 5 minutes. No new control should be performed within that sleep time.
Particular wishes
-
The code should contain no so-called magic numbers. Any value should be declared as a global constant or a global variable with a meaningful name.
-
Ideally, I want it all to hold within the single existing YAML configuration file.
Error messages I am getting
-
Component not found: automation
-
Component template cannot be loaded via YAML (no CONFIG_SCHEMA)
YAML config file
substitutions:
name: bmssolar
max_cycles: "6000.0"
tx_pin: GPIO1
rx_pin: GPIO3
feed_in_power_threshold: !lambda '4000 * 0.975'
battery_soc_threshold: !lambda '4000 * 0.8'
high_power_threshold: !lambda '4000 * 0.9875'
low_power_threshold: !lambda '4000 * 0.875'
delta_charging_current: 0.2
max_charging_current: 25
min_charging_current: 1
esphome:
name: bmssolar
friendly_name: bmssolar
esp32:
board: esp32dev
framework:
type: arduino
logger:
baud_rate: 0
globals:
- id: can_420_rx
type: int
restore_value: "no"
initial_value: "0"
- id: charge_status
type: "std::string"
restore_value: "no"
initial_value: '"Startup"'
- id: charging_current
type: float
restore_value: "no"
initial_value: "25"
button:
- platform: restart
name: Restart button
id: restart_button
internal: true
wifi:
ssid: null
password: null
ap:
ssid: BmsSolar Fallback Hotspot
password: null
api:
encryption:
key: null
ota:
password: null
uart:
id: uart_0
baud_rate: 9600
rx_buffer_size: 384
tx_pin: "${tx_pin}"
rx_pin: "${rx_pin}"
modbus:
id: modbus0
uart_id: uart_0
send_wait_time: 900ms
modbus_controller:
id: bms0
address: 247
modbus_id: modbus0
command_throttle: 900ms
update_interval: 30s
output:
- platform: gpio
pin: 2
id: led
inverted: false
switch:
- platform: gpio
pin: GPIO4
name: Test
id: Test
sensor:
- platform: modbus_controller
modbus_controller_id: bms0
id: power_sensor
name: Leistung
address: 35140
register_type: holding
value_type: S_WORD
unit_of_measurement: W
device_class: energy
state_class: measurement
accuracy_decimals: 0
filters:
- multiply: 1
- platform: modbus_controller
modbus_controller_id: bms0
id: soc_sensor
name: SOC
address: 37007
register_type: holding
value_type: S_WORD
unit_of_measurement: "%"
device_class: energy
state_class: measurement
accuracy_decimals: 0
filters:
- multiply: 1
- platform: modbus_controller
modbus_controller_id: bms0
name: Temperatur
address: 35174
register_type: holding
value_type: S_WORD
unit_of_measurement: "°C"
device_class: temperature
state_class: measurement
accuracy_decimals: 0
filters:
- multiply: 1
template:
- sensor:
- name: "Charging Current"
id: charging_current_sensor
unit_of_measurement: "A"
accuracy_decimals: 1
lambda: |-
float power = id(power_sensor).state;
float current = id(charging_current);
if (power > feed_in_power_threshold) {
if (current < max_charging_current) {
current += delta_charging_current;
}
} else if (power < feed_in_power_threshold) {
if (current > min_charging_current) {
current -= delta_charging_current;
}
}
id(charging_current) = current;
ESP_LOGD("charging_current", "Calculated charging current: %.1f", current);
return current;
automation:
- id: charge_control
alias: "Charge Control"
trigger:
- platform: time
interval: 30s
action:
- lambda: |-
float soc = id(soc_sensor).state;
float power = id(power_sensor).state;
if (soc > battery_soc_threshold && power > high_power_threshold) {
digitalWrite(GPIO_PIN, HIGH);
id(led).turn_on();
delay(600000); // 10 minutes in milliseconds
float new_power = id(power_sensor).state;
if (new_power < low_power_threshold) {
digitalWrite(GPIO_PIN, LOW);
id(led).turn_off();
delay(300000); // 5 minutes in milliseconds
}
} else {
digitalWrite(GPIO_PIN, LOW);
id(led).turn_off();
}