
AC Energy Meter
A bare-metal STM32F103 energy meter that samples AC voltage and current simultaneously, computes true-RMS power and accumulated energy, and reports over UART to a host controller.
Measuring AC power off the shelf usually means buying a couple of sensor modules and trusting a black box to do the maths. This is the version where every stage is explicit: the analog front-end is re-biased for the STM32's 3.3 V ADC, voltage and current are sampled at the same instant, and the firmware turns those samples into true-RMS voltage and current, real and apparent power, power factor, and accumulated energy.
It began as a sub-project of the grow controller. The hydroponics system needs to know what its lights, pumps, and heaters are actually drawing, so instead of bolting on a commercial meter the whole measurement path is built from first principles in bare-metal C.
How It Works
The meter runs on a single STM32F103. A ZMPT101C module scales the mains voltage and a ZMCT103C module senses the load current; both feed the two on-chip ADCs, which convert them in lockstep and hand the results to memory without the CPU touching a single sample.
230 V AC ──► ZMPT101C (voltage) ──► ADC1 (PA0) ──┐
├──► STM32F103 ──► USART1 ──► ESP32
load ─────► ZMCT103C (current) ──► ADC2 (PA1) ──┘ │
relay ──► load- Sample both channels at once. ADC1 and ADC2 run in dual regular simultaneous mode, so the voltage and current for a given conversion belong to the same instant. That is what makes the power calculation meaningful rather than a pair of unrelated averages.
- Never copy in software. A DMA channel streams the ADC results into a circular buffer in the background. Half-transfer and transfer-complete interrupts wake the CPU only to process a finished half-buffer.
- True RMS, not averaged. Each half-buffer has its DC bias removed, then the firmware takes the root-mean-square of each channel and the product of the two to get real power. Apparent power and power factor fall out of the same maths.
- Talk to a host. A DMA-driven UART at 115200 baud accepts single-byte commands and returns a packed energy packet, with framing, overrun, and noise errors counted so a bad link is visible rather than silent.
- Switch the load. A relay output lets the host controller connect or disconnect the load from the mains on command.
Features
- True-RMS AC voltage and current measurement
- Active and apparent power, and power factor
- Accumulated energy in watt-seconds
- Dual ADC simultaneous sampling of voltage and current
- Circular DMA capture with half/transfer interrupt processing
- UART at 115200 baud with DMA transmit and receive
- Double-buffered, idle-line-framed receive with error statistics
- Relay output for load switching
- Bare metal — no HAL, no RTOS, about 2.4 KB of flash
Project Status
The measurement path is working end to end. The firmware clocks the part at 72 MHz, runs both ADCs from a 12 MHz clock, captures one full mains cycle per buffer, and produces calibrated voltage, current, power, and energy on every half-buffer. The UART command path is live: the host can request the latest reading and drive the relay.
Still in progress: finalising the host protocol (the packet format is defined and the response is being wired through), tightening the calibration constants against a reference meter, and documenting the command set so the grow controller can consume it directly.
The full hardware and firmware design lives in the documentation.
More projects
CWX Valve Controller
A programmable irrigation timer for CWX series motorized valves, built around an STM32 with a custom PCB, a real-time clock, and up to four daily schedules.
Hydroponics Control System
An internet-connected hydroponic grow controller that runs each vegetable from its own profile, automating climate, lighting, watering, and nutrient delivery.