在python中计算thd

tah*_*314 4 python numpy fft arduino sampling

我正在尝试计算所提供的交流电压的总谐波失真值。我使用 Arduino 以超过 8 KHz 的速率采样电压数据,并将这些数据存储到文本文件中。然后我尝试使用以下用 python 编写的代码片段来计算 thd:

    import numpy as np
    import scipy.fftpack
    from scipy.fftpack import fft
    from numpy import genfromtxt

    sampled_data = genfromtxt('/../file.txt',delimiter=',')
    abs_yf=np.abs(fft(sampled_data))

    #As far as I know, THD=sqrt(sum of square magnitude of
    #harmonics+noise)/Fundamental value (Is it correct?)So I'm
    #just summing up square of all frequency data obtained from FFT,
    #sqrt() them and dividing them with fundamental frequecy value.

    def thd(abs_data):
    sq_sum=0.0
    for r in range(len(abs_data)):
       sq_sum=sq_sum+(abs_data[r])**2
    sq_harmonics=sq_sum-(max(abs_data))**2.0
    thd=100*sq_harmonics**0.5/max(abs_data)
    return thd

    print "Total Harmonic Distortion(in percent):"
    print thd(abs_yf)
Run Code Online (Sandbox Code Playgroud)

问题是,在我的例子中,获得的 Thd 值在 5% 到 25% 之间变化。(实际上这个比例不超过5%)。我究竟做错了什么?还有其他方法可以查到thd吗?

小智 5

虽然这已经很长时间了,但对于像我这样遇到这篇文章的人来说:OP 方法存在一些问题。

1) FFT返回的幅度包括0频率仓的幅度,因此如果信号中存在任何DC偏置,则max(abs_data)是对应于基频的幅度的假设是不正确的。这是线路上的问题

thd = 100*sq_harmonics**0.5 / 最大值(abs_data)

作为一种快速解决方案,可以忽略与 0 频率相关的幅度。

2)abs_data的后半部分应该被丢弃,它是前半部分的“镜像”反射。这是由于傅里叶变换的性质造成的。

这两个问题都可以通过更改函数的输入来解决,即通过替换

打印 thd(abs_yf)

打印( thd(abs_yf[1:int(len(abs_yf)/2) ]) )

我们已将输入更改为不包含第一个或最后一个 N/2 元素。

结果仍然不理想,因为窗口需要恰好是整数个周期,如上面提到的先前答案。使用带有偏移的纯正弦测试并调整窗口表明该方法工作得相当好,但如果出现重大窗口错误,则会严重失败。

t0=0
tf = 0.02  # integer number of cycles
dt = 1e-4
offset = 0.5
N = int((tf-t0)/dt)
time = np.linspace(0.0,tf,N )    #;

commandSigFreq = 100
Amplitude = 2

waveOfSin = Amplitude*np.sin(2.0*pi*commandSigFreq*time) + offset

abs_yf = np.abs(fft(waveOfSin))
#print("freq is" + str(scipy.fftpack.fftfreq(sampled_data, dt )  ))
#As far as I know, THD=sqrt(sum of square magnitude of
#harmonics+noise)/Fundamental value (Is it correct?)So I'm
#just summing up square of all frequency data obtained from FFT,
#sqrt() them and dividing them with fundamental frequency value.

def thd(abs_data):
    sq_sum=0.0
    for r in range( len(abs_data)):
       sq_sum = sq_sum + (abs_data[r])**2

    sq_harmonics = sq_sum -(max(abs_data))**2.0
    thd = 100*sq_harmonics**0.5 / max(abs_data)

    return thd

print("Total Harmonic Distortion(in percent):")
print(thd(abs_yf[1:int(len(abs_yf)/2) ]))
Run Code Online (Sandbox Code Playgroud)