日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

频域补零上采样_AURIX 学习笔记(12)频域法互相关实现超声测距

發(fā)布時間:2024/4/18 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 频域补零上采样_AURIX 学习笔记(12)频域法互相关实现超声测距 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

概述

上一篇 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)化思路:
  • 「參考信號頻譜的共軛 」是個常量,沒必要反復算,算一次存起來即可;
  • 實信號的頻譜,正頻率和負頻率成分呈共軛對稱關(guān)系,所以乘法只需要算一半, 也只需要存一半;
  • 相對于 123.76 kHz 采樣率(根據(jù)奈奎斯特采樣定理,有效頻率是一半),超聲收發(fā)系統(tǒng)通帶很窄,不到有效測量頻率的 。而通帶以外算不算都是 0。
  • 于是,實際上每次只要算 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ā)信號的時延,減去幀長度并打印到串口。超聲信號線計算步驟:

  • 等待 DMA 中斷
  • 在 DMA 中斷服務中將最新信號復制到 copy_buffer+256,也就是歷史數(shù)據(jù)的后一半。這一步要第一時間做,免得下一個 VADC 完成沖了這次的結(jié)果。所以在中斷服務里做就不錯。拷貝用 memcpy,比手寫循環(huán)快!即使手工優(yōu)化到 64 位拷貝一次 memcpy 還快 20% 以上!
  • 將 copy_buffer+256 拷貝到 fft_buffer+512,fft_buffer 的前 512 點是上次的 copy_buffer,要在上次計算結(jié)束時準備好
  • 求 fft_buffer 中這 768 點的均值,減去均值。VADC 給出的是12 位無符號數(shù),FFT 要補 0,不減去直流分量會導致引入一個階躍信號,階躍信號有極寬的頻譜,會污染信號頻帶,導致準確性下降。之所以 768 點求一次,而不是 DMA 之后 256 點求一次,是為了避免直流分量的不夠平穩(wěn)在一次計算中每 256 點減的是不同的數(shù),這個可以優(yōu)化減少加法計算,但時間夠用,沒必要
  • FFT!
  • 由于我們采樣率僅有 123.76 kHz,高頻幾乎已經(jīng)占滿,不必再濾了。用 memset 將頻譜 0~39 kHz 的成分干掉,然后將負頻率成分全部干掉。這就是沒有相位延遲的理想帶通濾波,比什么 FIR、IIR 高到不知哪里去了
  • 從 39 kHz 開始,乘上參考信號的頻譜,這一步可以做某種白化濾波、頻域加權(quán)、均衡之類的操作
  • IFFT!
  • 在這個窗口的互相關(guān)譜上尋峰,保存
  • 實現(xiàn)中的坑

    注意,這個計算步驟里有一個大坑,就是 AURIX 的硬件 FFT 是定點運算,固定的 sint32。所以要時刻警惕溢出!參考信號先在線下做個 FFT 看一下,要保證其 FFT 之后幅度譜小于

    ,這樣才能保證完全對齊時信號頻譜與參考信號頻譜的乘積不溢出,這個實際上要求參考信號幅值要比較小,最好先寫程序驗證一番。

    此外,還有一些小坑。

    • 雖然:
    /** brief Configuration structure for the FFT job*/ typedef struct {IfxFft_Fft *fft; /**< brief Pointer To FFT.Used when (IFXFFT_FFT_OPTIMIZED == 0) */uint16 inputLength; /**< brief Length of the input */uint16 outputLength; /**< brief Length of the output */IfxFft_Length fftLength; /**< brief Length of the transform */IfxFft_Input inputFormat; /**< brief Input format */IfxFft_Output outputFormat; /**< brief Output format */IfxFft_Operation operation; /**< brief Operation (FFT / IFFT) */boolean useWindowFunction; /**< brief Selection to use window function */IFX_CONST void *inputPtr; /**< brief Pointer to input data */void *outputPtr; /**< brief Pointer to output data */ } IfxFft_Fft_JobConfig;

    里有 inputLength 和 outputLength 兩個字段,但這兩個字段不一樣會導致 FFT 計算無法完成,沒看到相關(guān)描述,原因不明。對我影響不大,我就沒仔細研究。

    • 不要讓編譯器自動分配大塊內(nèi)存,用 __at(p) 指定。親測
    #pragma section farbss bss_cpu0 #pragma section farbss restore

    沒有卵用,還是會從 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)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。