我們在之前在《流量傳感器(2)—超聲流量傳感器,相位差和相關性原理》中曾留了一個問題:如果采樣頻率不一樣,模擬的結果會怎么樣?不知道大家有沒有時間去運行測試一下,反正小編嘗試了。測試的結果(但不是最終結論,請根據實際應用進行調整)下文會提到。
在小編上次關于超聲流量的相關信號處理的模擬中,用到了插值的方式,不過由于沒有經過太多的測試,在后續測試過程中,發現當聲速為4500m/s的模擬流體的流速不超過15m/s時,都沒有什么問題;但是當模擬的流速超過15m/s之后,兩組模擬信號的相位差超過了180°時,獲取相關性序列中對應的時間值時,發現取值結果為負數。
相位差180°,這本身沒有問題,但是由于數據的相關性處理函數是個偶函數,對稱于中點,所以在數據相關性處理中,當兩路信號的相位差超過180°前后時,因為兩路測試信號是正余弦形式,相當于其中一路信號序列在相對于另外一路信號序列移動的時候,在某個相對處的相關計算結果,可以找到另外一個錯位的對方有相同的相關處理結果,然而在查找標識相位偏差所對應的最大值時間序列值時,測試代碼優先輸出了最左側編號是負數的相位序列,實際應該輸出相關性序列中點右側的最大值所對應的時間序列值。結果可想而知,計算的流速變成了負數。修改后的代碼中,計算流速時,使用的相關性序列是整個相關結果序列的右邊部分,就解決了輸出流速突然變成負數的問題。
另外,實際的超聲波接收信號并不會是從頭至尾都是理想的正余弦,因此,我們看到的模擬信號似乎也是太過于理想。這里我們稍微加了點料,讓穩定的信號后面加上了快速衰減。
在進行模擬信號相關性處理的時候,之前我們使用的是直接死磕方式的計算,這里調整為快速傅里葉計算(FFT)。
所以,這里我們將模擬代碼作了以下調整,順便作了在不同采樣頻率下的模擬測量值比較:
在原來的模擬超聲波接收信號的生成數據中,加入最后衰減的部分;
在生成的相關性序列中,只取中間點右側的一半作為分析處理部分;
圖像輸出時,仍然輸出全部的相關性序列;
在生成相關性序列時,需用了FFT的模式(原先的選用的直算的方式);
降低“采樣頻率”到5MHz,然后采樣插值的方式進行相關性處理。
上圖模擬的是16m/s下,5MHz采樣率,得到的輸出值:
T1_0: 4.5617943222309144e-07
Length of t lags: 2000
Ts Delayed cycles: 23 ,
Delayed time: 4.6e-07
degree(相位差,角度): 165.6
Sample time interval(采樣間隔時間): 2.0e-08
Estimated velocity: 16.134001423268288(m/s)
不同采樣率,不同模擬流速下的模擬輸出比較(都有插值)
從模擬結果來看,較高的采樣率確實可以獲得較高的測量精度,而低的采樣率,雖然適用了插值提高了測量精度,但是插值運算畢竟是基于我們設定了波形的形態進行的。實際應用,還是要根據實際需求和情況配置相關的軟硬件功能。
另外需要說明的是,在整個信號相關性處理的模擬過程中,這里并沒有將相關性結果序列歸一化后輸出,而是使用直接結果的方式。
小編還要留一個問題:如果插值處理中標識插值點數的參數有變化的時候,模擬結果會出現什么變化?歡迎大家測試并留個回復。
修改之后的模擬代碼
其中:模擬代碼中的噪聲部分是被注釋掉的
import numpy as np import matplotlib.pyplot as plt from scipy.signal import correlate import math from scipy.interpolate import interp1d def cor_demo(): try: # Parameters c = 4500 # Sound speed in the fluid in m/s d = 0.5 # Pipe diameter in meters theta = math.pi / 6 # Angle of the emitted ultrasound wave, in radians. 30 degrees here. L = d / math.cos(theta) # The sound path length in meters parallel to the flow direction v = 16 # Fluid velocity in m/s f = 1e6 # Frequency of the signal in 1MHz T = 1 / f # Period of the signal in s Fs = 5e6 # 采樣頻率為5MHz Ts = 1/Fs # 采樣間隔 # Calculate time delay caused by flow velocity time_up = L / (c - v * math.sin(theta)) # Time of flight upstream time_down = L / (c + v * math.sin(theta)) # Time of flight downstream print("T1_0:",time_up-time_down) t_delay = 2 * L * v * np.sin(theta) / (c**2 - v**2 * np.sin(theta)**2) # Time array # 返回一個從0到period*T范圍內的有num_samples個元素的一維數組,數組中的數值是等間距分布的 period = 40 num_samples = period*T/Ts t = np.linspace(0, period*T, int(num_samples)) t_max = t.max() t_start_decay = t_max * 5/6 # 定義信號衰減準則 - 衰減系數一般由物質的特性決定 attenuation_coefficient = 10e5 # Signals stationary_s0 = np.sin(2 * np.pi * f * t[t=t_start_decay])* np.exp(-attenuation_coefficient * (t[t >= t_start_decay] - t_start_decay)) decay_s1 = np.sin(2 * np.pi * f * (t[t>=t_start_decay]-t_delay))* np.exp(-attenuation_coefficient * (t[t >= t_start_decay] - t_start_decay)) #s0 = np.sin(2 * np.pi * f * t)* np.exp(-attenuation_coefficient * t) #s1 = np.sin(2 * np.pi * f * (t - t_delay))* np.exp(-attenuation_coefficient * t) #*2.0 # Signal 1 s0 = np.concatenate([stationary_s0, decay_so]) s1 = np.concatenate([stationary_s1, decay_s1]) """ noise0 = np.random.normal(0, 0.5, s0.shape) noise1 = np.random.normal(0, 0.5, s1.shape) s0 = s0 + noise0 s1 = s1 + noise1 """ # Define interpolation factor interp_factor = 10 # New time vector after interpolation t_new = np.linspace(t.min(), t.max(), t.size * interp_factor) # Create a function based on the original signals, which can be used to generate the interpolated signals interp_func_s0 = interp1d(t, s0, kind='cubic') interp_func_s1 = interp1d(t, s1, kind='cubic') # Generate the interpolated signals s0_new = interp_func_s0(t_new) s1_new = interp_func_s1(t_new) # 計算Cross-correlation,并找到最大值對應的位置 #correlation = correlate(s1, s0, method='direct', mode='full') # old correlation = correlate(s1_new, s0_new, method='fft', mode='full') # 找出該序列的長度 len_corr 和其中間點 mid_index len_corr = len(correlation) mid_index = len_corr // 2 #取序列中間值右邊的序列(包含中間值) corr_half = correlation[mid_index:] #lags = np.arange(-len(s1_new) + 1, len(s1_new)) # Lags array lags = np.arange(0, len(s1_new)) # Lags array print("Length of t lags:", len(lags)) # Calculate flow speed using the estimated time delay # Find the peak of the cross-correlation corresponds to the time delay delay = lags[np.argmax(corr_half)] # 相位差所對應的信號序列值 # 采樣時間 sample_time = (period*T) / len(t_new) time_delay = delay * sample_time # 兩個信號間的延遲時間 phase_shift = (time_delay / T) * 2 * np.pi # 由時間延遲換算成的兩個信號序列的相位差 phase_shift_deg = phase_shift * (180 / np.pi) # 由相位差換成的兩個信號序列的角度差 print("Ts Delayed cycles:", delay, ", Delayed time: ", time_delay, "degree:", phase_shift_deg) # 將延遲轉換為相位差 print("Sample time interval:",sample_time) # 計算所得的流速 v_estimated = (math.sqrt((L**2)+(time_delay**2)*(c**2))-L)/(time_delay * math.sin(theta)) print('Estimated velocity: ', v_estimated) # 輸出圖 fig, (ax_origin, ax_interpo, ax_corr) = plt.subplots(3, 1, figsize=(12, 8)) # 原始信號圖 ax_origin.plot(t, s0, label='Signal 1') ax_origin.plot(t, s1, label='Signal 2') ax_origin.set_title('Original signals') ax_origin.legend() # 插值后的信號圖 ax_interpo.plot(t_new, s0_new, label='Signal 1') ax_interpo.plot(t_new, s1_new, label='Signal 2') ax_interpo.set_title('interpolated signals') ax_interpo.legend() # 互相關圖 ax_corr.plot(correlation) ax_corr.axvline(x = len(correlation)//2 + delay, color = 'r', linestyle = '--', label = "Max correlation at delay") ax_corr.set_title('Cross-correlation between signal 1 and signal 2') ax_corr.legend() plt.tight_layout() plt.show() return except Exception as e: print("Error:",e) if __name__=='__main__': cor_demo()
-
流量傳感器
+關注
關注
1文章
182瀏覽量
22162 -
FFT
+關注
關注
15文章
434瀏覽量
59366 -
信號
+關注
關注
11文章
2789瀏覽量
76730
原文標題:流量傳感器(2-1)超聲流量傳感器-信號采樣率的影響及相關處理插值模擬部分的代碼更新
文章出處:【微信號:安費諾傳感器學堂,微信公眾號:安費諾傳感器學堂】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論