2024年10月11日金曜日

ヘテロダイン検波

DAS(ヘテロダインOTDR)を理解するため、順に可視化してみました(Thanks! GPT)。
誤っていたらいずれ気づくでしょう。その際に修正しましょう。

まずは import。

  1. import numpy as np
  2. from scipy.signal import hilbert, butter, filtfilt
  3. import matplotlib.pyplot as plt

レーザーを作成します。

  1. # サンプリング周波数
  2. fs = 5000 # サンプリング周波数
  3. t = np.linspace(0, 1, fs, endpoint=False) # 1秒間の時間軸
  4.  
  5. # 信号の周波数
  6. f_signal = 1000 # 1000Hzの振動信号
  7. signal = np.sin(2 * np.pi * f_signal * t)
  8.  
  9. # 周波数シフト
  10. carrier_freq = 1010
  11. carrier_wave = np.sin(2 * np.pi * carrier_freq * t)
  12.  
  13. # 後方散乱光
  14. # 光ファイバーから得られた2ショット
  15. # 位相が少しずれている
  16. scattered_signal1 = np.sin(2*np.pi*(carrier_freq)*t
  17.                    + 2*np.pi*0.1)
  18. scattered_signal2 = np.sin(2*np.pi*(carrier_freq)*t
  19.                    + 2*np.pi*0.2)
  20. plt.plot(t[:100],signal[:100],label="signal")
  21. plt.plot(t[:100],carrier_wave[:100],label="carrier",c="green")
  22. plt.plot(t[:100],scattered_signal1[:100],label="scatteres1")
  23. plt.plot(t[:100],scattered_signal2[:100],label="scatteres2")
  24. plt.legend()

戻ってきた光を干渉させます。
sin波の積和の公式より、高周波成分と低周波成分が生まれます。

  1. # 干渉信号の生成
  2. interfered_signal1 = scattered_signal1 * signal
  3. interfered_signal2 = scattered_signal2 * signal
  4. plt.plot(t[:100],interfered_signal1[:100])
  5. plt.plot(t[:100],interfered_signal2[:100])

光の高周波数は検出できませんが、干渉後の低周波成分は検出可能です。

  1. # Butterworthフィルタ(ローパス)
  2. cutoff = 50
  3. # 正規化周波数
  4. Wn = cutoff / (f_signal / 2)
  5. # Butterworthフィルタの設計
  6. b, a = butter(4, Wn, 'low')
  7. filtered_signal1 = filtfilt(b, a, interfered_signal1)
  8. filtered_signal2 = filtfilt(b, a, interfered_signal2)
  9. plt.plot(t,filtered_signal1)
  10. plt.plot(t,filtered_signal2)

低周波側の信号から位相を取り出し、2ショット間の位相差を算出します。
ここはプロのノウハウがあるそうです。図書にも見当たらないので推定です。

  1. # ヒルベルト変換を用いた瞬時位相の抽出
  2. analytic_signal1 = hilbert(filtered_signal1)
  3. instantaneous_phase1 = np.unwrap(np.angle(analytic_signal1))
  4. analytic_signal2 = hilbert(filtered_signal2)
  5. instantaneous_phase2 = np.unwrap(np.angle(analytic_signal2))
  6. # 瞬時周波数の計算
  7. instantaneous_frequency1 = np.diff(instantaneous_phase1)
  8. / (2.0 * np.pi) * fs
  9. instantaneous_frequency2 = np.diff(instantaneous_phase2)
  10. / (2.0 * np.pi) * fs
  11.  
  12. plt.figure(figsize=(10, 10))
  13. # プロット:位相
  14. plt.subplot(311)
  15. plt.plot(t, instantaneous_phase1)
  16. plt.plot(t, instantaneous_phase2)
  17. plt.title('Extracted Phase from Interfered Signal')
  18. plt.xlabel('Time [s]')
  19. plt.ylabel('Phase [radians]')
  20. plt.grid(True)
  21.  
  22. plt.subplot(312)
  23. plt.plot(t, instantaneous_phase2-instantaneous_phase1)
  24. plt.title('Extracted Phase from Interfered Signal')
  25. plt.xlabel('Time [s]')
  26. plt.ylabel('Phase [radians]')
  27. plt.grid(True)
  28.  
  29. # プロット:周波数
  30. plt.subplot(313)
  31. # t変数の長さをinstantaneous_frequencyに合わせる
  32. plt.plot(t[:-1], instantaneous_frequency1)
  33. plt.plot(t[:-1], instantaneous_frequency2)
  34. plt.plot(t[:-1], instantaneous_frequency2
  35. -instantaneous_frequency1)
  36. plt.title('Instantaneous Frequency')
  37. plt.xlabel('Time [s]')
  38. plt.ylabel('Frequency [Hz]')
  39. plt.ylim(-20,20)
  40. plt.grid(True)
  41. plt.tight_layout()


0 件のコメント:

コメントを投稿