- 我正在生成 2 个正弦波,第一个具有基频 = 50 Hz,幅度 = 10,相位 = 0,第二个具有基频 = 100 Hz,幅度 = 5 和相位 = np.pi/6(即 30 度) .
- 然后我将它们相加,并对添加的信号执行 FFT。
- 我使用 np.abs() 计算 50 Hz 和 100 Hz 的信号幅度
- 我分别使用 np.angle() 计算 50 Hz 和 100 Hz 的信号相位
- 这是我得到的结果
“幅度_50赫兹”:9.997827675356993,“相位50赫兹”:-89.0677734968239,“幅度_150赫兹”:4.990392258900833,“相位150赫兹”:-57.231981462145704,
返回的幅度分别非常接近 10 和 5。但相位不是 0 和 30 度。
我也尝试了其他方法,例如 math.atan2 和 cmath.phase,它提供了类似的结果。
我想了解我的相位计算出了什么问题。我的代码如下。
def sine_wave(amplitude1: Union[int, float], amplitude2: Union[int, float], phase1: float, phase2: float,
duration: Union[int, float],fund_freq_1: int, fund_freq_2: int, samp_freq: int) -> dict:
# generating the time domain signal
t = np.linspace(0, duration, int(samp_freq * duration))
wave1 = amplitude1 * np.sin((2 * np.pi * fund_freq_1 * t)+phase1)
wave2 = amplitude2 * np.sin((2 * np.pi * fund_freq_2 * t)+phase2)
combined_wave = np.add(wave1, wave2)
N = combined_wave.size
T = 1/samp_freq
# DFT
f = np.fft.fftfreq(N, 1 / samp_freq)
fft = np.fft.fft(combined_wave)
index_one = np.where(np.isclose(f, fund_freq_1))
magnitude_one = np.mean(np.abs(fft[index_one]) * (2 / N))
phase_one = degrees(np.angle(fft[index_one]))
# phase_one = atan2(fft[index_one].imag, fft[index_one].real)
# phase_one = degrees(phase(fft[index_one]))
index_two = np.where(np.isclose(f, fund_freq_2))
magnitude_two = np.mean(np.abs(fft[index_two]) * (2 / N))
phase_two = degrees(np.angle(fft[index_two]))
# phase_two = atan2(fft[index_two].imag, fft[index_one].real)
# phase_two = degrees(phase(fft[index_two]))
return {'magnitude_{} Hz'.format(fund_freq_1): magnitude_one,
'phase_{} HZ'.format(fund_freq_1): phase_one,
'magnitude_{} Hz'.format(fund_freq_2): magnitude_two,
'phase_{} HZ'.format(fund_freq_2): phase_two}
代码可以这样运行
sine_wave(amplitude1=10, amplitude2=5, phase1=0, phase2=np.pi/6, duration=0.1, fund_freq_1=50, fund_freq_2=150, samp_freq=10000)
进一步的怀疑
与我昨天讨论的类似,我正在解决工作中的另一个问题。
为了解决这个问题,我正在创建测试正弦波(N=2000 个样本或数据点)并对这些正弦波执行相同的过程。
*** 第一波 = 基频 = 50,采样频率 = 10000,持续时间 = 0.2,幅度 = 10,相位 = 0 度
- 第二波 = 基频 = 50,采样频率 = 10000,持续时间 = 0.2,幅度 = 10,相位 = 120 度
- 第三波 = 基频 = 50,采样频率 = 10000,持续时间 = 0.2,幅度 = 10,相位 = 240 度**
我使用此功能生成波浪。
def generate_test(amplitude1: Union[int, float], amplitude2: Union[int, float], amplitude3: Union[int, float],
phase1: float, phase2: float, phase3: float, duration: Union[int, float], fund_freq_1: int,
fund_freq_2: int, fund_freq_3: int, samp_freq: int) -> tuple:
"""
:param amplitude1: Amplitude of the first sine wave
:param amplitude2: Amplitude of the second sine wave
:param amplitude3: Amplitude of the third sine wave
:param phase1: Phase of the first sine wave in radians
:param phase2: Phase of the second sine wave in radians
:param phase3: Phase of the third sine wave in radians
:param duration: Duration of each sine waves
:param fund_freq_1: Fundamental frequency the first sine wave
:param fund_freq_2: Fundamental frequency the second sine wave
:param fund_freq_3: Fundamental frequency the third sine wave
:param samp_freq: Sampling frequency of each sine waves
:return: 3 sines waves
:rtype: tuple of 3 numpy arrays
"""
t = np.arange(0, duration * samp_freq) / samp_freq
wave1 = amplitude1 * np.sin((2 * np.pi * fund_freq_1 * t) + phase1)
wave2 = amplitude2 * np.sin((2 * np.pi * fund_freq_2 * t) + phase2)
wave3 = amplitude3 * np.sin((2 * np.pi * fund_freq_3 * t) + phase3)
return wave1, wave2, wave3
主要任务:
1. Generate 3 sine waves using the 'generate_test' function. Each with 120 degrees phase shift
* first wave = fundamental frequency = 50, sampling frequency = 10000, duration = 0.2, amplitude = 10, phase = 0 degrees
* second wave = fundamental frequency = 50, sampling frequency = 10000, duration = 0.2, amplitude = 10, phase = 120 degrees
* third wave = fundamental frequency = 50, sampling frequency = 10000, duration = 0.2, amplitude = 10, phase = 240 degrees
2. I divide each wave into exactly two halves, let's call these halves as the before half and after half. (2000 samples or data points divided into two signals with 1000 data points each)
2. From each of the halves I drop the first and last 50 data points (50 (first fifty) + 50 (last fifty) = 100)
3. Now i have 3 before halves and 3 after halves
4. From each of the 3 before and 3 after halves I need to calculate the amplitude and phase at 50 Hz using FFT .
5. Calculate FFT
6. Find indices corresponding to 50 Hz. I get 2 indices here, because the frequency bins are not centered at 50 Hz
7. Use np.abs to calculate the absolute value of the FFT component then take a mean of it
8. Use np.angle to calculate the phase of the FFT component, convert it to degrees and then take the mean of it.
代码如下
def test_amplitude_phase_algo(amplitude1: Union[int, float], amplitude2: Union[int, float],
amplitude3: Union[int, float],
phase1: float, phase2: float, phase3: float, duration: Union[int, float],
fund_freq_1: int,
fund_freq_2: int, fund_freq_3: int, samp_freq: int):
test_data = plot_and_return(amplitude1, amplitude2, amplitude3, phase1, phase2, phase3, duration, fund_freq_1,
fund_freq_2, fund_freq_3, samp_freq)
T = 1 / samp_freq
result_df = pd.DataFrame()
for col in test_data.columns:
prevail = test_data[col][50:950]
trail = test_data[col][1050:1950]
N = prevail.size
# Prevailing samples
prevail_frequencies = np.fft.fftfreq(N, 1 / samp_freq)
prevail_fft = np.fft.fft(prevail)
prevail_index = np.where(np.isclose(prevail_frequencies, 50, atol=1 / (T * N)))
prevail_amplitude = np.mean(np.abs(prevail_fft[prevail_index]) * (2 / N))
prevail_phase = degrees(np.mean(np.angle(prevail_fft[prevail_index])))
# Trailing samples
trailing_frequencies = np.fft.fftfreq(N, 1 / samp_freq)
trailing_fft = np.fft.fft(trail)
trail_index = list(np.where(np.isclose(trailing_frequencies, 50, atol=1 / (T * N)))[0])
trail_amplitude = np.mean(np.abs(trailing_fft[trail_index]) * (2 / N))
trail_phase = degrees(np.mean(np.angle(trailing_fft[trail_index])))
result_array = np.array((prevail_amplitude, trail_amplitude, prevail_phase, trail_phase))
temp_df = pd.DataFrame(result_array).T
result_df = result_df.append(temp_df)
i0 = result_df.mean(axis=0)
result_df = result_df.append(i0, ignore_index=True)
result_df.columns = ['amplitude_before', 'amplitude_after', 'phase_before', 'phase_after']
result_df.index = ['w1', 'w2', 'w3', 'avg_w']
return result_df
这是我得到的答案:
amplitude_before amplitude_after phase_before phase_after
w1 6.346514 6.346514 -0.011246 -0.011246
w2 6.383717 6.383717 -60.070936 -60.070936
w3 6.383184 6.383184 60.082026 60.082026
avg_w 6.371139 6.371139 -0.000052 -0.000052
我的问题仅涉及信号的测量相位(我将在另一个问题中讨论幅度)。
正如昨天的答案中提到的,我的角度应该偏离-90度。如果我在合成角度上加上 90 度,那么我的角度将是
phase_before phase_after
w1 ~90 ~90
w2 ~30 ~30
W3 ~150 ~150
avg_w ~90 ~90
阶段应该是
phase_before phase_after
w1 ~0 ~0
w2 ~120 ~120
W3 ~240 ~240
avg_w ~120 ~120