一種短距離聲波通信的方案

    短距離通信方法很多,有NFC、二維碼、藍牙等,它們各有各自的特點和限制。比如NFC和藍牙需要硬件支持,二維碼是一個偉大的發明,解決了很多問題,但是前提是信息接收的一方需要有圖像採集單元。聲波通信是利用發送端播放包含了信息的音頻,接收端對音頻進行採集,分析出發送的數據來進行通信。所以也有一個限制就是接收端和發送端得有音頻輸入和音頻輸出的單元(這是顯而易見的)。目前聲波通信的方案有很多,比如支付寶咻咻咻等,而根據方案的不同還有其他方面的限制,比如採樣率、性能消耗和自動增益單元等。

    由於項目原因,需要在嵌入式設備上實現聲波通信的接收端。平臺是ARM 32bit 500M單核CPU。要求CPU使用率不能太高。音頻輸入設備是固定增益。產品需求上一次傳輸大約64byte字節左右的數據,在3~4s內完成,並且達到一個比較高的成功率。

    實際的設計主要分爲兩個層次,物理層和鏈路層,下面分別敘述兩個層:

一.聲波物理層

    1.音頻信道採樣率:音頻處理使用FFT實現,所以考慮到CPU使用率,本方案使用16KHz 採樣16bit的音頻。

    2.比特數據的調製。

    這裏先說傳輸1bit數據的方法,發送端發送頻率相鄰的兩個頻率中的一個來分別代表0和1。如圖1所示。

 圖1

    圖中黑色粗線代表發送端這段時間內信號中存在頻率f1或者f2。對應圖下面的值爲0和1。圖中後面兩種情況在發送端不會發生。

    關於這種方法的特點就要說到另一種方法,即發送段一段時間內發送一個頻率f的有無來代表1和0。如圖2所示。

圖2

    最開始開發時候用的就是這種方法(其實過程中還踩過各種坑哭,就不一一例舉了)相對來說這種方法的優點在於用到的頻率點只有一個,但是缺點很嚴重,在開發過程中發現,實際上接收端不能很準確的判定頻率f1的有和無,比如用FFT結果中f1當前振幅A和一個閾值B比較,那麼閾值B如果太大在發送端聲音較小,或者接收端在該設備上的頻率響應較差的情況下會誤判;閾值B如果太小容易對噪聲進行誤判。而最理想的結果就是只能在一個特定的設備上每個頻率點調出來一個很好的閾值B,這樣就不具有通用性,而且通信的兩個設備的距離和音量同樣也影響振幅的大小。當然之前還在這個坑裏待了挺長時間,甚至想到了前後振幅變化了確定有無,依然失敗告終(實際信號有到無的過程中振幅有抖動)。

    論述完上述方法之後圖1的方法優勢就很明顯了,接收端只需要比較f1和f2振幅大小就行,比如f1>f2時就是存在頻率f1而沒有f2。這樣在一般情況下,f1和f2衰減都會一起衰減,增大也會一起增大,所以不會受硬件頻率響應、傳輸距離和音量大小的影響;實際上基本原理就是差分傳輸有效抑制共模干擾。

    3.前後幀判斷

    接收段通過FFT分析一段一段的音頻數據,這個應該叫做短時傅里葉變換,即對信號進行加窗分別計算FFT結果。這樣就能知道聲波在哪段時間擁有那些頻率。如圖3所示。

圖3

    FFT時間爲T,那麼最好情況就是接收端在T時間裏正好採到了圖1中黑色粗線,緊接着下一個採到下一幀。顯然這是不可能的,所以我的方法是發送端發送的數據幀長爲3T,接收端進行FFT計算的幀長爲T,這樣在接收端的窗口與數據幀偏移的任何情況,都會有一個完整的數據幀落在FFT窗口裏。如圖4所示。

圖4

    而圖4中FFT3的數據中可能會計算出有頻率f1或者沒有頻率f1。所以多個FFT數據中如果發現f1連續出現2~4次認爲是發送了一幀數據,同理可以推廣到多個的情況,如果FFT計算出來的個數是5~7個,那麼真是的數據就是2幀並且兩幀數據一樣。

    4.數據幀長度

    由上述可知,由於數據幀的長度是FFT計算窗的3倍,所以數據幀的長度除了會影響到傳輸時間外,還影響FFT結果中的頻率分辨率(由於海森堡測不準原理,如果要想FFT窗口小,頻率分辨率就會低。要想頻率分辨率高,FFT窗口就得大),並且數據幀長度除以3的採樣點個數得是2的整次冪。而且最終一幀傳輸的不是一個bit而是多個bit(這個下文會說)。綜合考慮選取的是24ms一幀。16KHz採樣下FFT窗口(8ms)就是128個採樣點,對應頻率的量化步進就是125Hz,即FFT結果中依次是0、125、250、375、500.....的振幅數據。

    5.多頻同時傳輸

    前面論述了聲波通信的基本原理和相關參數的大小,但是說的是1bit的傳輸方式,使用上述的方法在不同頻率上可以同時傳輸多個比特。相當於是創建多個傳輸信道,提高傳輸速度。

    通過實際錄製的音頻的光譜圖可以看出,在1000Hz以下的環境噪聲比較大,而由採樣定理可以知道,16KHz可以採集的頻率在8KHz以下,所以最後選取得到的以下10個傳輸通道的相鄰兩個頻率點:

    通道1:1375Hz、1625Hz

    通道2:2000Hz、2250Hz

    通道3:2625Hz、2875Hz

    通道4:3250Hz、3500Hz

    通道5:3875Hz、4125Hz

    通道6:4500Hz、4750Hz

    通道7:5125Hz、5375Hz

    通道8:5750Hz、6000Hz

    通道9:6375Hz、6625Hz

    通道10:7000Hz、7250Hz

    6.奇偶校驗糾錯

    實際開發過程中發現,在聲波傳輸過程中,通常會導致某一個通道內頻率衰減(比如距離、遮擋)。甚至會衰減到通道內兩個頻率振幅大小都無法判斷導致數據不對的情況。所以5中所述的10個通道中用一個通道來傳輸一幀數據(24ms)中其他9個通道的奇偶校驗信息,當物理層檢驗發現數據有錯誤時(通常認爲1個比特位不對),會翻轉各個通道中最大振幅最小的哪一個比特,嘗試更正錯誤。因爲實際環境中通常都是頻帶衰減厲害導致數據傳輸錯誤,故在聲波通信中可以認爲發生錯誤的應該是振幅最小的那一個比特通道。

二.聲波鏈路層

    鏈路層主要是根據應用程序要傳輸的數據進行RS糾錯編碼和封包,包括了包頭(包含數據大小)、數據、糾錯數據三個部分。

    1.數據包的結構

    上層每4byte數據爲一個數據包,最後不足4byte的爲一個包。如圖5所示:

    

圖5

    包頭:包頭主要用來識別一個數據包的開始,目前定的是0x34,最低兩位是用來記錄數據的大小(單位:字節)。

    數據:即要傳輸的數據中的四個字節,在數據流末尾如果不足四個字節也封爲一個包。

    RS糾錯位:由於聲波的應用場景往往是單向傳輸,所以不能像TCP通過重傳來解決誤碼的問題,只能由包內包含的信息最大程度上還原錯誤的數據。由數據段裏面的所有數據生成的糾錯段,糾錯段和數據段總共糾錯能力是2byte以下(包含2byte)。

    2.數據包的傳輸方式

    發送時鏈路層數據包由物理層拆分爲一幀一幀的數據(由一中的5所述,一幀數據是9bit)來生成波形,接收端也是解析一幀一幀數據由鏈路層還原成數據包再丟給上層數據。而具體的拆分數據幀的方式有兩種,如圖6和圖7所示:

 

圖6

圖7

    由圖可以看出其實就是橫着放和豎着放的區別。最終使用的是圖7的方式,而圖6的方式主要有兩個缺點:

    缺點1:包頭的數據不好確定,同樣是8bit,後面的數據段也可能出現和包頭一樣的數據而誤判。當然這個也是可以解決的,我們有9個通道,可以給包頭第9bit數據置1來區分頭數據和中間的數據。但是這個不是主要缺點。

    缺點2:在實際通信過程中,正如一中6所述,往往出現問題都是有一個通道的頻帶出現驗證衰減,導致的誤碼;那麼在圖6的方式中有一條通道誤碼(假設物理層奇偶糾錯沒有糾正過來),就會導致當前數據包的每一字節部分的數據都可能有1bit的錯誤。而RS糾錯只能糾錯2byte。所以在這種情況下RS糾錯的意義不大。

    在圖7的方式中,包頭和數據包的其他部分並不在一個通道內,所以很好區分,而且只有1byte。如果有一個通道的頻率衰減導致的也是一個字節的錯誤,這時候RS就能正確的糾正過來。

三.總結

    以上敘述了一種聲波通信的具體方案,是在實際開發過程中很多次的嘗試定下來的一個相對較好的方法,實現了在嵌入式設備場景下的聲波通信,對音頻硬件模塊要求不高,性能消耗較小,目前已經在我當前項目產品中使用。

    但是目前該方案還有一些沒解決的問題,比如沒有解決聲波在小空間反射的問題、遮擋比較嚴重或者揚聲器和mic相互背對的情況下成功率較低、聲波的音頻不太好聽的問題(嘗試提高採樣率和各通道頻率效果較好,但是目前項目不支持,所以有需要的可以自行更改或者聯繫我)。這些問題在之後希望可以得到解決,同時也歡迎大家提出好的方案和建議大笑

    源碼地址:聲波通信源碼

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章