Mains frequency measurement

I am using the following approach to measuring mains frequency (50Hz): Measuring frequency from the EmonLib | Archived Forum

this seems to be accurate to ~0.5Hz but depends on the rest of the code in the programme. If there are interrupts, the millis() function will be inaccurate.

Please could someone suggest how I can measure 50Hz mains frequency to within 0.1% or less?

On an Arduino like the Uno, it is inaccurate in any case, due to the low quality resonator or crystal. Tell us what MCU board you actually have.

For accurate time or frequency measurements, you need an accurate reference clock.

A different approach would be to count the number of zero crossings in a decently long interval, using for example, the 1PPS signal of a GPS module as a time base. Nick Gammon's web pages feature a nice tutorial on input capture using Timer1 for such a purpose.

2 Likes

I am using an arduino mega

Hi,
it is possible to use ESP32, my friend Gustavo and I wrote this code for ESP32.

Measures from 1Hz to up to 40 MHz

1 Like

Why do you want to measure mains frequency.
Mains frequency is a zillion times more accurate than the clock of a Mega.
It only makes some sense (to me) if you run your own petrol/diesel generator.
Leo..

Right! If you live in a modern country the line frequency is probably more accurate than the crystal in your watch. And if it runs a tiny bit fast for a little while they slow it down for awhile so the number of cycles in a year is probably "perfect" and clocks are correct. Electric clocks with synchronous motors or digital clocks synchronized to the line frequency are some of the most accurate as long as you don't have a power failure.

GPS, cell network time, and internet time come from atomic clocks so they are also "perfect". And if you have a power failure or your cell phone battery dies, they reset to the correct time when power is restored.

There are groups of "timing enthusiasts" who closely monitor the frequency and voltage of their household AC, with the idea that this gives them some insight into the health of the system. And some historical records are available, at least in the U.K.

The frequency does vary by some fraction of 1% during the day, but it seems that the number of AC cycles is held to a fixed number over some long term.

There was an interesting discussion on the EEVBlog a while back: AC Power Line Frequency Accuracy Question - Page 1

Oi! Good idea using the portB pins for the PCNT.

1 Like

The original idea behind Time Error Correction (TEC) is that over a 24-hour period the total number of cycles is held constant. This is done by speeding up or slowing down the generators in that timeframe, to compensate for slow downs due to load or speed ups from decreasing load. Try this link: The Dirty Little Secret about Mains Power Line Frequency

Still don't see why you need to know if the mains frequency is 49 , 50 or 51 Hz.
Almost all modern gear doesn't rely on exact mains frequency anymore.
Leo..

Assume that it would be fun.

This site has some of the enthusiasts data:


https://powerit.utk.edu/worldmap/

Hi, @jhinshel

What is your application?
Why do you need that sort of accuracy?

Tom... :smiley: :+1: :coffee: :australia:

The aaplication is for an off grid electricity system. The solar inverters get a frequency signal to ramp down generation when excess power builds up. When the frequency rises above 51Hz the inverters ramp down. I monitor the island grid frequency and utilise excess power before the inverters ramp down. If my monitors can respond to a change from 50-51Hz this will pre-empt the ramping down of the solar inverters.

have a look at post output-phase-shift-on-linear-load

0.1% of 50Hz is 0.25Hz. Looking at your linked code, my first thought is to use a longer sampling time as they suggest. Maybe double the 50 crossings to go from 0.2% to 0.1%.

Also, millis's hardware counter keeps running during interrupts. While interrupts are suspended, millis()'s overflow updating is only paused until the interrupts are un-suspended, and then the millis() interrupt takes place. If you code has ISRs that inhibit interrupt for longer than 1024 cycles, you could miss a cycle during the pause, but those would be poor ISRs.

What is your circuit? Detecting zero crossing with while() {AnalogRead()...} seems fraught with danger. A resistor and optocoupler should be able to condition a half-wave digitalRead() and you could measure a cycle with 20000 micros() instead of 50 millis() in loop().

The mega also uses a low accuracy resonator instead of a quartz crystal.

1 Like

And millis() is only accurate to +/-5uS.

50Hz +-1Hz I'd use a ESP32 and the PCNT API; a 12.5nS resolution.

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html

When programmed the PCNT will count pulses and can give outputs based upon settings and can do its thing without the use of the main CPU.

Heck threads can be generated to make adjustments from/by the PCNT so that the main program can keep on running.

Even computer grade crystals are typically spec'ed to something like 0.1% (100 ppm). I'd expect they're "good enough" for this application over a narrow room temperature range, but something to consider as part of the error budget.

Watch grade crystals are typically around 0.001% (1 ppm).

Yes, however the 0.1% refers to the accuracy, not deviation. So with a typical quartz crystal can, the centre frequency may not be exactly as marked on the can, but whatever it is, will remain pretty close. That means, you can provide a correction factor in software and calibrate it.

A resonator is not like that, it is highly temperature sensitive regards resonant frequency. Quartz are also temperature sensitive, but not nearly to the same degree.

1 Like