频域补零上采样_AURIX 学习笔记(12)频域法互相关实现超声测距
概述
上一篇 AURIX 學習筆記(11)外部中斷以及基于時域互相關(guān)的超聲測距 介紹了 TC264D 實現(xiàn)超聲波測距應用的結(jié)構(gòu)、原理等,也提到時域法的不足:計算復雜度高、濾波手段少、沒有充分利用單片機外設資源。頻域法互相關(guān)利用 FFT 模塊,補上了時域法的短板,可以取得比較良好的效果。本文介紹頻域法相對頻域法的改動——主要是相關(guān)計算的改動——以及在 TC264DA 上實現(xiàn)頻域互相關(guān)的一些細節(jié)(浪費調(diào)試時間的坑)。
頻域互相關(guān)原理
數(shù)學原理
上一次寫過,離散互相關(guān)運算的時域表達:
并且,我們知道離散卷積運算的表達式是:
發(fā)現(xiàn)兩個表達式唯一的不通是原信號
取 還是 ,換句話說,離散互相關(guān)和離散卷積的唯一區(qū)別是原信號的一次反褶。所以還可以從卷積運算滿足交換律推出互相關(guān)運算不滿足交換律。并且很容易記住交換互相關(guān)的兩個信號導致相關(guān)譜的反褶。我們還知道:
所以,可以寫出互相關(guān)的頻域表達:
其中,
是離散傅里葉變換, 是離散傅里葉反變換, 是同維向量的對應項相乘, 是對復信號取共軛。性能分析
原本
的互相關(guān)運算,將被轉(zhuǎn)化為 2 次傅里葉變換、1 次傅里葉反變換,以及 的取共軛再相乘(注意,這里是復數(shù)相乘,一個復數(shù)乘是 4 個實數(shù)乘和 2 個實數(shù)加)。并且,很容易想到更多優(yōu)化思路:于是,實際上每次只要算 1 次傅里葉變換、1 次傅里葉反變換,以及最多
頻譜長度的共軛和復數(shù)乘法(乘,然后共軛生成負頻率成分)。對比時域法的性能:- -O3 下,200 點參考的互相關(guān)譜 1 個點約 600 周期
- 1024 點 FFT/IFFT 5000 周期,算上拷貝,置零之類的,差不多 20000 周期能完成一次普通的互相關(guān)運算,但這相當于是 256 點參考的 1024 點互相關(guān)譜, ,是 的差不多 40 倍
為啥 1024 點 FFT 實現(xiàn)的是 256 點參考的 1024 點互相關(guān)譜呢?
理解這個需要在有限長信號下考慮互相關(guān)運算。互相關(guān)本質(zhì)上是在計算兩個信號在不同對齊方式下的內(nèi)積,或者說,兩個無限維向量在方向上的接近程度(假設它們的長度/幅度已經(jīng)歸一化)。所以對于實際上有限長,或者是窗口外全為零的信號來說,它們的窗口至少有一個公共非零點,才能得到非零的內(nèi)積,才能得到非零的相關(guān)譜線。當
的 挪動參考信號時,互相關(guān)譜的第一點是參考信號的尾重合于信號的頭,即 ,把參考信號左移了參考信號長度少一個。所以教科書上寫道 m 點參考和 n 點信號的互相關(guān)得到的是 m+n-1 點互相關(guān)譜。那么 1024 點的 DFT 自然得到 1024 點的互相關(guān)譜,m+n-1 不能大于 1024,否則由于 FFT 假設周期延拓,得到的是混疊的互相關(guān)譜。而 m+n-1 較小則會在互相關(guān)譜里補零,有點浪費計算量。所以 1024 點 FFT 是肯定不能計算 1024 點參考的互相關(guān)的,選擇 256 的其他理由在后面。
知乎的分隔線好大!分幀問題
當然,這種加速也是有代價的,代價就是「窗」的存在。時域互相關(guān)可以每一點都算一次,完全從定義出發(fā)。而頻域則必須截取一段時域信號,才能享受這個加速的優(yōu)勢。截的越長,優(yōu)勢越大。
這個在軟件互相關(guān)才是完全正確的,按理說 FFT 使得 加速到 ,加速效果隨 n 指數(shù)增長。但 AURIX 學習筆記(10)硬件 FFT 寫過,TC264DA 的 FFT 模塊差不多是線性的。但是(相同采樣率下)更長的窗就是更多的點數(shù),通常會使用更長的 FFT,由于頻譜點數(shù)也變多,相當于頻域分辨率加大,還是會獲得一些精度提升。有窗,就會遇到窗里有沒有我要的信號?有多少?如果只有一半在窗里怎么辦?等等問題。這些問題非常現(xiàn)實。為了解決窗里截到部分信號的問題,就需要重疊分幀。如圖所示:
重疊分幀,保證至少有一幀包含完整的目標信號只要滿足這些條件:
就能保證至少有一幀包含完整的信號。
總結(jié)一下,現(xiàn)在我們的(幀、重疊部分、參考信號)長度選擇受到以下限制:
而我們回頭去考察時域互相關(guān),會發(fā)現(xiàn)時域互相關(guān)其實就是
、 的而已,所以一次只能算出 1 個點也沒什么奇怪的。這也告訴我們重疊長度越小,重復計算就越少,當然相當于性能就越高。進一步考慮,為了讓 CPU 多做事,不應該讓 ADC 中斷這樣的例行公事頻繁打擾 CPU,那就要使用 DMA,而又由于 AURIX DMA 的奇怪設計,其地址循環(huán)必須是 2 的整數(shù)次冪。
當然地址循環(huán)是,中斷不一定非要和地址循環(huán)對應,這里仍有優(yōu)化空間。可以改但沒必要。所以選擇幀長度=768,參考長度=重疊長度=256 就顯得比較自然、順理成章了。
實現(xiàn)
為了使用頻域法計算互相關(guān),進行下列配置:
- 分配內(nèi)存
- 供 ADC 的 DMA 寫的 uint16 vadc_buffer[256]
- 保存歷史數(shù)據(jù)的 uint16 copy_buffer[512]
- 保存參考時域信號的 const sint16 reference_signal[256](編譯器懂,這個在 ROM 里)
- 保存參考共軛頻譜的 sint32 ref_buffer[1024](1024 是 512 個復數(shù),實際上可以在外面算頻譜,不存時域的,讓這個在 ROM 里。但是反正內(nèi)存夠用,這樣顯得原汁原味)
- 用于 FFT 計算的 sint32 fft_buffer[2048](這才是 1024 個復數(shù))
- 初始化外設
- VADC 模數(shù)轉(zhuǎn)換模塊、及其 DMA
- ERU 外部中斷模塊
- ASC/UART 串口通信模塊
- FFT 模塊
- 計算:計算參考信號頻譜,把一半的共軛保存到內(nèi)存對應區(qū)域
計算過程仍分超聲信號線和觸發(fā)信號線,觸發(fā)信號到來時總結(jié)最高峰到上一個觸發(fā)信號的時延,減去幀長度并打印到串口。超聲信號線計算步驟:
實現(xiàn)中的坑
注意,這個計算步驟里有一個大坑,就是 AURIX 的硬件 FFT 是定點運算,固定的 sint32。所以要時刻警惕溢出!參考信號先在線下做個 FFT 看一下,要保證其 FFT 之后幅度譜小于
,這樣才能保證完全對齊時信號頻譜與參考信號頻譜的乘積不溢出,這個實際上要求參考信號幅值要比較小,最好先寫程序驗證一番。此外,還有一些小坑。
- 雖然:
里有 inputLength 和 outputLength 兩個字段,但這兩個字段不一樣會導致 FFT 計算無法完成,沒看到相關(guān)描述,原因不明。對我影響不大,我就沒仔細研究。
- 不要讓編譯器自動分配大塊內(nèi)存,用 __at(p) 指定。親測
沒有卵用,還是會從 0x60000000 開始分配。 而 Cpu0 對應的內(nèi)存地址從 0x70000000 開始,訪問 0x60000000 段會慢 3 倍。
實測效果
知乎視頻?www.zhihu.com代碼在 https://github.com/autolaborcenter/test_aurix 。和本文描述不完全一樣,因為還在探索之中。但不一樣的主要是過濾、優(yōu)化,外設使用基本不會有什么變化。要做到這個視頻的效果還需要一些對峰值的后過濾,目前還在優(yōu)化,這次就不寫了。說實在話,這些優(yōu)化都不如干脆發(fā)大點的信號有用,所謂力大磚飛是也。有什么問題歡迎討論。
總結(jié)
以上是生活随笔為你收集整理的频域补零上采样_AURIX 学习笔记(12)频域法互相关实现超声测距的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 拟合一条曲线_数据预测与曲线拟合
- 下一篇: react 判断图片是否加载完成_如何判