Hi community,
I set up home assistant to track solar/windpower production and consumption of the whole farm.
I use a Shelly 3EM for reading energy & power import and export (power-flow with positive or negative values).
Then I have templates that calculate the used power and the generated power, added up in Watts over all phases.
I built some ESPhome hardware for measurements based on the PZEM-004, but used also Tasmota plugs temporarely for reading energy production.
Also I made a power controller. The esp8266 outputs a pwm signal, which feeds a dimmer which is capable to regulate a few kilkowatts.
The ESP gets a power value from HA and controlls the power of an heating element.
Also the esp runs a service, where i can send an positive or negative offset to the actual power.
That was a long way, I worked several days to get it running and to calibrate. My knopwledge in coding is very basic.
All works fine so far.
The calibration is not very exact, I think because of voltage differences of the net and deviation of the dimmer because of heating up.
Because its a phase cutting dimmer, the power output is also not linear to the pwm-input.
But I’m inside 10% accuracy.
The YAML of the ESP might be interesting for some:
esphome:
name: leistungssteller
friendly_name: Leistungssteller
esp8266:
board: esp01_1m
# Enable logging
logger:
level: DEBUG
# Enable Home Assistant API
api:
encryption:
key: "xxxxxxxxxxxxxxxxxxxxxx"
services:
- service: adjust_power
variables:
offset: float
then:
- lambda: |-
if ((id(output_power).state) + offset >= id(max_power).state)
{ id(output_power).publish_state(id(max_power).state); }
if ((id(output_power).state) + offset <= 0)
{ id(output_power).publish_state(0); }
else
{ id(output_power).publish_state(id(output_power).state + offset); }
ota:
wifi:
ssid: "xxxxxxxxxxxxxxxxxxxx"
password: ""
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "xxxxxxxxxxx"
password: "xxxxxxxx"
captive_portal:
output:
- platform: esp8266_pwm
pin: GPIO16
frequency: 1000 Hz
id: pwm_output
inverted: True
min_power: 0.20
max_power: 0.95
zero_means_zero: True
sensor:
- platform: homeassistant
name: "Sollwert"
entity_id: input_number.dumpload_power
id: sollwert_vorgabe
icon: "mdi:radiator"
device_class: "power"
unit_of_measurement: "W"
accuracy_decimals: 0
internal: True
on_value:
then:
- lambda: |-
id(output_power).publish_state(x);
# - platform: homeassistant
# entity_id: sensor.3phase_meter_pzem_pzem_004t_v3_power
# id: power_flow
- platform: template
name: "Maximalleistung"
id: max_power
lambda: 'return 2120;'
device_class: "power"
unit_of_measurement: "W"
- platform: template
name: "Leistung"
id: output_power
device_class: "power"
unit_of_measurement: "W"
on_value:
then:
- lambda: |-
id(pwm).publish_state(x);
- platform: template
name: "PWM output"
id: pwm
accuracy_decimals: 3
icon: "mdi:pulse"
filters:
- calibrate_polynomial:
degree: 3
datapoints:
- 0 -> 0
- 2 -> 100
- 36 -> 150
- 59 -> 200
- 110 -> 300
- 182 -> 400
- 285 -> 500
- 407 -> 600
- 550 -> 700
- 708 -> 800
- 875 -> 900
- 1050 -> 1000
- 1370 -> 1200
- 1500 -> 1300
- 1650 -> 1400
- 1850 -> 1600
- 2000 -> 1800
- 2120 -> 1900
- lambda: 'return x / id(max_power).state;'
on_value:
then:
- lambda: |-
id(pwm_output).set_level(x);
Now im looking for an automation: The goal is to use up most of the leftover energy in several dump loads in a cascade, each with its own ESPhome dimmer.
Later the same could be used to control an charger.
This is how I made it now via 2 automations in the automation dialog:
- id: '1679041958358'
alias: Dumpload hoch
description: ''
trigger:
- platform: numeric_state
entity_id: sensor.power_flow
for:
hours: 0
minutes: 0
seconds: 0
below: -100
condition:
- condition: numeric_state
entity_id: sensor.power_flow
below: -100
- condition: numeric_state
entity_id: sensor.leistungssteller_leistung
above: sensor.leistungssteller_maximalleistung
action:
- repeat:
while:
- condition: numeric_state
entity_id: sensor.power_flow
below: -100
sequence:
- delay:
hours: 0
minutes: 0
seconds: 2
milliseconds: 0
- service: esphome.leistungssteller_adjust_power
data:
offset: 50
mode: single
- id: '1679074461130'
alias: Dumpload runter
description: ''
trigger:
- platform: numeric_state
entity_id: sensor.power_flow
for:
hours: 0
minutes: 0
seconds: 0
above: -50
enabled: true
condition:
- condition: numeric_state
entity_id: sensor.power_flow
above: -50
enabled: true
- condition: numeric_state
entity_id: sensor.leistungssteller_leistung
above: 0
action:
- repeat:
while:
- condition: numeric_state
entity_id: sensor.power_flow
above: -50
sequence:
- service: esphome.leistungssteller_adjust_power
data:
offset: -50
- delay:
hours: 0
minutes: 0
seconds: 2
milliseconds: 0
mode: single
It works, but quite slow!
And somehow I think its not a good way to do.
If I reduce the delay, the power goes to much up and down, because the power_flow entity has some lag.
I also tried the PID-function in ESPhome, but I could not get this working. I think its the wrong application for this.
Whats a good solution for this? I’m really interested how other users would realize this.
Also with (later) distributed loads with priorities and some logic. We have different water heaters etc.
Thanks for advice!
Also for links to similar projects