Skip to content

Instantly share code, notes, and snippets.

@CountParadox
Created July 24, 2023 00:50
Show Gist options
  • Save CountParadox/e17751f2ec3579476483f77d2e6a64cb to your computer and use it in GitHub Desktop.
Save CountParadox/e17751f2ec3579476483f77d2e6a64cb to your computer and use it in GitHub Desktop.
esphome:
name: sop-power-monitor
friendly_name: sop-power-monitor
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "XXX
ota:
password: "XXX"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Sop-Power-Monitor"
password: "XXX"
captive_portal:
color:
- id: my_red
red: 100%
green: 0%
blue: 0%
- id: my_yellow
red: 100%
green: 100%
blue: 0%
- id: my_green
red: 0%
green: 100%
blue: 0%
- id: my_blue
red: 23.92%
green: 65.1%
blue: 84.71%
- id: my_gray
red: 50%
green: 50%
blue: 50%
binary_sensor:
- platform: status
name: "Node Status"
id: system_status
- platform: gpio
pin:
number: GPIO0
inverted: true
mode:
input: true
pullup: true
name: "T-Display Button Input 0"
id: tdisplay_button_input_0
- platform: gpio
pin:
number: GPIO35
inverted: true
name: "T-Display Button Input 1"
id: tdisplay_button_input_1
# We can still control the backlight independently
switch:
- platform: gpio
pin: GPIO4
name: "Backlight"
id: backlight
time:
- platform: homeassistant
id: esptime
spi:
clk_pin: GPIO18
mosi_pin: GPIO19
font:
- file: "gfonts://Audiowide"
id: audiowide_48
size: 48
- file: "gfonts://Audiowide"
id: audiowide_20
size: 20
- file: "gfonts://Audiowide"
id: audiowide_18
size: 18
- file: "gfonts://Audiowide"
id: audiowide_14
size: 14
- file: "gfonts://Audiowide"
id: audiowide_12
size: 12
image:
- file: "bck_gauge.png"
id: background
type: RGB24
- file: mdi:lan-connect
id: connected
resize: 20x20
- file: mdi:wifi-remove
id: disconnected
resize: 20x20
display:
- platform: st7789v
model: TTGO TDisplay 135x240
backlight_pin: GPIO4
cs_pin: GPIO5
dc_pin: GPIO16
reset_pin: GPIO23
rotation: 90
pages:
- id: home
lambda: |-
it.image(0, 0, id(background));
// Header
it.print(2, 5, id(audiowide_14), id(my_gray), TextAlign::TOP_LEFT, "Smart Power-meter");
it.strftime(215, 5, id(audiowide_14), id(my_gray), TextAlign::TOP_RIGHT, "%H:%M", id(esptime).now());
if (id(system_status).state) {
it.image(240, 5, id(connected), ImageAlign::TOP_RIGHT);
} else {
it.image(240, 5, id(disconnected), ImageAlign::TOP_RIGHT);
}
// Values of current and daily consumed power
it.printf(5, 50 + 5, id(audiowide_20), id(my_gray), TextAlign::TOP_LEFT, "%.1fW", id(current_power).state*1000.0);
it.printf(5, 80 + 5, id(audiowide_20), id(my_gray), TextAlign::TOP_LEFT, "%.2fkW/h", id(daily_power).state);
it.printf(5, 110 + 5, id(audiowide_20), id(my_gray), TextAlign::TOP_LEFT, "%.2fAUD", id(daily_cost).state);
// Real time consumption indicator
float pi = 3.141592653589793;
float alpha = 4.71238898038469; // Defined as the gauge angle in radians (270deg)
float beta = 2*pi - alpha;
int radius = 42; // Radius of the gauge in pixels
int thick = 7; // Size of the marker
int needle_radius= 9;
int min_range = 0;
int max_range = 10;
int xc = 180;
int yc = 85;
float measured = id(current_power).state;
if (measured < min_range) {
measured = min_range;
}
if (measured > max_range) {
measured = max_range;
}
float val = (measured - min_range) / abs(max_range - min_range) * alpha;
int xc0 = static_cast<int>(xc);
int yc0 = static_cast<int>(yc);
int x0 = static_cast<int>(xc + radius * cos(pi / 2 + beta / 2 + val));
int y0 = static_cast<int>(yc + radius * sin(pi / 2 + beta / 2 + val));
int x1 = static_cast<int>(xc + needle_radius * cos(pi / 2 + beta / 2 + val + 0.1));
int y1 = static_cast<int>(yc + needle_radius * sin(pi / 2 + beta / 2 + val + 0.1));
int x2 = static_cast<int>(xc + needle_radius * cos(pi / 2 + beta / 2 + val - 0.1));
int y2 = static_cast<int>(yc + needle_radius * sin(pi / 2 + beta / 2 + val - 0.1));
int x3 = static_cast<int>(xc + needle_radius * cos(pi / 2 + beta / 2 + val + 0.2));
int y3 = static_cast<int>(yc + needle_radius * sin(pi / 2 + beta / 2 + val + 0.2));
int x4 = static_cast<int>(xc + needle_radius * cos(pi / 2 + beta / 2 + val - 0.2));
int y4 = static_cast<int>(yc + needle_radius * sin(pi / 2 + beta / 2 + val - 0.2));
int x5 = static_cast<int>(xc + needle_radius * cos(pi / 2 + beta / 2 + val));
int y5 = static_cast<int>(yc + needle_radius * sin(pi / 2 + beta / 2 + val));
it.line(x0, y0, x1, y1, id(my_blue));
it.line(x0, y0, x2, y2, id(my_blue));
it.line(x0, y0, x3, y3, id(my_blue));
it.line(x0, y0, x4, y4, id(my_blue));
it.line(x0, y0, x5, y5, id(my_blue));
sensor:
- platform: homeassistant
id: daily_cost
name: "Daily cost"
entity_id: sensor.total_daily_power_cost
# - platform: adc
# pin: A0
# id: LDR
# name: "LDR"
# update_interval: 5s
# on_value_range:
# - above: 0.1
# then:
# - switch.turn_on: backlight
# - below: 0.1
# then:
# - switch.turn_off: backlight
- platform: adc
pin: A3
id: Input_1
attenuation: 11db
update_interval: 1s
- platform: adc
pin: A4
id: Input_2
attenuation: 11db
update_interval: 1s
- platform: adc
pin: A5
id: Input_3
attenuation: 11db
update_interval: 1s
- platform: ct_clamp
sensor: Input_1
id: Probe_1
name: "Probe 1"
sample_duration: 200ms
update_interval: 1s
filters:
- calibrate_linear:
- 0 -> 0
- 0.042 -> 2.72
- platform: ct_clamp
sensor: Input_2
name: "Probe 2"
id: Probe_2
sample_duration: 200ms
update_interval: 1s
filters:
- calibrate_linear:
- 0 -> 0
- 0.033 -> 1.07
- platform: ct_clamp
sensor: Input_3
name: "Probe 3"
id: Probe_3
sample_duration: 200ms
update_interval: 1s
filters:
- calibrate_linear:
- 0 -> 0
- 0.022 -> 0.66
- platform: total_daily_energy
name: "Total Daily Power"
power_id: current_power
id: daily_power
- platform: template
id: current_power
name: "Measured Power"
lambda: return (id(Probe_1).state + id(Probe_2).state + id(Probe_3).state) * 230.0 / 1000; #Power = Current * Voltage
unit_of_measurement: 'kW'
update_interval: 5s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment