Cheap energy monitor with CT clamp, Wemos D1 mini

0. Safety notice

You will be working near mains voltage, so stay alert and only proceed if you know what you are doing. Get help from a professional if you feel uncomfortable at any moment. Safety first!

1. Resources

This project is based on the excellent guide from OpenEnergyMonitor
https://learn.openenergymonitor.org/electricity-monitoring/ct-sensors/interface-with-arduino

Have a look on the main component – SCT013 https://www.mcielectronics.cl/website_MCI/static/documents/Datasheet_SCT013.pdf

2. What you need

SCT013-100A ($3): you can use different model with smaller capacity for higher resolution (30A or 50A). Voltage type recommended. (Current type also works) https://www.aliexpress.com/item/4000680462559.html

Wemos D1 mini ($2) https://www.aliexpress.com/item/32831353752.html

3.5mm headphone jack

100k Ohm resistor x2: any value between 10k~470k shall work

33 Ohm resistor: any value between 20~200 Ohm shall work

10uF electrolytic capacitor, 0.1uF ceramic capacitor

Some cables to make connections: Recommend 22AWG single solid core wire

Perfboard or breadboard

Tools for soldering

Energy meter for calibration: I used a SJPM-C16

3. The circuit

Image from OpenEnrgyMonitor.org

Although SCT013 has an internal burden resistor (for voltage types) or voltage suppression diode (for current types), a burden resistor is recommended in case the internal protection component is faulty.

The basic concept is the CT clamp will provide an inductive voltage proportional to the current flowing through the clamped wire, and the circuit converts it into a safe positive voltage that can be read by an analog pin of your ESP8266.

R1 and R2 should be same values so that the maximum voltage is halved. However SCT013-100A voltage type has a max voltage of 1V, so this is not actually needed.

Electrolytic capacitors (C1) have polarity, so check the (-) sign on the side of the capacitor.

Ceramic capacitors do not have polarity, and I added one in parallel to the burden resistor. Based on recommendations from https://www.casler.org/wordpress/low-current-measurement-performance-of-the-sct013/ Needed to filter out high frequency noise from the CT clamp.

My setup on a perfboard
Used pin headers to make the ESP swappable

4. Temporary firmware for calibration

esphome:
  name: energy-meter
  platform: ESP8266
  board: d1_mini

logger:

api:

ota:
  password: !secret password

wifi:
  networks:
  - ssid: !secret ssid
    password: !secret password
  - ssid: !secret ssid2
    password: !secret password2
  ap:
    ssid: "energy_meter_fallback"
    password: !secret ap_password

captive_portal:

sensor:
  - platform: ct_clamp
    sensor: adc_sensor
    name: "Test Current"
    update_interval: 10s
  - platform: adc
    pin: A0
    id: adc_sensor
    internal: true
    update_interval: 10s

This firmware will attempt to read the voltage at the A0 pin and convert it into a current reading from the CT clamp in Amps. However it will be off by several folds, so a calibration step is needed.

5. Calibration

Clamp on a single strand, not the whole thing
Using a reference energy meter for calibration

Safety note!! Always plug the CT clamp to the circuit board before clamping, so that the burden resistor can protect you from inductive spikes of electricity! (SCT013 has internal protection components, but you never know)

Peel off the outermost insulation to expose the 2 or 3 strands of wires inside a extension cord you don’t mind throwing away. Then, grab a high burden load for calibration. A device like an electric heater or kettle is recommended since it is a pure resistive load. By changing the heater level, I got the ADC readout values for 3.9A, 5.7A, 9.45A, which were 0.00747, 0.01148, 0.1910A.

Although I measured 5 values, the larger 3 values were in the actual range I would encounter while monitoring the power consumption of the whole house. (I would never read 0A unless I pull down the breaker) So I used the 3 higher measurements from my electric heater for calibration. I would recommend to get at least 3 readings and plot out to see if the data is reliable

6. The final ESPHome firmware

esphome:
  name: energy-meter
  platform: ESP8266
  board: d1_mini

logger:

api:

ota:
  password: !secret password

wifi:
  networks:
  - ssid: !secret ssid
    password: !secret password
  - ssid: !secret ssid1
    password: !secret password1
  - ssid: !secret ssid2
    password: !secret password2
  ap:
    ssid: "energy_meter_fallback"
    password: !secret ap_password

captive_portal:

sensor:
  - platform: ct_clamp
    id: ct_clamp_power
    sensor: adc_sensor
    name: "Realtime Power"
    update_interval: 4s
    accuracy_decimals: 0
    filters:
    - calibrate_linear:
      - 0.00747 -> 3.90
      - 0.01148 -> 5.70
      - 0.01910 -> 9.45
    - median:
        window_size: 3
        send_every: 3
        send_first_at: 3
    - lambda: return x * 220;
    unit_of_measurement: W
    state_class: measurement
    device_class: power
  - platform: adc
    pin: A0
    id: adc_sensor
    internal: true
  - platform: total_daily_energy
    name: "ESPHome daily energy"
    power_id: ct_clamp_power
    filters:
    - multiply: 0.001
    unit_of_measurement: kWh

time:
  - platform: homeassistant
    id: homeassistant_time

Type in the numbers for calibration under filters – calibrate_linear.

I used a median filter to filter out any erratic readings (which happened if you physically disturbed the case of the ESP)

Multiplied with 220V to convert Amps to Watts. I didn’t care about the amperage, but wanted to monitor power.

I also added a TOTAL DAILY ENERGY sensor to integrate Wattage into kWh, and feed the value into a monthly utility_meter in home assistant.

Time platform is required to use the total_daily_energy platform sensor.

7. Installing the clamp

Safety note!! Even if you pull down the breaker, the wires upstream to your main breaker is still hot!

Cut the mains power and clamp one of the two main wires. Make sure the CT clamp is connected to the circuit, so that the burden resistor can protect you from inductive electric spikes when you switch the breaker back on.

8. Add monthly energy usage and prediction sensors to HA

configuration.yaml: I am using separate yaml files for sensor and utility_meter

sensor: !include sensors.yaml
utility_meter: !include utility_meters.yaml

utility_meters.yaml

energy_monthly:
  source: sensor.realtime_energy
  cycle: monthly

sensors.yaml

# Monthly Energy Consumption Prediction
- platform: template
  sensors:
    energy_monthly_prediction:
      unique_id: energy_monthly_prediction
      friendly_name: Electricity Monthly Prediction
      value_template: >
        {{ (states('sensor.energy_monthly')|float / (as_timestamp(now()) - as_timestamp(state_attr('sensor.energy_monthly', 'last_reset'))) * 86400 * 30)|round }}
      unit_of_measurement: kWh
      icon_template: mdi:chart-histogram
      device_class: energy

9. Results

Energy related sensors displayed on Lovelace UI
Viewed on Home Assistant energy tab
Not pretty, but it works
3D printed case

10. Conclusions

Since this setup only monitors current and not voltage, an assumes power factor (cosφ) of 1. So the actual unit of the measurement should be VA instead of W, but this was ignored for my convenience. Most household appliances have a power factor over 0.9 (Korean industrial standards certified), and voltage is rather stable (at least for the Korean power grid) so the final values will off by 10% at most. I would say it is a price I would willingly pay considering how cheap this setup is.

CC BY-NC-SA 4.0 This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Leave a Comment

Time limit is exhausted. Please reload CAPTCHA.