1. 程式人生 > >LimeSDR 中文教程 (七)

LimeSDR 中文教程 (七)

GNU Radio中接收和發射ASK訊號

這是第七篇教程。我們繼續上一次的內容,我們會仿製出一個最簡單的無線電裝置。上一篇文章我們可以接收位元流,但是每個符號對應的位元數是錯誤的。這篇文章,我們計劃改進ASK接收機,並且設計一個發射機,重放資料。

要實現這個目標我們需要同時有發射機(類似遙控器)和接收裝置。我們手頭正好有Brennenstuhl Primera-Line遙控插座。出於好奇,我們看了它的遙控器訊號,它們也是ASK而且還是OOK,因此我們的流圖幾乎不需要大概就能適配。

我們上次做到這裡

這是我們上次的流圖,如果你沒看過這篇文章最好看一下。在我們深入之前,最好先回憶一下這個流圖做了什麼,以及如何實現的。

osmocom source 對應於LimeSDR

DC blocker 用來對接收到的訊號去除直流分量,這個模組使得示波器不會顯示出大的直流分量

Multiply const 模組產生了一個固定的數字增益,大小是10

RMS 模組把訊號從正弦波的形式轉換為二進位制形式

Add const 增加了直流偏置,把訊號移動下來,使其穿過零點,這是Clock recovery模組要求的

Clock recovery模組和Binary slicer模組把資料恢復出來並記錄到檔案中

AM解調

我們現在用RMSAM解調,做得還不錯,但是原理是什麼?

如果我們看一下RMS模組內部,它很簡單:Out = sqrt(Avg),其中

Avg = (1-Alpha)*Avg + Alpha*abs(in)^2,我們這裡設定Alpha=1,那麼Avg = abs(in)^2

我們看一下正弦波的絕對值,我們會得到上述波形,然後把這個波形和原始波形以10個取樣點取平均,我們會得到:

正弦波=0

Abs(正弦波)=0.5

現在你應該可以清楚知道RMS模組為什麼能解調AM訊號了,因為當載波出現時RMS模組輸出一個大於0的值,沒有載波時輸出等於0

Clock Recovery模組

上一篇文章中我們發現,用程式來解調位元比直接觀察波形更難。因為我們必須根據位元的波特率在正確的時間點取樣,並解碼出位元流。我們使用了clock recovery模組,我們上次用幾個位元組來表示一個位元。我們上次說了這是因為我們沒有選擇一個正確的

Omega值。Omega值代表每個位元對應的取樣點數量(等效于波特率)。

我們如何知道每個位元對應多少採樣點?

首先我們需要知道每個位元對應的長度。有很多方法,最簡單的是找datasheet。我們這次無法找到。或者用URH程式可以幫助我們做這個事情,但是隻用GNU Radio也可以實現。

有些裝置的波特率會變化,這樣難度比較高。比如之前在eBay買的遙控鑰匙就是這樣,那麼就會增加難度。所以現在我們換成了另一個遙控電源開關。

Brennenstuhl電源開關就沒有這個問題。我們只需要在RMS模組後接一個示波器,然後計算最小的脈衝的長度,就可以得到準確的Omega值。我們算過了上升沿和下降沿的時間間隔大約是0.51ms。我們的取樣率是1MSps/s,因此每1x10^-6秒就有一個取樣點。那麼我們可以得到0.51ms對應於510個取樣點,這個510就是我們的新的Omega值。

在我們把510輸入到clock recovery模組中前,我們要知道,把這麼大的數字作為Omega不太好。最好先做降取樣,然後再做clock recovery。我們增加一個Rational Resampler,然後降取樣率設定為10,這樣每個符號對應的取樣點數量就降為了51,這個數字設定為Omega更好。

位元流是關鍵

現在我們的解碼器就可以正常解調UHF電源開關的訊號了,我們可以解調開關按鈕各自的訊號,我們就得到下面兩個位元流:

每次傳輸(包含重複傳輸)都會有這個前導碼: 11111100000000000000

關閉按鈕的載荷 payload:110100110110110110100110100110110110100110110110100100110100110110100100111111

開啟按鈕的載荷 payload: 110100110110110110110110110100100110110110110100100110100110110110100100111111

開關按鈕的區別很小。根據這種式樣,很有可能這個位元流使用了某種形式的反碼演算法,來實現編碼增益並對抗干擾。

構建發射流圖

瞭解怎樣的資料在開啟和關閉我們的Brennunstuhl很不錯,但是如果無法發射這樣的訊號那也美多少用處。我們現在建立一個433MHzOOK發射機,並且重複我們前面觀察到的序列。

流圖中首先應該有我們觀測到的資料。就像接收和解碼資料時一樣,有各種方法來儲存這個資料。為了方便,我們這裡使用了Vector Srouce,而不是檔案儲存或者message box。把我們的資料編碼為vector,它看上去是這樣的:(1,1,0,1…中間省略…,0,0,1)。我們還加入了150作為間隔,這樣每次重複的資料間會有個暫停。

這個vector source會不停迴圈播放位元流,但是播放的速率是流圖設定的取樣率,在我們這裡是1MSps/s,這樣它的速度會比我們需要的快510倍。我們可以用一個超大的vector代替,每個位元都重複510次,比如1替換為1111…中間502…111。但是這樣的實現方式不優雅。更好的方式是使用Repeat Interpolation模組。這樣它會根據差值長度來重複每個位元(在我們這裡就是重複510個取樣點),這樣的效果實際上是一樣的。接下來,我們可以使用Throttle模組來設定位元率為1MSps/s。這個模組會對流過的取樣點的數量進行限制,把我們的輸入速度降下來,達到目標波特率。這樣我們就有了一個方波,波特率符合我們的要求。然而這是一個數字訊號,沒有載波,無法傳輸。

首先我們需要一個載波,使用一個433.91MHz的正弦波應該夠了。我們用Signal Source來建立。OOK訊號的好處是,它們要不就是開啟(值是1),要不就是關閉(值是0),那麼我們只需要把載波乘上去就完成編碼了。

最好增加一個門,我們可以用GUI Chooser來選擇01,這樣用這個來控制另一個乘法模組,來控制訊號是否發射,我們還可以在其中增加數字增益。最終我們可以用一個按鈕來實時控制。

最後一級是Osmocom Sink,我們設定為正確的引數後就好了:

  • Device Arguments: “driver=lime,soapy=0”
  • Frequency: 433.91e6
  • Bandwidth: 5.1e6 我們必須這樣設定,否則GNU Radio會自動填寫一個錯誤的值,造成流圖無法生成.

在按下執行按鈕前,必須注意儘管433MHz是免費頻段,但是你還是要限制發射功率,把增益降低或者用一個小天線就可以滿足這個要求。如果你不確定,可以先用一個較低增益試試。

經常有人會認為更多增益會更好。不是所有情況下都這樣的,比如一個接收機正好在發射機旁邊時,太大的增益會使接收機飽和,接收效果反而不好。

最後

我們希望這篇文章展現了GNU RadioLimeSDR的強大之處,我們自己實現了一個遙控器,用來控制我們的電源開關,只需要這麼一個簡單的流圖就能實現。這個對於所有OOK裝置都是如此,包括你鄰居家的門鈴,所以使用這個流圖的時候需要你自己負責。對於433MHz頻段,我們暫時就講到這裡了,但是我們將來可能還會回來講FSKPSK,我們可能會嘗試一些別的裝置。