【问题标题】:Calculating thd in python在python中计算thd
【发布时间】:2017-02-06 21:05:36
【问题描述】:

我正在尝试计算提供的交流电压的总谐波失真值。我正在使用 Arduino 以超过 8 KHz 的速率对电压数据进行采样,并将这些数据存储到文本文件中。然后我尝试使用以下用 python 编写的代码 sn-p 计算 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)

问题是,在我的情况下,获得的 Thd 值在 5% 到 25% 之间变化。 (实际上它实际上不超过 5%)。我究竟做错了什么?还有其他方法可以找出 thd 吗?

【问题讨论】:

  • 请检查代码的缩进
  • THD 只是谐波的总和,而不是 fft 中的每个 bin,除非您的基本周期正好等于数据记录长度。如果您的基频周期不是样本长度的精确整数除数,那么您应该使用 Window 函数和包含许多基频周期的记录长度
  • 实际上我正在尝试计算 THD+N。根据 wiki,(en.wikipedia.org/wiki/Total_harmonic_distortion) 它也包括噪声(谐波以外的频率)。
  • 您仍然需要加窗或精确整数倍周期,否则您的“噪音”实际上是光谱拖尾。 ADC 数据也可能被“杂散”污染——来自 ADC、传感器硬件的非谐波音调或电源线频率等外来音调。你真的应该绘制 fft 震级数据并关注它

标签: python numpy arduino fft sampling


【解决方案1】:

虽然这很安静,但对于像我这样遇到这篇文章的人来说:OP 方法存在一些问题。

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

thd = 100*sq_harmonics**0.5 / max(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) ]))

【讨论】:

    【解决方案2】:

    您很可能会通过测量过程本身添加额外的失真。

    如果您将 Arduino ADC 与高级测量设备进行比较,Arduino 的值很可能会更差。至少你需要一个非常稳定且无抖动的时钟。

    此外,数据的输出(我猜是通过 UART)可能会干扰 ADC 测量的时序。

    【讨论】:

    • 谢谢,但我也在 MATLAB 中使用相同的数据进行了相同的分析。在这种情况下,它显示的结果约为 2%,我猜这很好。你可以找到代码 [这里] (pastebin.com/T7ib0N27) 也许这不完全是 Arduino 的错。 (我对微控制器硬件不太了解,如果我错了,请纠正我)。在这种情况下,我需要使用 python。那我该怎么办?
    • 好的,那么我的假设是错误的,即您使用了额外的硬件。无论如何,不​​要把你的结果看得太严肃,但我不知道你的申请——这可能就足够了。但是 f5r5e5d 有一个非常有效的论点。你应该调查一下!
    猜你喜欢
    • 2020-07-02
    • 2023-03-13
    • 2022-01-10
    • 1970-01-01
    • 2011-06-20
    • 2018-09-27
    • 2017-08-08
    • 2016-04-05
    • 2015-06-14
    相关资源
    最近更新 更多