Skip to content
Martin Mwiti
All projects
AC Energy Meter thumbnail
Prototype

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.

STM32F103CADCDMAUARTCMake

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.