Shelly power plug S with esphome

To monitor the power usage of many of my devices I started looking into smart plugs and came across the “Shelly plug S”

advantages of this model:

  • cheap (€20 a piece at the time of writing)
  • ESP8266 used allows for reflashing with your own code
  • power monitoring and switchable

disadvantages:

  • only 10A rated
  • Accuracy is quite bad, even after calibration the values jump around
  • low update speed to accurately measure low power (explained why below)
  • wifi instead of Zwave or Zigbee (been stable for me but this depends on your wifi network)
  • Wifi antenna is not great but not terrible

How to program?

Opening it is easy, there is a screw hidden inside the ground plug, unscrew this and the front pops loose.
Be aware there is a small thermal pad that can fall out.

I got the pinout from this post on the HA forum.
I was able to flash the ESP by pushing Dupont wires which are also used with breadboards through the holes and keeping a bit of sideways pressure while flashing.
But because that method would always work well I switched over to using pogo pins with a header soldered on.

The hardware

The power plug uses the eps8266 as its main IC, and because there is a header that exposes the pins needed for programming, reprograming it is really easy.

The antenna is a flex pcb with a trace, this does work but does not offer the best connection, I have noticed it is slightly worse than a normal pcb antena as some esp dev boards use.

The HLW8012 IC is used for the energy monitoring, this IC can measure active power,voltage and current but does not calculate energy used, this has to be done in software.

The active power value is sent to the esp via a variable frequency from the HLW8012, so when the measured active power is low the output frequency is low as well. 12w is already only 1HZ, so if we would want to measure 1.2w it would take us 10 seconds to know that..
Because of that the update speed of the measured power can get really slow when trying to measure low power devices.

The current sense resistor used in the shelly plug is 1mΩ with an accuracy of 10-20%, if you want to be somewhat accurate I should suggest calibrating the plug before putting them to use.

The internal temperature is monitored with a NTC, this is really important for the safety of the device. when drawing large loads for longer duration the temperature can get dangerously high. I have experienced overtemperature when drawing a load of 2000W for 15 min.
The 2300W power rating of the plug cannot be sustained for long..

The software

Most of my code is based on the config found on the esphome devices forum, I made some adjustments to make it safer and adjust it to my liking.

One important change I made was adding an overcurrent protection before the esp devices forum had some code that did not have that present. When a large load is connected with a bad power factor the current can go well above the rated 10A while staying below the 2300w limit. The temperature protection might not trip fast enough if the overcurrent is large enough.

Each shelly plug has their own config that contains the name and some config and calibration data.

substitutions:
  devicename: shelly-ps-01
  channel_1: Relay

  max_power: "2200"

  # Higher value gives lower watt readout
  current_res: "0.001100"
  # Lower value gives lower voltage readout
  voltage_div: "1911"
  # Power does not seem to calculated with the calibrated voltage and current vallues, Power needs its own callibration
  Power_calibration_multiplier: "1.03888"

packages:
  base-config: !include x-shelly-ps-00-base-config.yaml
  debug-info: !include x-debug-info.yaml

This is the base config for the plugs containing all the sensor configuration.

substitutions:
  #filter settings
  window_size: "3"
  send_every: "1"
  send_first_at: "1"

  max_current: "10"
  max_temp: "70.0"

  update_interval: "3s" #update interval in seconds # low update interval will cause inacurate results, measurements are based on pulses # https://tinkerman.cat/post/hlw8012-ic-new-sonoff-pow
  update_interval_slow: "5s" #update interval in seconds

esphome:
  name: "${devicename}"

esp8266:
  board: esp01_1m

logger:

api:
  encryption:
    key: "ThPfR6f+epdPwN0bx63o4+yEfejlq4DP8juJfaNr0jE="

ota:
  password: "297e7ca2c43a39cf7c8cb62c808797b2"

wifi:
  networks:
  - ssid: !secret wifi_ssid
    password: !secret wifi_password
    #manual_ip:
    #  static_ip: "${static_ip}"
    #  gateway: 10.10.1.1
    #  subnet: 255.255.255.0
    #use_address: "${use_ip}"
  reboot_timeout: 120min

time:
  - platform: sntp
    id: my_time

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO13
      inverted: True
    name: "${devicename}_button"
    on_press:
      - switch.toggle: relay

#red led for status
status_led:
  pin:
    number: GPIO00
    inverted: True

#blue light to indicate power
output:
  - platform: gpio
    pin: GPIO02
    inverted: true
    id: led

#relay
switch:
  - platform: gpio
    pin: GPIO15
    id: relay
    restore_mode: RESTORE_DEFAULT_ON
    name: "${channel_1}"
    on_turn_on:
      - output.turn_on: led
    on_turn_off:
      - output.turn_off: led

sensor:
  # NTC Temperature
  - platform: ntc
    sensor: temp_resistance_reading
    name: ${devicename} temperature
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    icon: "mdi:thermometer"
    filters:
       - median:
          window_size: ${window_size}
          send_every: ${send_every}
          send_first_at: ${send_first_at}
    calibration:
      b_constant: 3350
      reference_resistance: 10kOhm
      reference_temperature: 298.15K
    on_value_range:
      - above: ${max_temp}
        then:
          - switch.turn_off: relay
          - homeassistant.service:
              service: persistent_notification.create
              data:
                title: Message from ${devicename}
              data_template:
                message: Switch turned off because temperature exceeded ${max_temp}°C
  - platform: resistance
    id: temp_resistance_reading
    sensor: temp_analog_reading
    configuration: DOWNSTREAM
    resistor: 32kOhm
  - platform: adc
    id: temp_analog_reading
    pin: A0
    update_interval: ${update_interval_slow}

  - platform: hlw8012
    model: BL0937
    sel_pin:
      number: GPIO12
      inverted: true
    cf_pin: GPIO05
    cf1_pin: GPIO14
    current_resistor: ${current_res}
    voltage_divider: ${voltage_div}
    current:
      name: "${channel_1} current"
      unit_of_measurement: "A"
      accuracy_decimals: 1
      icon: mdi:flash-outline
      filters:
       - median:
          window_size: ${window_size}
          send_every: ${send_every}
          send_first_at: ${send_first_at}
      on_value_range:
        - above: ${max_current}
          then:
            - switch.turn_off: relay
            - homeassistant.service:
                service: persistent_notification.create
                data:
                  title: Message from ${devicename}
                data_template:
                  message: Switch turned off because current exceeded ${max_current}A
    voltage:
      name: "${channel_1} voltage"
      unit_of_measurement: "V"
      icon: mdi:flash-outline
      accuracy_decimals: 0
      filters:
       - median:
          window_size: ${window_size}
          send_every: ${send_every}
          send_first_at: ${send_first_at}
    power:
      name: "${channel_1} power"
      id: power
      unit_of_measurement: "W"
      accuracy_decimals: 0
      filters:
       - multiply: ${Power_calibration_multiplier}
       - median:
          window_size: ${window_size}
          send_every: ${send_every}
          send_first_at: ${send_first_at}
      icon: mdi:flash-outline
      on_value_range:
        - above: ${max_power}
          then:
            - switch.turn_off: relay
            - homeassistant.service:
                service: persistent_notification.create
                data:
                  title: Message from ${devicename}
                data_template:
                  message: Switch turned off because power exceeded ${max_power}W
    change_mode_every: "2"
    update_interval: ${update_interval}

  - platform: total_daily_energy
    name: "${channel_1} daily energy"
    power_id: power
    filters:
      # Multiplication factor from W to kW is 0.001
      - multiply: 0.001
    unit_of_measurement: kWh

Author: Robin

I'm Robin Peeten, a science enthusiast specialized in electronics and IT. By working on a lot of personal projects I gathered a lot of knowledge and practical experience with the aforementioned subjects and more. Able to design and repair electronic and electrical systems, and work as a sysadmin for professional computer systems and server gear. Take a look at my project list for examples.

1 thought on “Shelly power plug S with esphome

  1. Jurgen says:

    Great manual!

    With this clear guidelines and code I had my shelly plug working on the 1st go.

    Thanks!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

WordPress Appliance - Powered by TurnKey Linux