2021年8月29日 星期日

Nixie Tube, Miniature Atomic Clock, Frequency measurement, Clock. - Part D (AC waveform measurement)

市電頻率一向是我很有興趣的一個觀測對象,理由是讀歷史資料的時候看到了兩種對於市電頻率衝突的描述。有一種說法是市電頻率非常的精確,很多工業用的計時基準跟同步裝置甚至是直接用了市電。另外一種則是指市電頻率可以觀測到當下供電端跟受電端平衡,當供給大於需求的時候頻率上升,反之下降。所以既然都入手了原子鐘要來做時間基準,當然是想辦法塞進監控AC頻率來看看到底頻率變化是長甚麼樣子。

測量AC頻率最基本的方式就是Zero-Crossing觸發,然後再透過外部的MCU/FPGA計算每次觸發之間的時間間隔來計算。Onsemi有一份App Note真的不錯,第一版的電路就是照這個做: https://www.onsemi.com/pub/Collateral/AND9282-D.PDF

之後把觸發訊號送到FPGA內的計數器這樣。不過第一版為了簡化供電跟安全考量,沒有直接市電而是透過一個AC變壓器轉成12VAC之後送進去,12VAC在內部轉DC之後降壓。所造成的問題也可想而知,因為原子鐘的耗電量不低,電流量大的狀況下AC整流那一塊的電容跟二極體發熱量不低。

這個是顯示AC的計數器,1/166421 * 10Mhz = 60.088Hz,殘影是因為頻率後面幾位數變化不低





第二版就把AC的訊號跟供電分開,簡化整流的部分,另外為了能夠在比較精確的方式監控Vrms,把第一版的LTC1966換成了直接用ADC測量波形後用軟體計算Vrms。ADC用的是ADS8681,因為SAR架構下可以直接吃正負電的訊號,我也不用另再用OPA處理進來的訊號,而且還有內部的PGA可以調放大倍率。ADC跟FPGA之間透過SPI通訊,採樣速度50Khz,觸發採樣的訊號也是原子鐘出來的,所以可以確保時間的精確度。資料透過RPI計算Vrms,頻率跟資料保存。

軟體很簡化的長這樣,其中比較重要的是Polling是先讀FPGA內FIFO的數量,然後把該數量的資料讀回來。 Polling thread特別讓他獨佔了一個Core,Linux的Schdeular只能用其他三個,然後寫入的部分開了一些Ram Disk的空間寫入,每分鐘定時再把資料搬到NVMe Drive上面。

Polling還有一個需要提到的是SPI在這種高密度的讀寫的時候,如果用的是spidev的介面,由於預設的狀況下系統很容易用到Interrupt Base的處理,這時候就會造成不可預期的時間delay。所以我在/boot/cmdline.txt加了這一行: spi_bcm2835.polling_limit_us=65535,這樣一來就可以確保系統在讀寫SPI的時候會是busy loop的方式等SPI結束。

ADC的校正則是用了一台Keysight 34410A,先校正ADC電壓測量,再來就是直接督插座之後兩邊比對AC Vrms資料


波形大概長這樣

另外多虧這次AC變成純訊號端,把供電接上UPS就可以抓到跳電/停電瞬間的波形:

其實真的很有趣,那時候跳電跳到停電之前就有感覺到燈光閃了一下,波形上就很明顯看到那一段,而且更有趣的是跳電瞬間之後電壓居然比之前高了一點,之後才整個停電。

拉近一點看第一次跳電的話,可以看到在100~200ms之內就幾乎沒電了。

不過直接用ADC採樣的話要抓精確的頻率就需要非常高的採樣頻率,這也是第二版最大的問題,ADC本身是可以跑到1M的,問題在於FPGA。即便是已經單獨給CPU/SPI用Polling,還是很容易掉幾筆資料。我用的FPGA是iCE5LP,算是滿小顆的FPGA,內部並沒有多少的ram block可以給我當FIFO用,而Linux下還是很常遇到數ms的中斷,導致FIFO overflow,加上為了標記每一筆資料的時間,每個Sample都是16bit的timestamp+16bit的ADC value,16bit的timestamp其實很尷尬,為了資料好處理,50Khz的話剛好每一秒timestamp可以歸0,這樣比較容易把資料跟真實時間擺在一起。

總結來說錯估了RPI的SPI通訊的能力跟FIFO的需求,所以沒有設計外部的DRAM只能靠內部太淺的FIFO。還好就是跟好這個FPGA的封裝可以換一個有內建比較大容量BRAM的高效能版本,可能之後rework FPGA替換掉之後再來看速度可以拉到多少。

至於頻率精確度,我大致上能理解為什麼會有兩種說法,問題在於看的是哪個時間平均,如果單純用來推時鐘,那長期下來<4ppm的時間誤差其實也比很多石英震盪器來的精確,但是短時間的誤差會飄很大,如果直接拿這來當PLL的時間基準是不行的。另外很有趣的是市電電壓跟需求量還滿有關的,需求越高,電壓越低(線阻?)

總結來說算是回答了我原本的疑問,接下來就是看有甚麼有趣的市電異常的現象發生了。