Here in South Africa the Eskom mains grid is under pressure, with periodic planned load shedding to alleviate the strain. I thought it would be a good idea to monitor and log the mains frequency using an ESP32 module and ESPHome, in order to gauge the state of the grid and possibly predict outages. However, it turns out that accurately measuring low frequencies to 2 or 3 decimals is not as easy as one would think.
I used a 9VAC wall-wart transformer for the supply and signal, with the 9VAC secondary winding driving an opto-coupler through a 1k current limiting resistor and reverse-blocking diode, and a bridge rectifier/capacitor/LM7805 to power the ESP32.
I tried the frequency_counter component, which was not consistent in output, even with an averaging filter. Then I tried the pulse width sensor but calibration and consistency was not acceptable. Finally I settled on @stevebaxter’s pulse_meter custom sensor, which is so far gives the most consistent reading.
Here is the code, warts and all:
sensor:
- platform: pulse_meter
pin: GPIO34
name: "Eskom Grid PPM"
id: eskom_ppm
unit_of_measurement: 'ppm'
- platform: template
id: frequency
name: "Eskom Grid Frequency"
unit_of_measurement: "Hz"
lambda: |-
return ( id(eskom_ppm).state / 60);
accuracy_decimals: 3
update_interval: 5s
filters:
- offset: -2.63158
The offset was needed because the frequency was consistently exactly over by that amount. It may vary between ESP32 devices.
Update: After boot, the log output shows the correct ppm and Hz readings, but after about half an hour, (I will still confirm exact interval) it spontaneously changes so that the offset value is no longer needed. Maybe an artifact of Steve’s code?
Log output:
[21:48:50][D][sensor:092]: 'Eskom Grid Frequency': Sending state 50.00000 Hz with 3 decimals of accuracy
[21:48:55][D][sensor:092]: 'Eskom Grid Frequency': Sending state 50.00000 Hz with 3 decimals of accuracy
[21:49:00][D][sensor:092]: 'Eskom Grid Frequency': Sending state 50.00000 Hz with 3 decimals of accuracy
[21:49:05][D][sensor:092]: 'Eskom Grid Frequency': Sending state 50.00000 Hz with 3 decimals of accuracy
[21:49:10][D][sensor:092]: 'Eskom Grid Frequency': Sending state 50.00000 Hz with 3 decimals of accuracy
[21:49:15][D][sensor:092]: 'Eskom Grid Frequency': Sending state 50.00000 Hz with 3 decimals of accuracy
[21:49:20][D][sensor:092]: 'Eskom Grid Frequency': Sending state 50.00000 Hz with 3 decimals of accuracy
[21:49:25][D][sensor:092]: 'Eskom Grid Frequency': Sending state 50.00000 Hz with 3 decimals of accuracy
[21:49:30][D][sensor:092]: 'Eskom Grid Frequency': Sending state 50.00000 Hz with 3 decimals of accuracy
[21:49:35][D][sensor:092]: 'Eskom Grid Frequency': Sending state 50.00000 Hz with 3 decimals of accuracy
and:
21:51:00][D][sensor:092]: 'Eskom Grid PPM': Sending state 3000.00000 ppm with 2 decimals of accuracy
[21:51:00][D][sensor:092]: 'Eskom Grid PPM': Sending state 3157.89478 ppm with 2 decimals of accuracy
[21:51:00][D][sensor:092]: 'Eskom Grid PPM': Sending state 3000.00000 ppm with 2 decimals of accuracy
[21:51:00][D][sensor:092]: 'Eskom Grid PPM': Sending state 3157.89478 ppm with 2 decimals of accuracy
[21:51:00][D][sensor:092]: 'Eskom Grid PPM': Sending state 3000.00000 ppm with 2 decimals of accuracy
[21:51:00][D][sensor:092]: 'Eskom Grid PPM': Sending state 3157.89478 ppm with 2 decimals of accuracy
[21:51:00][D][sensor:092]: 'Eskom Grid PPM': Sending state 3000.00000 ppm with 2 decimals of accuracy
[21:51:00][D][sensor:092]: 'Eskom Grid PPM': Sending state 3157.89478 ppm with 2 decimals of accuracy
[21:51:00][D][sensor:092]: 'Eskom Grid PPM': Sending state 3000.00000 ppm with 2 decimals of accuracy
[21:51:00][D][sensor:092]: 'Eskom Grid PPM': Sending state 3157.89478 ppm with 2 decimals of accuracy
Please feel free to use the code if you wish, and to give comments, improvements or suggestions for alternative ways to implement a mains frequency counter.


