緣由
最近在學習 SDR,會需要用到 訊號產生器,市面上有的機型 具有非常強的功能,但是通常也不便宜。在網路上找一下,發現這塊 AD9833 模組,它雖然比較偏向音頻的用途,但價錢非常便宜而且取得方便,所以就買了幾塊來試試,並且用 Python 寫了對應的 driver,可以跨平台適用在 PC (Windows / Linux,需使用 USB-SPI converter)、Raspberry Pi、ESP32 上面。
後來索性把市面上較常見的幾種 signal generator 模組 (AD9833, AD9834, AD9850, ADF4351) 的 python drivers 都寫一寫,GitHub repository 在 這裡。
訊號產生器 的 種類與特點
我將 訊號產生器 大致區分為以下三個種類:
1. 獨立機台:
機種非常多 (例子),功能會因為應用領域而有些微不同。特色為:
優點:
- 可以獨立使用,不需要依賴與耗用 PC 的資源。
- 由很多硬體元件所組成,運行效率高。
- 功能齊全完備。
缺點:
- 功能雖多但還是受到限制,擴充不易 (可能需要額外的費用)。
- 有的機型 可以需依照廠商所定的 API / protocol 來與 PC介接溝通,但仍有學習門檻。
- 廠商所提供的 driver / API / utility 不一定能跨平台 (Windows / Linux)。
- 無法透過 MCU (例如 ESP32、Arduino) 來操作。
- 價位較高。
優點:
- 體積小,便於攜帶。
- 仍含有專用的硬體元件,維持執行效率。
- 可由 PC 上的軟體控制,應用上較為彈性。
缺點:
- 通常較小型,功能有限。
- 仍需透過 PC控制,某種程度地占用 PC 的資源。
- driver / utility 不見得能跨 OS (Windows / Linux)。
- 無法透過 ESP32、Arduino 使用。
- 不是非常便宜。
在 PC 上編寫/編譯程式之後上傳到控制 AD9833 的裝置 (Arduino / ESP32)上,在程式中插入一些例如 "print" 的指令將執行狀況顯示出來,以作為 tracing / debugging 的依據;修正錯誤之後 再次重複以上的步驟。
優點:
- 在真實的裝置中執行,其結果絕對真實。
缺點:
- 須根據要檢測的點,逐一插入相對的 "print" 指令,並且要重新編譯,費工費時。
- 無法設定中斷點,也就無法暫停程式的執行 以檢視流程與狀態。
- 無法動態地 修改變數值 或 改變程式流程,必須重新修改編譯才行,費工費時。
- 每次修改之後都需要重新編譯,並重新上傳到 MCU 上面,相當耗時。
- 跨平台的移植性較弱,為 Arduino 開發的程式 不見得可以在 ESP32、Raspberry Pi、PC 上面執行。
2. 使用 JTAG based in-line debugger:
優點:
- 不再需要手工加入 "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()
- 可以針對 兩組不同的 registers 設定值 做比較,並列出各個欄位的差異,這在 development 階段 debug 時候非常有用。
- 使用 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:
- Tested as in this notebook
- Also, we can use MicroPython Remote Kernel to control an ESP32 from a Jupyter notebook.
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
very detail.
回覆刪除very good.
thank you.