2020年6月19日 星期五

Signal Generators

(Including AD9833AD9834AD9850ADF4351)

緣由
最近在學習 SDR,會需要用到 訊號產生器市面上有的機型 具有非常強的功能,但是通常也不便宜。在網路上找一下,發現這塊 AD9833 模組,它雖然比較偏向音頻的用途,但價錢非常便宜而且取得方便,所以就買了幾塊來試試,並且用 Python 寫了對應的 driver,可以跨平台適用在 PC (Windows / Linux,需使用 USB-SPI converter)、Raspberry PiESP32 上面。
後來索性把市面上較常見的幾種 signal generator 模組 (AD9833AD9834AD9850ADF4351的 python drivers 都寫一寫,GitHub repository 在 這裡。 

訊號產生器 的 種類與特點
我將 訊號產生器 大致區分為以下三個種類:
1. 獨立機台:
機種非常多 (例子),功能會因為應用領域而有些微不同。特色為:
優點: 
  • 可以獨立使用,不需要依賴與耗用 PC 的資源。
  • 由很多硬體元件所組成,運行效率高。
  • 功能齊全完備。
缺點:  
  • 功能雖多但還是受到限制,擴充不易 (可能需要額外的費用)。
  • 有的機型 可以需依照廠商所定的 API / protocol 來與 PC介接溝通,但仍有學習門檻。
  • 廠商所提供的 driver / API / utility 不一定能跨平台 (Windows / Linux)。
  • 無法透過 MCU (例如 ESP32、Arduino) 來操作。
  • 價位較高。
2. Signal generator in an USB dongle (例子):
優點: 
  • 體積小,便於攜帶。
  • 仍含有專用的硬體元件,維持執行效率。
  • 可由 PC 上的軟體控制,應用上較為彈性。
缺點:
  • 通常較小型,功能有限。
  • 仍需透過 PC控制,某種程度地占用 PC 的資源。
  • driver / utility 不見得能跨 OS (Windows / Linux)。
  • 無法透過 ESP32、Arduino 使用。
  • 不是非常便宜。
3. Arduino-like based signal generator (例子):
優點
  •   可以獨立使用,不需要依賴與耗用 PC 的資源。
  •   便宜。
缺點
  •   不易與 PC 介接。
  •   可以獨立使用,但較難與其他設備協同作業。
  •   功能較有限。
網路上就有很多以 Arduino / ESP32 搭配 AD9833 模組的 例子,這也是我原本所採取的模式,但是有以下的考量。

Device driver 的開發模式
就以 "使用  Arduino / ESP32 或其他控制器 搭配 AD9833 來產生各種訊號" 這個目的來說,通常可以採用以下幾種開發模式:
1. 一般的開發模式:
在 PC 上編寫/編譯程式之後上傳到控制 AD9833 的裝置 (Arduino / ESP32)上,在程式中插入一些例如 "print" 的指令將執行狀況顯示出來,以作為 tracing / debugging 的依據;修正錯誤之後 再次重複以上的步驟。 
優點: 
  • 在真實的裝置中執行,其結果絕對真實。 
缺點: 
  • 須根據要檢測的點,逐一插入相對的 "print" 指令,並且要重新編譯,費工費時。
  • 無法設定中斷點,也就無法暫停程式的執行 以檢視流程與狀態。
  • 無法動態地 修改變數值 或 改變程式流程,必須重新修改編譯才行,費工費時。
  • 每次修改之後都需要重新編譯,並重新上傳到 MCU 上面,相當耗時。  
  • 跨平台的移植性較弱,為 Arduino 開發的程式 不見得可以在 ESP32、Raspberry Pi、PC 上面執行。   
優點: 
  • 不再需要手工加入 "print" 指令。 
  • 可以設定中斷點 暫停程式的執行 以檢視流程與狀態。
  • 可以動態地 修改變數值 或 改變程式流程。 
缺點:
  • 操作與設定較複雜,學習門檻較高。
  • 不是每種 MCU 都有支援。  
  • 不是每種 語言都可搭配 in-line debugger 使用 
  • 需要 IDE 有支援。 
  • 跨平台的移植性較弱,為 Arduino 開發的程式不見得可以在 ESP32、Raspberry Pi、PC 上面執行。   
 

目標
因為我比較常用 ESP32+ (Micro)Python,這邊就沒有考慮 Arduino。
這次實作 想達到的目標如下:
  • 建構必要的軟體,可以用 ESP32 / Raspberry Pi 來控制 AD9833 模組 來產生訊號。
  • 也可以使用 PC (Windows / Linux)來做控制 AD9833,這樣就可與 PC上的資源連接,例如將 PC 上的資料透過 AD9833 產生訊號發送出去。
  • 可以控制一個或多個 AD9833 來做多種 modulation (BFSK、BPSK、QPSK、IQ、FM、PM、OOK、DTMF)
  • 開發出來的成果,可以跨 OS (Windows / Linux) 與硬體 (PC / Raspberry Pi / ESP32) 地用來控制 AD9833。
  • 開發的過程中:
    • 不需要反反覆覆的上傳程式到 MCU 上。
    • 可以設定中斷點,也可以 監看或改變 變數的內容值,不需要使用 JTag,沒有學習門檻。

  • 使用 Python
    • Python 某種程度地將 OS 與 硬體平台 抽象化,同一套 Python 程式很可能可以在 Windows / Linux,Raspberry / ESP32上面執行,只需要經過些微修改,甚至不需要修改就可以運行。
  • 使用 Adapter 設計模式:
    • 將不同平台上驅動 bus (SPI / I2C / GPIO)的方式 包裹成 統一介面 的 adapters,同一套程式可以適用在 不同的 OS (Windows / Linux) 與硬體 (PC / Raspberry Pi / ESP32) 上,僅須依據不同的環境 選用不同的 adapter 即可,所需的調整微乎其微。
  • 將 registers 元件化:
    • 依照 AD9833 的規格書,將煩人的 register 讀寫透過元件來處理,只需要指定 欄位的名稱,不需要去計算左移、右移 的位數,例如要控制 SLEEP1 的欄位,只需:
      • def _enable_internal_clock(self, value = True):
        self.control_register.elements['SLEEP1'].value = int(not bool(value))
        self._update_control_register()
    • 可以隨時列出一個 register中 各個欄位的值,例如:
    • ad.control_register.print()
      
      << Control >>    :  ('0x2000', '0b10000000000000')
      [ D15 ]        :  0
      [ D14 ]        :  0
      [ B28 ]        :  1
      [ HLB ]        :  0
      [ FSELECT ]    :  0
      [ PSELECT ]    :  0
      [ PIN_SW ]     :  0
      [ Reset ]      :  0
      [ SLEEP1 ]     :  0
      [ SLEEP12 ]    :  0
      [ OPBITEN ]    :  0
      [ SIGN_PIB ]   :  0
      [ DIV2 ]       :  0
      [ Reserved_2 ] :  0
      [ Mode ]       :  0
      [ Reserved_0 ] :  0
    • Registers 狀態的比較:
      • 可以針對 兩組不同的 registers 設定值 做比較,並列出各個欄位的差異,這在 development 階段 debug 時候非常有用。
  • 可以直接在 PC 上直接控制 AD9833 模組
    • 使用 USB-SPI converter (例如 FT232H FX2LP),讓 PC 可以直接連接  使用 SPI 介面的 AD9833。
    • 透過 Bridges package,將 PC 假扮成 ESP32 / Raspberry Pi:
      • 讓 使用 USB-SPI converter 的 PC 具有 和 ESP32 / Raspberry Pi 相同介面定義的 SPI功能,將 PC 假扮成 ESP32 / Raspberry Pi,所以開發出來的 Python 程式不需要修改,直接複製過去 就可以在 PC / ESP32 / Raspberry Pi 上使用
      • 反過來說,網路上既有裝置的 Python driver,不論是為了 Raspberry Pi 或 ESP32 寫的,都很可能 只需經過極少的調整,甚是不需要修改,就可以在 PC 上面使用極大化地拓展 裝置可用的資源 與 PC可使用的裝置品項
    • 對開發上的影響:
      • 在 PC 上開發程式並直接控制 AD9833 來測試,不需要反反覆覆地上傳程式到 ESP32 上。
      • 利用 PC 上的開發環境優勢,例如先進的 IDE (如 PyCharm) 來開發程式,可以設定中斷點,隨時監看執行狀況並檢視變數值
      • 網路上既有的 Python device driver,只需經過極少的調整,就可以在 PC 上面使用,我們可以使用 PC 上 IDE 的 debug 功能,加速我們對 device 運作原理的了解,縮短開發時程
      • 可以透過 Jupyter Notebook 來測試與使用 AD9833,兼顧程式的發展與文件的累積。
    • 對 AD9833 使用上的影響:
      • 可以透過 PC 來使用 AD9833,與PC介接 沒問題。
      • 可以與 PC 上豐富的資源做連接,可最大化且彈性的擴充功能。 
        • 可以透過 Numpy 與各式各樣的 Python modules 來準備資料。
        • 可以直接在 PC 上透過 AD9833 做 modulation 發送資訊
      • 控制軟體化,不需要獨立的 MCU 就可以控制 AD9833。就如 SDR 的發展,可以省下部分硬體元件的成本
      • 除了 AD9833,也可以依照相同的模式 透過 PC 控制其他的裝置,達到協同作業的目的 (例如測試自動化)。

測試結果
Basic functional tests:
Waveform manipulation
  • Tested with this notebook:
  • Frequency sweeping:
Control AD9833 with PC + FT232H (USB-SPI converter) 
using Jupyter notebook


Control AD9833 with ESP32 
(which in turns is controlled via Jupyter + MicroPython Remote Kernel)


  • Waveform juggling:
Control AD9833 with PC + FT232H (USB-SPI converter) 
using Jupyter notebook


Control AD9833 with ESP32 
(which in turns is controlled via Jupyter + MicroPython Remote Kernel)


 Modulations 



  • IQ (using two AD9833 modules)





  • DTMF  (using two AD9833 modules):


其他模組:
  • AD9834


  • AD9850 (忘了錄影)
  • ADF4351



Dependencies:
 

1 則留言: