yaml layout updates to v1.x
This commit is contained in:
@@ -1,15 +1,30 @@
|
||||
##########################################################################################
|
||||
##########################################################################################
|
||||
# MAIN HOUSE 3 PHASE POWER MONITOR
|
||||
# Power Monitor using 3x PZEM004 for 3 phase monitoring plus energy monitoring for 32A EV Charger
|
||||
#:########################################################################################:#
|
||||
# TITLE: MAIN HOUSE 3 PHASE POWER MONITOR
|
||||
# zorruno.com layout v1.1 2026
|
||||
#:########################################################################################:#
|
||||
# REPO:
|
||||
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-mainpowermonitor.yaml
|
||||
#:########################################################################################:#
|
||||
# VERSIONS:
|
||||
# v1.3 2026-02-25 Updated yaml to zorruno layout V1.1
|
||||
# v1.2 2026-02-25 Updated yaml to zorruno layout V1.1. Added EV charging binary sensor
|
||||
# and EV power rolling average (default 5 min). Clarified EV pulse notes.
|
||||
# v1.1 2026-02-21 Fix globals array init compile error, reduce flash writes (globals update_interval)
|
||||
# v1.0 2026-02-21 Initial Version
|
||||
#:########################################################################################:#
|
||||
# HARDWARE:
|
||||
# - Wemos D1 mini (ESP8266)
|
||||
# - 3x PZEM-004T V3 (Modbus, 9600 baud)
|
||||
# - DHT11 (GPIO2)
|
||||
# - EV pulse input (GPIO14)
|
||||
#:########################################################################################:#
|
||||
# OPERATION NOTES:
|
||||
# - Power Monitor using 3x PZEM-004T V3 (Modbus) for 3-phase monitoring
|
||||
# - Pulse input energy monitoring for 32A EV Charger (2 Wh per pulse)
|
||||
# - Adds a 5 minute rolling average for EV power to avoid spiky readings at low loads
|
||||
# - Adds a binary sensor to indicate when the EV charger is operating (threshold configurable)
|
||||
#
|
||||
# Hardware: Wemos D1 mini (ESP8266) + 3x PZEM-004T V3 (Modbus) + DHT11 + EV Pulse Input
|
||||
#
|
||||
# V1.1 2026-02-21 Fix globals array init compile error, reduce flash writes (globals update_interval)
|
||||
# V1.0 2026-02-21 Initial Version
|
||||
#
|
||||
# NOTES
|
||||
# - PZEM-004T V3 uses Modbus over UART at 9600 baud.
|
||||
# NOTES:
|
||||
# - UART is on GPIO1 (TX) and GPIO3 (RX). Logger UART is disabled (baud_rate: 0).
|
||||
# - You will usually need to disconnect PZEM UART wires while flashing via USB.
|
||||
# - DHT11 is on GPIO2 (boot-strap pin and D1 mini onboard LED pin). Usually OK, but if you ever
|
||||
@@ -17,23 +32,35 @@
|
||||
# - PZEM "energy" from ESPHome pzemac is in Wh, converted to kWh in this YAML.
|
||||
# - Phase mapping requested: Red=0, Yellow=1, Blue=2 (Tasmota-style). In ESPHome pzemac Modbus
|
||||
# addresses must be 0x01..0xF7, so this YAML maps to Red=0x01, Yellow=0x02, Blue=0x03.
|
||||
# - 365-day history array is RAM-only (not restored) to avoid ESP8266 restore limits and flash wear.
|
||||
##########################################################################################
|
||||
##########################################################################################
|
||||
# - EV pulse power at very low load is inherently "chunky" due to 2 Wh pulses. Energy totals
|
||||
# remain accurate. Rolling average reduces spikes but can still read 0 W between infrequent pulses.
|
||||
#:########################################################################################:#
|
||||
# OFFLINE NOTES:
|
||||
# a) Home Assistant OFFLINE, WiFi OK
|
||||
# - Device continues measuring power, energy, and pulses locally.
|
||||
# - MQTT/API publishing will fail until HA is back.
|
||||
# b) WiFi OFFLINE (LAN down), Device powered
|
||||
# - No SNTP updates, so time may become invalid or drift (depending on last sync).
|
||||
# - Power and energy totals continue accumulating, but period rollovers (today/month/year)
|
||||
# will not update unless time is valid.
|
||||
# c) Entire WiFi/Network OFFLINE
|
||||
# - Accurate time IS needed for daily/monthly/year rollovers (SNTP required for correct period boundaries).
|
||||
# - Loss of network will drift the timeclocks; time of day can be reset by powering off then on again at 12pm (midday)
|
||||
#:########################################################################################:#
|
||||
|
||||
##########################################################################################
|
||||
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
# SUBSTITUTIONS: Specific device variable substitutions
|
||||
#:########################################################################################:#
|
||||
substitutions:
|
||||
# Device Naming
|
||||
device_name: "esp-mainpowermonitor"
|
||||
friendly_name: "Main House 3 Phase Power Monitor"
|
||||
description_comment: "Power Monitor using 3x PZEM004 for 3 phase monitoring plus energy monitoring for 32A EV Charger"
|
||||
description_comment: "Power Monitor using 3x PZEM004 for 3 phase monitoring plus energy monitoring for 32A EV Charger (Layout V1.1)"
|
||||
device_area: "Data Cupboard"
|
||||
|
||||
# Project Naming
|
||||
project_name: "Wemos.D1Mini PZEM-004T V3 3-Phase Power Monitor"
|
||||
project_version: "v1.1"
|
||||
project_version: "v1.3"
|
||||
|
||||
# Passwords
|
||||
api_key: !secret esp-api_key
|
||||
@@ -45,10 +72,6 @@ substitutions:
|
||||
# Don't forget to switch it back when changed.
|
||||
current_ip_address: ${static_ip_address}
|
||||
|
||||
# MQTT Controls
|
||||
#mqtt_device_name: "main-house-3phase-power"
|
||||
#mqtt_main_topic: "${mqtt_command_main_topic}/${mqtt_device_name}"
|
||||
|
||||
# Device Settings
|
||||
log_level: "ERROR"
|
||||
pzem_update_interval: "10s"
|
||||
@@ -70,6 +93,20 @@ substitutions:
|
||||
ev_pulse_filter_ms: "50ms" # Debounce / filter
|
||||
ev_pulse_pin_mode: "INPUT_PULLUP"
|
||||
|
||||
# EV Charging Detection (Averaged power + binary sensor)
|
||||
# Minimum EV charging power threshold (W) for binary sensor
|
||||
# NOTE: Pick a value comfortably above idle (idle can be ~0.2 kWh/day = very infrequent pulses).
|
||||
ev_charging_min_power_w: "300"
|
||||
|
||||
# Rolling average window - configuration notes:
|
||||
# - Substitutions are string replacements, so window samples must be updated manually if you change times.
|
||||
# - window_samples = (avg_minutes * 60) / sample_interval_seconds
|
||||
ev_power_avg_window_minutes: "5" # informational
|
||||
ev_power_avg_sample_interval: "10s"
|
||||
ev_power_avg_sample_interval_seconds: "10" # must match the value above
|
||||
ev_power_avg_window_samples: "30" # 5 min @ 10s = 30 samples
|
||||
ev_power_avg_buffer_size: "180" # ring buffer >= window_samples (180 @ 10s = 30 minutes)
|
||||
|
||||
# Names - PZEM (per phase)
|
||||
pzem_red_v_name: "Main Power Red Voltage"
|
||||
pzem_red_i_name: "Main Power Red Current"
|
||||
@@ -109,6 +146,7 @@ substitutions:
|
||||
|
||||
# Names - EV Wallcharger
|
||||
ev_power_name: "EV Wallcharger Power"
|
||||
ev_charging_name: "EV Wallcharger Charging"
|
||||
ev_total_energy_name: "EV Wallcharger Total Energy"
|
||||
ev_today_name: "EV Wallcharger Energy Today"
|
||||
ev_yesterday_name: "EV Wallcharger Energy Yesterday"
|
||||
@@ -122,9 +160,9 @@ substitutions:
|
||||
hum_name: "Main Power Monitor Humidity"
|
||||
dew_name: "Main Power Monitor Dew Point"
|
||||
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
# PACKAGES: Included Common Packages
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
packages:
|
||||
#### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode ####
|
||||
common_wifi: !include
|
||||
@@ -154,9 +192,10 @@ packages:
|
||||
diag_basic: !include common/include_basic_diag_sensors.yaml
|
||||
diag_more: !include common/include_more_diag_sensors.yaml
|
||||
|
||||
##########################################################################################
|
||||
# ESPHome
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
# ESPHOME:
|
||||
# https://esphome.io/components/esphome.html
|
||||
#:########################################################################################:#
|
||||
esphome:
|
||||
name: "${device_name}"
|
||||
friendly_name: "${friendly_name}"
|
||||
@@ -172,9 +211,10 @@ esphome:
|
||||
- delay: 3s
|
||||
- script.execute: rollover_check
|
||||
|
||||
##########################################################################################
|
||||
# ESP Platform and Framework
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
# ESP PLATFORM AND FRAMEWORK:
|
||||
# https://esphome.io/components/esp8266/
|
||||
#:########################################################################################:#
|
||||
esp8266:
|
||||
board: d1_mini
|
||||
restore_from_flash: true
|
||||
@@ -185,16 +225,17 @@ preferences:
|
||||
mdns:
|
||||
disabled: false
|
||||
|
||||
##########################################################################################
|
||||
# LOGGING
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
# LOGGING:
|
||||
# https://esphome.io/components/logger.html
|
||||
#:########################################################################################:#
|
||||
logger:
|
||||
level: "${log_level}"
|
||||
baud_rate: 0
|
||||
|
||||
##########################################################################################
|
||||
# UART + MODBUS (PZEM-004T V3)
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
# UART + MODBUS (PZEM-004T V3):
|
||||
#:########################################################################################:#
|
||||
uart:
|
||||
id: uart_pzem_bus
|
||||
tx_pin: GPIO1
|
||||
@@ -205,9 +246,9 @@ modbus:
|
||||
id: modbus_pzem_bus
|
||||
send_wait_time: 200ms
|
||||
|
||||
##########################################################################################
|
||||
# GLOBALS (Energy rollovers + 365-day history + temp min/max)
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
# GLOBALS (Energy rollovers + 365-day history + temp min/max):
|
||||
#:########################################################################################:#
|
||||
globals:
|
||||
# Date tracking for rollovers (restored)
|
||||
- id: g_last_day
|
||||
@@ -320,6 +361,25 @@ globals:
|
||||
update_interval: ${globals_save_interval_pulses}
|
||||
initial_value: "0"
|
||||
|
||||
# EV rolling average power (RAM only)
|
||||
- id: g_ev_power_avg_w
|
||||
type: float
|
||||
restore_value: no
|
||||
initial_value: "0.0"
|
||||
|
||||
# EV pulse history ring buffer for rolling average (RAM only)
|
||||
- id: g_ev_pulses_hist
|
||||
type: uint32_t[${ev_power_avg_buffer_size}]
|
||||
restore_value: no
|
||||
- id: g_ev_pulses_hist_index
|
||||
type: int
|
||||
restore_value: no
|
||||
initial_value: "0"
|
||||
- id: g_ev_pulses_hist_count
|
||||
type: int
|
||||
restore_value: no
|
||||
initial_value: "0"
|
||||
|
||||
# Temperature min/max tracking (RAM ONLY - not restored, gentler on flash)
|
||||
- id: g_temp_today_min
|
||||
type: float
|
||||
@@ -357,18 +417,35 @@ globals:
|
||||
restore_value: no
|
||||
initial_value: "-9999.0"
|
||||
|
||||
##########################################################################################
|
||||
# INTERVAL (periodic rollover checks)
|
||||
# NOTE: common_sntp may define its own interval. That is OK.
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
# INTERVAL (periodic rollover checks + EV rolling average updates):
|
||||
#:########################################################################################:#
|
||||
interval:
|
||||
- interval: "${rollover_check_interval}"
|
||||
then:
|
||||
- script.execute: rollover_check
|
||||
|
||||
##########################################################################################
|
||||
# SENSORS
|
||||
##########################################################################################
|
||||
- interval: "${ev_power_avg_sample_interval}"
|
||||
then:
|
||||
- script.execute: ev_power_avg_update
|
||||
|
||||
#:########################################################################################:#
|
||||
# BINARY SENSORS:
|
||||
#:########################################################################################:#
|
||||
binary_sensor:
|
||||
- platform: template
|
||||
name: "${ev_charging_name}"
|
||||
id: ev_wallcharger_charging
|
||||
device_class: power
|
||||
icon: "mdi:ev-station"
|
||||
lambda: |-
|
||||
const float p = id(ev_power_avg_w).state;
|
||||
if (isnan(p)) return false;
|
||||
return (p >= ${ev_charging_min_power_w});
|
||||
|
||||
#:########################################################################################:#
|
||||
# SENSORS:
|
||||
#:########################################################################################:#
|
||||
sensor:
|
||||
########################################################################################
|
||||
# PZEM-004T V3 - RED PHASE
|
||||
@@ -851,23 +928,16 @@ sensor:
|
||||
|
||||
########################################################################################
|
||||
# EV WALLCHARGER PULSE ENERGY (GPIO14)
|
||||
# - pulse_counter reports pulses/minute
|
||||
# - Power (W) = pulses_per_min * (Wh_per_pulse) * 60
|
||||
########################################################################################
|
||||
- platform: pulse_counter
|
||||
id: ev_pulse_rate_ppm
|
||||
internal: true
|
||||
pin:
|
||||
number: GPIO14
|
||||
mode: ${ev_pulse_pin_mode}
|
||||
inverted: false
|
||||
update_interval: 10s
|
||||
internal_filter: ${ev_pulse_filter_ms}
|
||||
name: "${ev_power_name}"
|
||||
unit_of_measurement: "W"
|
||||
accuracy_decimals: 0
|
||||
filters:
|
||||
- lambda: |-
|
||||
return x * (${ev_pulse_wh} * 60.0f);
|
||||
total:
|
||||
id: ev_pulses_raw_total
|
||||
internal: true
|
||||
@@ -882,6 +952,15 @@ sensor:
|
||||
id(g_ev_pulses_total_abs) += (raw - last);
|
||||
id(g_ev_pulses_raw_last) = raw;
|
||||
|
||||
- platform: template
|
||||
name: "${ev_power_name}"
|
||||
id: ev_power_avg_w
|
||||
unit_of_measurement: "W"
|
||||
accuracy_decimals: 0
|
||||
update_interval: "${ev_power_avg_sample_interval}"
|
||||
lambda: |-
|
||||
return id(g_ev_power_avg_w);
|
||||
|
||||
- platform: template
|
||||
name: "${ev_total_energy_name}"
|
||||
id: ev_total_energy_kwh
|
||||
@@ -957,9 +1036,9 @@ sensor:
|
||||
lambda: |-
|
||||
return id(g_ev_last_year_kwh);
|
||||
|
||||
##########################################################################################
|
||||
# SCRIPTS
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
# SCRIPTS:
|
||||
#:########################################################################################:#
|
||||
script:
|
||||
# Initialize RAM-only history arrays and counters
|
||||
- id: init_history_arrays
|
||||
@@ -972,6 +1051,59 @@ script:
|
||||
id(g_mains_daily_hist_index) = 0;
|
||||
id(g_mains_daily_hist_count) = 0;
|
||||
|
||||
// Init EV pulse history buffer so rolling average starts stable after boot
|
||||
const int ev_buf = ${ev_power_avg_buffer_size};
|
||||
const uint32_t p0 = id(g_ev_pulses_total_abs);
|
||||
|
||||
for (int i = 0; i < ev_buf; i++) {
|
||||
id(g_ev_pulses_hist)[i] = p0;
|
||||
}
|
||||
id(g_ev_pulses_hist_index) = 0;
|
||||
id(g_ev_pulses_hist_count) = ev_buf;
|
||||
id(g_ev_power_avg_w) = 0.0f;
|
||||
|
||||
# EV rolling average update (based on absolute pulse total)
|
||||
- id: ev_power_avg_update
|
||||
mode: queued
|
||||
then:
|
||||
- lambda: |-
|
||||
const int buf = ${ev_power_avg_buffer_size};
|
||||
int idx = id(g_ev_pulses_hist_index);
|
||||
if (idx < 0 || idx >= buf) idx = 0;
|
||||
|
||||
const uint32_t p_now = id(g_ev_pulses_total_abs);
|
||||
id(g_ev_pulses_hist)[idx] = p_now;
|
||||
|
||||
idx = (idx + 1) % buf;
|
||||
id(g_ev_pulses_hist_index) = idx;
|
||||
|
||||
if (id(g_ev_pulses_hist_count) < buf) id(g_ev_pulses_hist_count)++;
|
||||
|
||||
int win = ${ev_power_avg_window_samples};
|
||||
if (win < 1) win = 1;
|
||||
if (win > buf) win = buf;
|
||||
|
||||
if (id(g_ev_pulses_hist_count) < win) {
|
||||
return;
|
||||
}
|
||||
|
||||
int old_idx = idx - win;
|
||||
if (old_idx < 0) old_idx += buf;
|
||||
|
||||
const uint32_t p_old = id(g_ev_pulses_hist)[old_idx];
|
||||
const uint32_t dp = (p_now >= p_old) ? (p_now - p_old) : 0;
|
||||
|
||||
const float wh = ((float) dp) * (${ev_pulse_wh});
|
||||
const float seconds = ((float) win) * (${ev_power_avg_sample_interval_seconds});
|
||||
|
||||
if (seconds <= 0.0f) {
|
||||
id(g_ev_power_avg_w) = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
// W = Wh * 3600 / seconds
|
||||
id(g_ev_power_avg_w) = wh * 3600.0f / seconds;
|
||||
|
||||
# Period rollover check (day/month/year) for:
|
||||
# - Main total energy (sum of 3 PZEM channels)
|
||||
# - EV total energy (pulse derived)
|
||||
@@ -1117,9 +1249,42 @@ script:
|
||||
if (t < id(g_temp_month_min)) id(g_temp_month_min) = t;
|
||||
if (t > id(g_temp_month_max)) id(g_temp_month_max) = t;
|
||||
|
||||
##########################################################################################
|
||||
# SWITCHES
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
# SWITCHES:
|
||||
#:########################################################################################:#
|
||||
switch:
|
||||
- platform: restart
|
||||
name: "Main Power Monitor Restart"
|
||||
name: "Main Power Monitor Restart"
|
||||
|
||||
#:########################################################################################:#
|
||||
# ROLLBACK COPY (v1.1) - EV POWER SECTION (for quick revert)
|
||||
# NOTE: This is commented out. Remove the new EV blocks and uncomment to restore old behavior.
|
||||
#:########################################################################################:#
|
||||
#sensor:
|
||||
# - platform: pulse_counter
|
||||
# id: ev_pulse_rate_ppm
|
||||
# pin:
|
||||
# number: GPIO14
|
||||
# mode: ${ev_pulse_pin_mode}
|
||||
# inverted: false
|
||||
# update_interval: 10s
|
||||
# internal_filter: ${ev_pulse_filter_ms}
|
||||
# name: "${ev_power_name}"
|
||||
# unit_of_measurement: "W"
|
||||
# accuracy_decimals: 0
|
||||
# filters:
|
||||
# - lambda: |-
|
||||
# return x * (${ev_pulse_wh} * 60.0f);
|
||||
# total:
|
||||
# id: ev_pulses_raw_total
|
||||
# internal: true
|
||||
# on_value:
|
||||
# then:
|
||||
# - lambda: |-
|
||||
# uint32_t raw = (uint32_t) x;
|
||||
# uint32_t last = id(g_ev_pulses_raw_last);
|
||||
# if (raw < last) {
|
||||
# last = 0;
|
||||
# }
|
||||
# id(g_ev_pulses_total_abs) += (raw - last);
|
||||
# id(g_ev_pulses_raw_last) = raw;
|
||||
Reference in New Issue
Block a user