My electricity bill jumped almost 30% last winter, and I had absolutely no idea why. Was it the space heater? The old fridge? The workshop equipment I leave plugged in overnight? I had no clue, and neither did anyone else in the house. So instead of guessing, I built a small ESP32-based energy meter that shows exactly how much power is being drawn, in real time, on a little OLED screen sitting on my desk.
This isn't the fanciest energy monitor you'll find online — some builds use dedicated metering chips and cost more in parts. This is the version I'd recommend if you want something accurate enough to actually be useful, without needing an electrical engineering degree to build it.
Fair Warning Before You Start
This project involves working near mains voltage (110V or 220V, depending on where you live). The sensors themselves are designed to be safe when wired correctly, but you're still dealing with live household wiring. If you're not comfortable with that, or you're unsure about any step involving the current clamp or voltage sensor, please get help from someone with electrical experience, or stick to monitoring a single extension cord/appliance rather than your main panel. I'm not going to sugarcoat this one — take it seriously.
What You'll Need
- 1x ESP32 development board
- 1x ZMPT101B voltage sensor module (measures AC voltage safely through a transformer, so there's no direct electrical contact)
- 1x ACS712 current sensor (comes in 5A, 20A, or 30A versions — pick one based on what you're measuring; for a single appliance, the 20A version covers most household devices comfortably)
- 1x SSD1306 OLED display (128x64, I2C)
- Jumper wires and a breadboard
- A stable 5V power source
How the Measurement Actually Works
Here's the part that confused me when I first read about this: the ESP32 doesn't measure electricity directly. Instead, two sensors do the actual sensing, and the ESP32 just reads their analog output and does the math.
The ZMPT101B measures voltage by using a small internal transformer, which keeps the ESP32 electrically isolated from the mains line — this is the safety feature that makes it usable by hobbyists at all. The ACS712 measures current using something called the Hall effect, meaning it senses the magnetic field created by current flowing through a wire, again without direct electrical contact.
Multiply voltage by current, and you get power in watts. That's genuinely most of what's happening here — the rest is calibration and code.
Step 1: Wiring the Sensors
ZMPT101B (voltage sensor):
- VCC → ESP32 3.3V
- GND → GND
- OUT → GPIO 34 (an ADC-capable pin)
- The module's screw terminals connect across your AC live and neutral lines
ACS712 (current sensor):
- VCC → ESP32 5V
- GND → GND
- OUT → GPIO 36
- The sensor is wired in series with the live wire of whatever you're measuring, meaning the current has to physically pass through the sensor
OLED Display (SSD1306, I2C):
- VCC → 3.3V
- GND → GND
- SDA → GPIO 21
- SCL → GPIO 22
Step 2: Installing the Libraries
In the Arduino IDE, install Adafruit GFX Library and Adafruit SSD1306 through the Library Manager for the display. For the sensors, there are dedicated ZMPT101B and ACS712 libraries available that handle the raw signal filtering for you — search for them by name in the Library Manager, and install both.
Step 3: The Code
Here's a simplified version that reads both sensors and displays voltage, current, and calculated power on the OLED screen.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "ZMPT101B.h"
#include "ACS712.h"
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
ZMPT101B voltageSensor(34, 50.0); // 50Hz - adjust to 60Hz if that's your local grid frequency
ACS712 currentSensor(ACS712_20A, 36);
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
voltageSensor.setSensitivity(500.0); // calibrate this value - see notes below
}
void loop() {
float voltage = voltageSensor.getRmsVoltage();
float current = currentSensor.getCurrentAC();
float power = voltage * current;
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Voltage: "); display.print(voltage); display.println(" V");
display.print("Current: "); display.print(current); display.println(" A");
display.print("Power: "); display.print(power); display.println(" W");
display.display();
delay(1000);
}Step 4: Calibration (Don't Skip This)
Raw sensor readings straight out of the box are almost never accurate. This is the step that separates "a number that shows up on a screen" from "a number you can actually trust."
For the voltage sensor, use a multimeter to measure the actual voltage at your outlet, then adjust the setSensitivity() value in the code until the sensor's reading matches your multimeter. For the current sensor, plug in a device with a known power rating (a lamp with a printed wattage on the bulb works great for this), calculate the expected current using the formula current = power ÷ voltage, and adjust your code until the readings line up.
It took me about 20 minutes of trial and error to get mine within about 3% accuracy — good enough to actually trust the numbers, not perfect lab-grade precision, but plenty for household monitoring.
Common Problems (And How I Fixed Them)
The voltage reading is wildly off or negative. Double-check your grid frequency setting in the code — some countries run 50Hz, others 60Hz, and using the wrong one throws off the whole calculation.
The current reading jumps around even with nothing plugged in. This is usually electrical noise. Try adding a small capacitor across the sensor's output, or take an average of multiple readings instead of a single instant reading.
The OLED display shows nothing at all. Check your I2C address — most SSD1306 displays use 0x3C, but some use 0x3D. If your wiring looks right and nothing's showing, that's usually the culprit.
Power readings don't match my actual electricity bill. Remember this measures instantaneous power, not accumulated energy over time. If you want to track total consumption (kWh) instead of just a live wattage number, you'll need to add code that integrates the power reading over time — this is a great next step once the basic version is working.
What You Can Do With This Data
Once it's running reliably, the natural next step is sending the readings to Home Assistant or a similar dashboard over Wi-Fi, so you can log usage over days or weeks instead of just glancing at a screen. That's when patterns actually start showing up — for me, it turned out the "mystery" power draw was an old chest freezer in the garage that was cycling far more than it should have been. Fixing that seal knocked a real chunk off my next bill.
Final Thoughts
This is one of those projects that pays for itself pretty quickly once you actually find the appliance that's quietly draining power in the background. It's not a huge weekend build, but it does require patience during the calibration step — don't rush that part, because an uncalibrated energy meter is really just a random number generator with extra wires.


