在設計基於GPS規範的振盪器(GPSDO)時,由於缺少10MHz參考輸入,我打算以Nano建構這樣的設計,最後還意外地創造了一個非常好的頻率計數器…
我最近正為一項新設計進行實驗,其間使用了函數產生器。儘管新的函數產生器具有相當好的頻率容差規格,但我還需要取得更高精度與準確性。採用頻率產生器、任意波形產生器和頻率計數器等取得更高精度的方法,在於使用這些測試儀器上所提供的10MHz參考輸入。由於缺少這樣的參考輸入,加上我最近一直在玩Arduino Nano,因此,我想以此Nano建構這樣的設計應該會很有趣。
圖1顯示了這種簡單且低成本「無需校準」的設計之主要元件。該頻率由10MHz壓控晶體振盪器(VCXO)產生。該振盪器會產生大約10MHz的頻率,並具有合理的容差,但也會有一個用於向上或向下調整頻率的調整接腳。取得更精確10MHz訊號的訣竅在於為VCXO設置正確的調整腳位,並在VCXO受到各種因素產生漂移時對其重新調整。讓我們來看看其實現方法。
圖1:無需校準的簡單頻率產生器之主要元件。
GPS模組可提供非常準確的每秒1個脈衝(1PPS)訊號。該脈衝看起來大約是每秒約100ms個脈衝。即使採用便宜的模組,該訊號在大約幾十奈秒範圍內通常比較準確。這是產生精確10MHz訊號設計的外部參考。1PPS訊號透過可產生中斷的I/O線連接到Nano。該設計中還有一個32位元計數器,能經由Nano對其進行讀取和重設。將32位元計數器連接到VCXO的輸出,就可以用它來計算自上次重設後的VCXO週期數。最後一個主要部份是如何調整VCXO。
在Nano上並沒有DAC,而是提供一項簡單功能來控制脈衝度調變(PWM)輸出,進而獲得可調節的直流(DC)輸出電壓(濾波後)。一組簡單的呼叫即能以固定頻率輸出5V PWM訊號。該PWM具有8位元調節範圍,因此如果想要2.5V輸出,可以將PWM設置為128 (50%的工作週期)。(請注意,對於這組呼叫,Nano使用大約500Hz的頻率,但這僅對濾波器設計比較重要。)所以,首先想到的是使用Nano的PWM輸出對其進行濾波,獲得相對無紋波的DC級,然後將其施加到VCXO的調整接腳。這樣便可以奏效了,但問題是只能設置多達255個離散級,這樣可能會不夠。讓我們更深入地瞭解一下。
我為該專案選擇採用的是泰藝電子(Taitien Electronics)的TSEAACSANF-10.000000 VCXO。它具有2ppm的初始頻率容差,以及在調整接腳上使用0.5V至2.5V電壓獲得約±12ppm的最大調整範圍,該範圍也稱為「上拉範圍」(pull range)。因此,如果使用完整的255步PWM,就能以大約(2×12/255≈0.1ppm)的解析度調整VCXO。這似乎對ppm精度沒有太大的改進,所以我想出了使用兩個PWM的想法:一個用於粗調,一個用於微調。為了保持設計簡單,我選擇只使用電阻而不使用運算放大器。這部份電路請參見圖2 (在此並顯示2個濾波電容)。
圖2:對專用於可調DC輸出電壓的PWM輸出進行粗調和微調。
基本上,目前所看到的是一個平均電路,電路粗調部份的電阻為2kΩ,微調部份的電阻為270kΩ。最後一個2kΩ電阻用於將電壓分壓成調節接腳,提醒一下,這裡需要2.5V最大值。VCXO調整電壓可以很容易地使用疊加來求解,其值大約等於公式1。
VCXO調整電壓=9.76×10-3×PWMCOARSE+144×10-6×PWMFINE (公式1)
其中,PWMCOARSE和PWMFINE的取值範圍為0到255。該電路有時稱為被動平均電路,如彌爾曼定理(Millman’s theorem)所述。現在,使用兩個PWM讓VCXO調整接腳的輸出電壓單調並不切實際,因為電阻的精度需要非常高。這可以透過選擇電阻值,使PWM微調的調整範圍與後續的粗調範圍相重疊來解決。
舉例來說,如圖2中所示的電阻值支援PWM粗調訊號,每一步移動大約9.8mV,微調訊號則是每步移動約0.14mV,即在其整個範圍內移動大約36mV。由於微調範圍大於粗調步長,因此總是會有很多重疊。
圖3顯示了幾個粗調範圍,以及如何配置微調值與之重疊。我將在介紹對調整演算法的討論中解釋如何使用這種重疊。(請注意,圖2中的兩個100μF電容之所以選擇此值,是為了將PWM波形的紋波保持在0.14mV微調步長以下。為了説明濾波,可使用程式碼將PWM頻率提高到大約31kHz。)
圖3:圖示說明微調範圍和粗調步長重疊。
將所有這些加在一起,進行如下所示操作:上電後,Nano將PWM粗調和PWM微調設定為初始值(某個中間值),然後等待直到檢測到來自GPS模組的1PPS訊號。接著,在下一個1PPS訊號中斷時,Nano重設32位元計數器,使其開始計算來自VCXO的週期數。在收到後續1PPS中斷後,Nano擷取並讀取32位元計數器——其計數值應為10,000,000。如果計數值小於10,000,000,則向上調整PWM微調值。如果調整前的PWM微調值為255,則使PWM粗調值遞增,並將PWM微調值設置為127 (中間值)。如果計數值大於10,000,000,則向下調整PWM微調值。如果調整前PWM微調值為0,則使PWM粗調值遞減,將PWM微調值設置為127(中間值)。可以看到,將微調過程與多個粗調值相重疊,可以使該演算法安全地尋找合適的值,但這在搜尋速度方面有些低效。
這實際上是調整的第一階段。如果只測量1秒的計數值,則無法獲得超過0.1ppm的精度。因此,程式碼的第二階段支援32位元計數器等待10次中斷來累積10秒。現在計數值就可以上升到100,000,000,也可以調整到0.01ppm範圍(即10ppb)。前兩個階段用於更快地接近10MHz目標值。第三個連續操作階段可計數100秒,等待100次中斷,然後再讀取計數器。這樣就達到了1,000,000,000的預期計數,從而支持調整到1ppb。但是PWM實際上可以調整到多少呢?如前所述,PWM微調每步移動大約0.14mV,VCXO可在0.5V至2.5V範圍內實現約±12ppm調整。因此,每個微調步長將頻率移動了大約(2×12ppm×(0.14mV/2.0V))≈0.0017ppm(即1.7ppb)。所以,看起來我們有足夠的調整來獲得大約±1ppb。在程式碼中還可以看到更多,但這是尋找精確10MHz的本質。(此時應注意,Arduino Nano實際上具有16位元PWM,但最大頻率太低,以至於所需濾波器的建立時間很長——對於此應用來說太長了。)
至於性能,Nano可在LCD上輸出各種統計資料,我的平均頻率通常為10,000,000.00,平均誤差為0.01Hz,該平均值的標準差為0.1ppb。因此,它可以將頻率保持在接近幾個ppb以內。這比我的函數產生器透過外部參考實現的效果更好兩個數量級。
現在來看如圖4的原理圖。可以看到PWM平均電路將調節電壓饋送到VCXO (這是唯一由Nano的3.3V電源供電的元件)。VCXO之後的電路用於對VCXO輸出的削波正弦波進行方波整形。這個經過整形和緩衝的10MHz方波訊號,不僅會發送到計數器,還會發送到外部BNC連接器。其中兩個BNC連接器用於提供TTL訊號。另一個配置有2個反相器閘和一個33Ω電阻,用以產生大約50Ω的輸出。第四個BNC連接器負責提供1PPS緩衝訊號,供外部元件使用。
圖4:符合GPS規範的10MHz訊號源原理圖。
在Nano下方的是GPS模組。在網路上就能以大約10-12美元的價格購買到這些模組和天線。其PCB如圖5和圖6所示。
圖5:符合GPS規範的10MHz訊號源之PCB。
圖6:在封裝中連接的GPS規範振盪器PCB。
原理圖中間是32位元計數器(圖1)。這個74LV8154(約1美元)實際上有兩個16位元計數器,可以將其配置為32位元計數器。該計數器設計透過定址位元組,而以4個單獨位元組方式讀取32位元計數器。這需要4條位址線,而由於我在Nano上的I/O不夠了,因此改使用74LS139,將Nano中的2條線轉換為計數器所需的4條線。
圖7所示的LCD採用標準I2C的20字元×4行LCD。原理圖底部是一個簡單的線性電源,使用了12V AC/DC配接器,將其調節至8V為Nano供電,並調節至5V為電路的各個部份供電。我還使用了線性電源,以確保獲得安靜的Vcc平面。最後,還有2個LED:其一是綠色LED,用於顯示1PPS訊號。第二個雙色LED,當系統緊密鎖定到所需的10MHz時為綠色;如果尚未鎖定,則為紅色;如果系統處於保持狀態,則交替顯示紅色/綠色。保持狀態用於在1PPS訊號遺失期間保持當前設置的狀態。
為了檢測1PPS訊號損耗,我使用了看門狗計時器(WDT)。我將WDT超時設置為2秒,並在1PPS中斷常式時進行重設,以取代使用WDT檢測錯誤程式碼的執行問題。如果系統沒有收到1PPS中斷,則WDT不會被重設。
圖7:已完成的GPS規範振盪器封裝,配置LCD。
Nano的程式碼是使用Arduino IDE以C語言編寫的。該程式碼基本上由1PPS中斷所驅動,並透過鎖定32位元計數器值(74LV8154的功能)、清除計數器和設置重設標誌來進行快速響應。你可能已經發現下一次計數的某些部份遺失了,因為我們正在擷取計數器暫存器,然後將其清除,使其再次從0開始計數。(擷取和清除之間有一定限制時間。)確實如此,因此韌體會透過將偏移值添加到原始計數器值來補償此延遲。事實證明有16個缺失計數。這已經由兩種方式得到驗證了。首先,在示波器上測量擷取暫存器訊號和清除暫存器訊號之間的時間。其次,在不調整VCXO的情況下使用1秒和100秒的擷取執行了許多測試。1秒擷取會重複100次並加總起來;如果延遲偏移正確,則1秒的總和值(現在包含100個延遲偏移)應該等於100秒擷取的讀數(其中包含1個延遲偏移)。在操作程式碼時,每次讀取計數器時都會重新添加遺失的16個計數。
程式碼中的主迴圈(Arduino開發系統始終將經典C語言的“Main”函數作為迴圈執行)等待設置中斷標誌,並在設置好時讀取74LV8154的鎖定暫存器的值。接下來,它會檢查這是否是「合理的」讀數而且毫無損壞(與10MHz的差異超過12ppm)。如果不好就扔掉。如果很好,它就會在一個小型boxcar平均器中處理該值,然後使用該平均值如前所述地對PWM進行向上或向下調整。接著,它會決定處於哪個階段。第一階段執行1秒計數並調整VCXO。這很快讓我們瞭解到PWM設置。此階段執行約20秒。第二階段需要10秒的計數讀數來微調PWM設置—執行5次或50秒。最後階段則執行100秒讀數且連續執行,隨著溫度或其他參數改變頻率,不斷地調整以保持頻率。
在最後階段,根據需要設置LED並在每次讀數後進行統計。這些統計資料可以在LCD上查看,也能使用電路中的防抖按鈕在主迴圈中查看多個頁面(圖8)。統計資料包括暫態頻率、平均頻率、當前ppb誤差、ppb平均誤差、ppb誤差標準差、良好讀數次數、不良讀數次數、連續鎖定時間、所看到的最大頻率、所看到的最小頻率,以及PWM粗調和微調設定。
圖8:LCD上每次讀數後進行的統計。
最後,有些人可能已經注意到,在設計基於GPS規範的振盪器(GPSDO)時,我們意外地創造了一個非常好的頻率計數器本質,後續將進一步探索。
本文作者:
Damian Bonicatto,諮詢工程師,在嵌入式硬體、韌體和系統設計方面累積數十年的經驗,並擁有30項專利
Phoenix Bonicatto,EDN特約撰稿
(參考原文:Simple GPS Disciplined 10MHz Reference uses Dual PWMs,by Damian Bonicatto & Phoenix Bonicatto Duncan Jones)
加入LINE@,最新消息一手掌握!