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