使用壁橱中的垃圾测量电源网络频率
Measuring power network frequency using junk you have in your closet

原始链接: https://halcy.de/blog/2025/02/09/measuring-power-network-frequency-using-junk-you-have-in-your-closet/

2025年2月,波罗的海国家将其电网从俄罗斯切换到欧洲同步。由于缺乏适当的电气设备,作者通过监视频移的吸引力,设计了一种DIY方法。他们使用了PC的线路,将电缆包裹在电源电缆上作为天线,并大胆地捕获电源嗡嗡声。然后,Python脚本分析了记录的音频,执行了Hann窗口的FFT,以识别50Hz左右的主要频率。尽管设置了粗糙,但与Sympower的专业频率监控工具的数据相比,测量值令人惊讶地准确,尽管时间滞后和平滑效果明显。使用F50Hz.de的数据进行进一步验证,转移到了滞后,清楚地表明了波罗的海网格与欧洲网络同步的那一刻。频率图在最终断路器翻转之前揭示了彼此之间的受控漂移,这表明有意同步过程。

该黑客新闻线程使用随时可用的材料来讨论电力网络频率。原始文章可能详细介绍了一种从主电源中提取频率数据的方法。评论者探索替代方法,例如使用变压器进行安全和连锁控制解码。 讨论的关键点是主频率调节的准确性,用户对可接受的偏差级别进行了辩论。一些人建议网格保持严格的频率控制,而另一些则引用了由于频率下降而导致的近崩溃场景的实例。讨论还涉及使用电压电压和适当隔离的重要性的潜在危险。 几位评论者表示有兴趣建立分布式电力网络监控系统。想法包括使用ESP32微控制器,GPS进行精确的时间同步和零交叉IC。人们对责任,数据完整性提出了担忧,并找到了开发此类项目的时间。还提到了收集和分析电网数据的Ting和Gridradar等现有项目。最后,提到使用频率噪声作为时间戳视频的法医工具。
相关文章

原文

Over the weekend starting on Saturday, the 8th of February 2025, the Baltic states’ electricity grid is switching from being synchronized with the Russian electric grid to being synchronized with the continental European electrical grid. This involves first disconnecting from the Russian grid, then operating a while as an island system, regulating the frequency alone and doing various tests, and finally, synchronizing frequency and phase with the EU grid and throwing the breaker. Which made me wonder earlier today: How hard would it be to watch the frequency changing?

The proper way to do this would probably be to step down line voltage to something more manageable and then just record that signal directly and find the dominant frequency component in that. However, I don’t have a step-down converter, or really any electrical equipment, and I am a mains voltage respecter and not about to plug anything homemade into a socket. So that’s out. However, there’s an easier way: Fortunately, just about everything is an antenna.

I did my PhD in biosignals processing, and a common problem there is to get mains hum out of just about every signal. If you don’t take great care and employ technical measures to get rid of it, you will get substantial 50Hz hum in your signals. Even if you do, there’s likely to still be some. While this is more of a problem with the high amplification factors required to record, say, an EEG, it should still be true when just recording any signal. So, lets plug an audio cable into the PCs line in, wrap it around a power cable a few times for good measure, plug the other side into absolutely nothing, and see what we can do.

An audio cable coming from my PC, coiled around a power cable a few times, plugged into absolutely nothing

Firing up Audacity and just recording for a few seconds shows… a flat line with absolutely no audio.

Audacity showing an audio track with nothing in it.

But what if we normalize this apparent lack of a signal up to -3dBFS?

Audacity showing an audio track with a very dirty sine wave in it. Audacities spectrum display, with a peak at 50Hz.

Ah! There’s a very noisy sine, and clearly, it’s somewhere around 50Hz. So this could work! Time to write some python.

Most of the script is boilerplate “record audio and put it into a ringbuffer” stuff, the more interesting part is a bit of basic DSP:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Do a Hann windowed FFT
hann_window = np.hanning(fft_window_size)
windowed = window_samples * hann_window
fft_complex = np.fft.rfft(windowed)

# Slice the magnitude spectrogram to the range we care about
freqs = np.fft.rfftfreq(fft_window_size, 1.0 / sample_rate)
idx_min = np.searchsorted(freqs, FREQ_MIN)
idx_max = np.searchsorted(freqs, FREQ_MAX)
sub_mags = np.abs(fft_complex[idx_min:idx_max])
sub_freqs = freqs[idx_min:idx_max]

# Find the peak
n = np.argmax(sub_mags)

# Quadratic interpolation to refine the peak location
frac_offset = 0.0
if not (n < 1 or n >= len(sub_mags) - 1):
    alpha = sub_mags[n - 1]
    beta  = sub_mags[n]
    gamma = sub_mags[n + 1]
    denom = alpha - 2*beta + gamma
if abs(denom) > 1e-12:
    frac_offset = 0.5 * (alpha - gamma) / denom
n_interp = n + frac_offset

# Compute which frequency this corresponds to
lower_idx = int(np.floor(n_interp))
upper_idx = int(np.ceil(n_interp))
frac = n_interp - lower_idx
if upper_idx >= len(sub_freqs):
    upper_idx = len(sub_freqs) - 1
est_freq = (1 - frac) * sub_freqs[lower_idx] + frac * sub_freqs[upper_idx]

I chose a relatively large FFT size (25 seconds) to have good frequency resolution - we can make up for that by just using a very low sample rate, since the frequencies we care about are very low as well, anyways. And indeed:

Script output, showing a frequency a sliver below 50Hz.

So how well does this work? How can we figure out if that reading is accurate? Fortunately, some people from Sympower, a power market company with offices in Estonia recently built their own, somewhat less hacky frequency monitoring tool, and it has a convenient API that lets you retrieve their data over some period of time. Turns out this works way better than it has any right to:

Graph comparing my measurement with Sympowers, showing a pretty good overall match.

There is obviously some time lag, and the output is way more smoothed than the more proper measurement, but it clearly works quite well and measures broadly the correct thing!

The logger is now running on my computer collecting data, I want to see if I can tell from the logs I am writing when they flip the breaker and connect to the EU network, so I’ll keep it running over the weekend. If you want to try yourself, The full python script is here.

Update late on the 9th of February, 2025: @[email protected] pointed me to https://f50hz.de, which has an an API to get the european network frequency, so plotting my measurements next to that (shifting by 12.5 seconds to account for the time lag due to the very long Fourier transform window) gets us this, with the time axis in UTC:

A plot showing, above, my measurements and data from f50hz.de, and below, the difference between the two time series. The moment where the grids sync is very clearly visible.

You can perfectly see the moment the two networks are synced up. Right before, one shifts up in frequency and then goes down, while the other shifts down and then goes up - I wonder if this was intentional, it certainly looks a bit like it, letting the frequencies drift towards each other in a nice, controlled way before flipping the breaker.

联系我们 contact @ memedata.com