Learning Objectives
- 說出 VISA 在程式與儀器之間的角色,以及 PyVISA 和 VISA 函式庫的關係
- 用 ResourceManager 列出與開啟儀器,設定終止字元與逾時
- 分辨 write、read、query 的差別,用 query_ascii_values 一次讀多筆數值
- 處理逾時與找不到儀器的錯誤,知道查詢沒讀走會產生 -410
把介面的差異交給 VISA
第 04 課用 pyserial 和電錶對話時,要自己處理鮑率、位元組、終止字元與逾時;換成 USB、網路或 GPIB,又是另一套函式庫。 VISA(Virtual Instrument Software Architecture)是儀器業界的標準軟體層,最早由 VXIplug&play 聯盟提出,現在由 IVI Foundation 維護。 它把不同介面包成同一組操作:開啟、寫入、讀取、關閉,再用資源字串指定是哪一台、接在哪裡。
你的 Python 程式
↓ rm.open_resource("GPIB0::22::INSTR")、query("*IDN?")
PyVISA(Python 套件)
↓
VISA 函式庫(各儀器廠牌提供的實作,或純 Python 的 pyvisa-py)
↓
USB/網路/GPIB/序列埠的驅動程式
↓
儀器
PyVISA 是 Python 這一端的套件(pip install pyvisa),本身不直接碰硬體,而是呼叫電腦上安裝的 VISA 函式庫。
pyvisa.ResourceManager() 會使用已安裝的 VISA 函式庫;沒有安裝時,可以另外裝純 Python 的後端 pyvisa-py,用 pyvisa.ResourceManager("@py") 指定它。
不管後端是哪一個,程式的寫法都一樣,這正是 VISA 的價值。
本課的程式在瀏覽器裡對著模擬儀器執行,模擬的是 PyVISA 的常用功能;真實環境的安裝與設定以 PyVISA 與 VISA 廠商的文件為準。
PyVISA 的核心操作
| 操作 | 做什麼 |
|---|---|
rm = pyvisa.ResourceManager() |
建立總管,載入 VISA 函式庫 |
rm.list_resources() |
列出找得到的儀器(資源字串的元組) |
inst = rm.open_resource(資源字串, read_termination="\n", timeout=5000) |
開啟一台儀器;可以設定讀取的終止字元與逾時(毫秒) |
inst.write("VOLT 5") |
只送出,不讀回應 |
inst.read() |
讀一則回應(字串) |
inst.query("MEAS:VOLT?") |
送出再讀回應,等於 write+read |
inst.query_ascii_values("READ?") |
送出查詢,把逗號分開的回應轉成數字串列 |
inst.close(),或 with rm.open_resource(...) as inst: |
關閉連線 |
兩個常見的設定:
- 終止字元:
write_termination是送出時自動加在結尾的字元;read_termination是讀取時「讀到這個字元就結束,並把它去掉」。 沒有設定read_termination時,回應結尾的換行會留在字串裡,所以前幾課常看到.strip()。 - 逾時(
timeout,毫秒):讀取最多等多久。等不到回應時丟出VisaIOError,錯誤代號VI_ERROR_TMO。
逐步看:write、read、query 與終止字元
電錶開啟時設定了 read_termination="\n",電源供應器沒有設定。比較最後兩種回答:一個乾淨,一個結尾留著 \n。看通訊紀錄裡 write 與 read 各產生哪一筆。
逐步看:一次讀 5 筆,轉成數字串列
電錶設定成一次觸發量 5 筆,READ? 的回答是一行用逗號分開的文字。比較自己處理文字與用 query_ascii_values 的差別。
逾時、找不到儀器、查詢沒讀走
PyVISA 的錯誤都是 pyvisa.errors.VisaIOError,用 e.abbreviation 看是哪一種:
| 錯誤 | 常見原因 |
|---|---|
VI_ERROR_TMO(逾時) |
對設定指令硬要讀回應、指令拼錯(儀器記下錯誤但不回應)、量測時間比 timeout 長、終止字元設錯 |
VI_ERROR_RSRC_NFOUND(找不到資源) |
資源字串打錯、位址錯、線沒接、儀器沒開 |
逾時的時候,儀器那一邊通常也會記一筆:沒有查詢卻被要求回應,錯誤佇列記下 -420,"Query UNTERMINATED"。
另一種問題不會丟出例外:送出查詢之後沒有讀走回應,又送了下一個指令,儀器會丟掉舊的回應,在錯誤佇列記下 -410,"Query INTERRUPTED"。
所以查詢一律用 query(),或 write() 之後一定緊接著 read()。
另外,用 with 開啟儀器,離開區塊時會自動 close(),即使中間出錯也一樣。
逐步看:逾時、-420、-410 與 with
注意虛擬時間:第 8 行硬要讀回應,程式等滿 2 秒才逾時(通訊紀錄出現 ×),電錶記下 -420。接著連送兩個查詢,只有第二個的回應讀得到,電錶記下 -410。
小測驗:PyVISA 的操作
inst.query("VOLT?") 等於下面哪一組?
下面的程式模擬 query_ascii_values 的處理,會印出什麼?
reply = "+1.5E+00,+2.5E+00,+3.5E+00\n"
vals = [float(x) for x in reply.strip().split(",")]
print(len(vals), sum(vals))
開啟儀器時設定 timeout=5000,單位是什麼?
小測驗:錯誤與層次
程式對電錶送出 CONF:VOLT:DC 之後呼叫 read(),等了一陣子丟出 VI_ERROR_TMO。為什麼?
同一支 PyVISA 程式,從使用 USB 的電錶換成使用網路的電錶,最可能只需要改哪裡?
重點整理
- VISA 是程式與儀器之間的標準軟體層,把 USB、網路、GPIB、序列埠包成同一組操作;PyVISA 是 Python 端的套件,呼叫 VISA 函式庫(或 pyvisa-py 後端
"@py")。 ResourceManager()→list_resources()→open_resource(資源字串, read_termination=, timeout=)。write只送、read只讀、query=送+讀;query_ascii_values直接得到數字串列。用完close(),或用with。- 錯誤:
VisaIOError;VI_ERROR_TMO逾時、VI_ERROR_RSRC_NFOUND找不到儀器。查詢沒讀走又送指令 → 儀器記下 -410。
到這裡,你已經認識儀器、介面、SCPI 與 PyVISA。下一課(第 07 課)把它們接起來,寫出第一個完整的自動量測程式: 辨識儀器、設定電壓與限流、打開輸出、量測,並用 try/finally 確保量完一定關閉輸出。