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

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.

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


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




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.
More from my site
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Leave a Comment