Close

Measuring Mains Frequency with a Raspberry Pi (MQTT / WebSocket) — Zero-Crossing and Safety Notes

A project log for Electric time

Vintage pressure gauge hacked into a frequency meter, sensing the 50 Hz electrical grid tremors; time wavers, bends, and fades away.

dtournerDétourner 10/29/2025 at 12:330 Comments

Principle

The idea is simple: detect every zero crossing of the AC waveform, count how many occur during a time interval T, and compute the frequency.
If all crossings are counted (both rising and falling), there are two per cycle:

I use a 10-second interval with a moving average to stabilize readings. The frequency value is updated every second.

Two Key Challenges

1. Accurate Time Reference

The accuracy of the frequency measurement is directly tied to the accuracy of your time base.

To see why, consider that the frequency is inversely proportional to the period:

If the real period of a 50 Hz signal is:

and we want to resolve a difference of 0.01 Hz (i.e. 50.00 Hz vs 50.01 Hz), the corresponding change in period is:

So, to detect a 0.01 Hz difference at 50 Hz, our timing precision must be on the order of a few microseconds. To obtain a stable result over several cycles, a base clock or timestamp resolution around 1 µs is typically required.

With this expected resolution, NTP synchronization is not sufficient — it usually offers millisecond accuracy. To achieve microsecond-level precision, I used a GPS PPS (Pulse-Per-Second) signal as a reference clock.

2. Bringing 230 V (or 120 V) to a GPIO Safely

Never connect the mains directly to a GPIO or use a resistor divider — that’s lethal and will destroy your Raspberry Pi.

A safe option is to use an optocoupler for AC detection. For this project, I used a mains sensing module from AliExpress that provides galvanic isolation and outputs a 3.3 V logic signal compatible with the Pi.

Discussions