2026年11月7日 星期六

Tektronix TDS3054B over Ethernet on the ATS Console: Live Scope Screen and Measurement Trends | 用 ATS 操作台控制 Tektronix TDS3054B 示波器:網路連線、畫面與量測曲線

Tektronix TDS3054B 是四通道、500 MHz 的數位示波器(TDS3000B 系列)。公司這台背後的通訊模組槽是空的,所以沒有 GPIB、也沒有 RS-232,只有內建的 Ethernet。這篇記錄怎麼把它接進 ATS 網頁操作台:網頁上照示波器螢幕畫出波形,也可以把頻率、Vpp 這些量測值畫成隨時間變化的曲線,最後是幾個讓示波器卡死的踩坑。

說明:本文截圖是在開發機上用模擬儀器拍的(回應格式照實機,CH1 是 1 kHz 方波、CH2 是正弦),數值只是示意;連線方式和踩坑都是實機經驗。

連線:Ethernet,但要走 VISA(VXI-11)

TDS3000B 的網路是 VXI-11 協定,不是常見的 raw socket(TCP 5025),所以 ATS 的「Ethernet」分頁連不上它。要走「GPIB」分頁(其實是 VISA),位址選「手動輸入」,填:

TCPIP0::192.168.10.2::INSTR
(不通再試 TCPIP0::192.168.10.2::gpib0,1::INSTR)

示波器的 IP 在面板 UTILITY → System: I/O → Ethernet Network Settings 設定,建議用固定 IP。公司這台直接用網路線接在測試桌機的第二張網卡上。手動輸入的位址連線成功一次後,ATS 會記進 visa_addresses.txt,之後就會出現在下拉選單裡。

網路儀器的位址 ATS 掃描時不會去問 *IDN?,因為這台示波器一次只接受一個 VXI-11 連線,掃描時開連線會跟正在用的程式搶。另外,瀏覽器打 http://示波器IP/ 是原廠的 e*Scope 網頁,可以看螢幕截圖、下指令,不用裝任何東西。

示波器畫面:網頁上照螢幕畫波形

連上後辨識成「示波器」類型,勾「曲線」會多一個下拉選單「示波器畫面/量測值曲線」,預設是示波器畫面。按「開始量測」,伺服器每一輪:

  1. 讀時基、觸發來源/準位/斜率、執行狀態::HORizontal:MAIn:SCAle?;:TRIGger:A:EDGe:SOUrce?;…
  2. :SELect? 看哪些通道開著,:HORizontal:RECOrdlength? 拿點數(10000)。
  3. 每個開著的通道讀 SCAle/POSition/OFFSet,設 DATa:SOUrce CHx;ENCdg ASCIi;…,讀換算係數 WFMPre:XINcr?;XZEro?;YMUlt?;YZEro?;YOFf?,最後 CURVe? 拿波形。
  4. 換算成「格」(電壓 =(原始值 − YOFf)× YMUlt + YZEro,格數 =(電壓 − OFFSet)/ SCAle + POSition),網頁照 10×8 格的螢幕畫出來。

波形資料一次一萬點,所以不寫進收發紀錄,也不進 CSV;「匯出 CSV」會存目前這一張。示波器本身的設定(時基、垂直刻度、觸發)還是在面板上調,ATS 只負責讀。

量測值曲線:長時間觀察頻率、Vpp

切到「量測值曲線」,可以從 44 個量測項目(CH1~4 × 平均、Vpp、最大、最小、RMS、頻率、週期、上升/下降時間、正脈寬、正工作週期)複選:

用的是 MEASUrement:IMMed(不顯示在螢幕上的量測),每項先送 HEADer OFF、切來源和類型,再讀 MEASUrement:IMMed:VALue?,不會動到螢幕上的四格量測。幾個要注意的地方:

  • Tek 預設回應帶標頭(:MEASUREMENT:IMMED:VALUE 1.2E0),不先送 HEADer OFF 曲線會讀不到數字。
  • 量不到(沒觸發、訊號不到一個週期、超出畫面)回 9.9E37,ATS 不畫這種點。
  • 時基 40 ms/div 以上是 Roll 模式,波形還沒成形前頻率、上升時間可能一直量不到。
  • 錯誤不會自己回傳,要用 EVMsg? 或 ALLEv? 讀事件,ATS 會附上中文說明(指令集收錄 124 個事件碼)。

踩坑:沒讀完的波形讓示波器卡死

有一次 ATS 在讀 CURVe? 的途中被強制結束,波形沒讀完、留在示波器的輸出緩衝。下次 ATS 連上問 *IDN?,先讀到的是那一大串舊波形,辨識就錯了。更糟的是嘗試「連上就讀到逾時,把殘留清掉」時,TDS3054B 的 VXI-11 直接卡死:開得了連線但什麼都不回,只能關機重開。

現在的做法是:網路儀器開連線時先 Device Clear,再送 *OPC?,一直讀到回「1」為止,前面讀到的都丟掉。絕對不要在沒送查詢的情況下去讀。正常按「停止量測」不會有這個問題,伺服器會把讀到一半的 CURVe? 讀完。

另外兩個小地方:示波器一次只收一個連線,ATS 連著時其他程式(例如另一個 ATS 視窗)會開不了,ATS 會提示「可能有別的程式正連著它」;被強制中斷後示波器大約要 30 秒才會釋放連線。如果是儀器先關機,ATS 的連線按 ✕ 也能直接移除,不會卡在清單裡。

Pi 5 Mecanum Robot Car: Web Control, Gyro Straight-Line Hold, Distance & Route Maps, Obstacle Avoidance | Pi 5 麥克納姆輪自走車:網頁遙控、陀螺儀走直線、距離圖與路線圖、自動避障實車調校

這台麥克納姆輪車之前是 Arduino UNO/Mega2560+ESP32-CAM 的取物機器人。這次把 Arduino 拿掉,改成 Raspberry Pi 5 直接用 GPIO 驅動兩片 L298N,加上 Logitech C310 攝影機、HC-SR04 超聲波(裝在 MG90S 伺服上可以轉頭)、MPU6050 陀螺儀,做成一台用手機網頁遙控、會自己避障的自走車。這篇記錄硬體接法、網頁介面,以及實車調校時一個一個踩到的坑。

硬體與接線

零件用途接到 Pi 5
L298N ×2四顆 TT 馬達(每片管一邊兩顆)EN 用 GPIO12/13/18/19(PWM 調速,板上 ENA/ENB 跳帽要拔),IN 用 8 支 GPIO
HC-SR04前方距離Trig GPIO17;Echo 是 5V,經 1kΩ/2kΩ 分壓才接 GPIO27
MG90S超聲波轉頭(±80°)GPIO22,電源吃 L298N 的 5V(不吃 Pi 的 5V)
MPU6050(GY-521)陀螺儀:車頭方向、撞擊偵測I2C:SDA 3 腳、SCL 5 腳、VCC 3.3V
Logitech C310影像+YOLO 物件偵測USB(640×480 YUYV,MJPG 會一直噴壞 JPEG)
18650 ×3 串聯馬達電源(12.6V 滿)→ 保護板 → 開關 → 兩片 L298N,GND 跟 Pi 共地
行動電源Pi 5 電源USB-C,跟馬達電源分開




三顆 18650 滿電 12.6V,扣掉 L298N 約 2V 壓降,馬達還是吃到 9~10V,而 TT 馬達額定 3~6V,所以程式把 PWM 上限壓在 60%。Pi 5 用行動電源供電,網頁上會顯示 Pi 的 5V 電壓;手邊這顆只有 4.75~4.89V,常跳「曾電壓不足/曾降頻」,之後要換 PD 的行動電源。

網頁操作

程式是 Python(aiohttp+lgpio+OpenCV+onnxruntime),開機自動跑成 systemd 服務,手機連 http://pi5-2:8080/:左邊搖桿前後+左右平移,右邊橢圓搖桿原地旋轉,影像上疊距離,YOLO(yolo26n,CPU 每張約 32 ms、限每秒 10 次)把看到的東西框出來。網頁每 0.1 秒送一次搖桿,超過 0.5 秒沒收到就停車(斷線、手機鎖螢幕)。


實車調校一:輪子方向與超聲波

  • 輪子方向:網頁有「單輪測試」,每顆按「正轉」都應該讓車往前推。實車 RL(左後)和 FR(右前)是反的,不用改線,在 config.yaml 把那兩顆的 invert 改成 true。
  • 超聲波第一次完全沒回音:Pi 送了 10 次 Trig,GPIO27 一次都沒變高——是接線問題(實體腳號和 GPIO 編號很容易搞混,第 13 腳是 GPIO27,GPIO13 是第 33 腳),重接後馬上量到 40 cm。
  • 轉頭後距離不會變:原本程式只在伺服朝正前方時才量,轉到 -10° 就凍結在最後一個值。改成任何角度都量,網頁標出方向(例如「63 cm 右 10°」);「太近不准往前」只看 ±15° 內的讀值。

實車調校二:陀螺儀讓車走直線

TT 馬達左右快慢不一樣,速度 50% 直走 3 秒,車頭就往左偏了 10°。加上 MPU6050 之後,搖桿沒有旋轉時程式會鎖住起步那一刻的車頭方向,偏了就讓兩邊輪子一快一慢拉回來(PD 控制),另外再學一個「這台車直走本來就要往右補多少」的固定量(積分,前/後/左/右分開學)。

版本3 秒直走的車頭偏移
沒修正10°
kp 0.037°
kp 0.1、ki 0.05、上限 0.5最多 2°,之後自己拉回,停下時 1.3°;實際走 115 cm,眼睛看是直的

兩個坑:

  • 兩個網頁互相蓋掉:我從遠端送「前進」做測試時,使用者手機的網頁還開著、每 0.1 秒送一次「搖桿放著=0」,車子其實是走走停停,第一次量到的「3 秒 80 cm」是錯的(真的是 115 cm)。改成每個網頁的搖桿分開記,有人在推就用最新推的那個,全部放開才停。
  • 積分飽和:自動模式卡在櫃子前推不動時,修正量一路累積到上限 -0.5,右輪只剩 14% 出力,車子一直往右繞。改成偏差小於 10° 才學、修正量上限 0.2、偏超過 20°(被撞歪、手轉、卡住)就改用現在的方向當目標。

距離圖與路線圖

影像下面多了兩張圖:

  • 距離圖(車身座標,車頭朝上):超聲波每 5° 一格、15 秒內的讀值畫成綠點連成輪廓;按「掃描一圈」伺服從右 80° 轉到左 80°,每 10° 量一次。黃色扇形是攝影機視角,YOLO 認得的東西畫成黃點並估距離。
  • 路線圖(俯視,出發時車頭朝上):沒有編碼器,位置是「送給四輪的速度 → 麥克納姆反運算 → 乘實測 77 cm/s(全速)」推算,方向用陀螺儀;超聲波打到的點換成世界座標畫成紅點,跑久了房間的輪廓就出來了。

攝影機估距離用「地面法」:鏡頭離地 8 cm,東西放在地上時,它的底邊在畫面越下面就越近,距離=鏡頭高度 ÷ tan(底邊在水平線下的角度);底邊碰到畫面下緣(看不到落地點)時,改用人、椅子這類已知高度的東西用框的高度估。一開始櫃子被估成 28 cm,因為鏡頭被夾子夾得往上仰——用一個放在 100 cm 的箱子校正:箱子底邊在畫面第 350 列、遠處地面的水平線在第 290 列左右,算出鏡頭往上仰約 6°,校正後估成 87 cm(從車頭算),跟超聲波的 86 cm 對得上。


自動避障:一路改了好幾版

最初的邏輯很簡單:前方 25 cm 內有東西就停、伺服左右各看 60°、往比較空的一邊轉。實車跑起來的問題和改法:

實車問題原因改法
斜面的路障偵測不到聲波被斜面彈走,收不到回音,原本當成「前方沒東西」前進時伺服在 0/左 20°/0/右 20° 輪流量,取擋在車寬內最近的;±25° 都沒回音超過 1 秒就停下來看;沒回音或接近時半速
撞到東西還一直頂沒有感測MPU6050 的加速度:水平加速度突然超過 0.9 g 當撞擊,退一點再找路
一直誤判撞到(前方還有 124 cm)起步、急停的加速度也超過門檻穩定前進 0.8 秒之後才算撞擊
跑不出房間只看左右兩個角度、固定轉一個角度;轉完還用轉之前的前方距離看 5 個角度(右 80、右 40、正前、左 40、左 80),往最空的方向轉、每次最多 30°;轉完清掉舊讀值
左右來回換、轉不出去每次重新選邊記住閃避方向:沒走出 50 cm 又被擋就繼續往同一邊;那邊累積轉 120° 還不行就記住、改另一邊;兩邊都不行就後退重來
頂著抽屜櫃推 45 秒超聲波裝得低,從櫃子下面看出去一直量到 90 cm卡住偵測:輪子推算走了 25 cm 以上,正前方距離卻變不到 1/4 → 當成卡住,後退換方向
太快自動模式不吃網頁的「速度上限」自動前進、轉彎、後退都乘上速度上限;轉彎改用陀螺儀轉到角度就停

最嚴重的坑:重開服務時暴衝

有一次車子突然全速衝進躺椅腳靠底下。查了才發現兩件事疊在一起:

  1. lgpio 的 tx_pwm(…, 0) 不會把腳位拉低:它只是停掉 PWM,腳位停在最後的電位。用 pinctrl get 一看,四支 L298N 的 EN 一直都是 high。
  2. 我用 SIGKILL 重開服務(程式收到 SIGTERM 不會自己結束,之前都用強制結束),當時車子正在自動模式轉動:方向腳停在「轉」、EN 又是 high,新程式起來前那 2~3 秒就是 100% 全速。

修法:停車時一定 gpio_write(EN, 0);systemd 服務加 ExecStartPre/ExecStopPost 用 pinctrl set … op dl 把 12 支馬達腳全部拉低、TimeoutStopSec=3;收到關閉訊號第一件事先停車。之後就算程式當掉或被砍,馬達也不會停在轉動狀態。接馬達的專案,「程式死掉時腳位會停在哪」一定要先想好。

還沒解決的

  • 超聲波看不到比它高或低的東西(躺椅腳靠、櫃子下緣、門檻),打算車頂加一顆 VL53L1X 雷射測距,跟 MPU6050 共用 I2C。
  • Pi 5 的行動電源電壓偏低(4.75~4.89V),要換 PD 5V 3A。
  • 路線圖的平移效率(假設直走的 80%)還沒實測;跑久了會飄。

2026年11月6日 星期五

HP 34401A on the ATS Console: GPIB Readings, Command Set and Live Charts | 用 ATS 操作台控制 HP 34401A 電表:GPIB 讀值、指令集與即時曲線

實驗室最常用的儀器大概就是電表。公司這台 HP 34401A 是六位半的桌上型數位電表,雖然是 1990 年代的機種,GPIB 和 SCPI 指令都很完整,到現在還是很好用。這篇介紹怎麼用自己寫的 ATS 網頁操作台控制它:自動找到儀器、查中文指令集、把讀值畫成即時曲線。

說明:本文截圖是在開發機上用模擬儀器拍的(回應格式照實機),畫面上的數值只是示意;指令和注意事項則來自公司實機測試。同系列還有 MT8870A 無線綜測儀那篇。

連線:GPIB 分頁自動找到儀器

左邊「新增連線」切到 GPIB,ATS 會透過 VISA(NI-VISA 或 Keysight IO Libraries)列出匯流排上的所有儀器,並逐台問 *IDN?,下拉選單直接顯示「位址+型號」,不用再去記哪台是幾號。34401A 出廠的 GPIB 位址是 22,公司這台改成了 24。

連上之後 ATS 會自動辨識成「電錶」類型,並載入 34401A 的指令集。別名會出現在連線清單和 log 檔名上,同時接好幾台儀器時比較好分。

指令集:98 條指令中文說明

送出列旁邊的「指令集」按鈕會打開這台儀器的指令清單。內容是從原廠 User’s Guide(34401-90004)第 4 章整理出來的,共 9 類 98 條,每條都有中文說明和手冊頁碼,可以搜尋、點一下就填進輸入框,<參數> 會自動反白方便直接改。錯誤碼(34 個)也有中文對照:送 SYST:ERR? 回來的錯誤會直接附上說明。

曲線:選量測功能,按開始

勾工具列的「曲線」,選量測功能(DC 電壓、DC 電流、AC 電壓、2 線/4 線電阻、頻率、週期等 9 種),設定間隔後按「開始量測」。ATS 伺服器會先送一次設定指令(例如 CONF:VOLT:DC),之後每一輪送 READ?,一筆回來才問下一筆,不會因為儀器慢而排隊。上面顯示最新值、最小、最大、平均、標準差,所有資料同時寫進 CSV log。

實用細節

  • NPLC 和逾時:*RST 之後是 NPLC 10(5½ 位)。改成 NPLC 100 時一筆要 2 秒以上,READ? 會超過 VISA 預設的 2 秒逾時,量測前先把連線的「逾時 ms」調大。想要快就選「DC 電壓(快速 4½ 位)」,會送 CONF:VOLT:DC 10,0.001 加 VOLT:DC:NPLC 0.2。
  • 超量程:回 ±9.90000000E+37,ATS 的曲線不畫這種點,統計也不算進去。
  • 同一條 GPIB 上的其他儀器:34401A 在跑曲線時,每次 READ? 會佔住匯流排一段積分時間。我們就碰過同一條 GPIB 上寫 PBZ 電源序列慢了十幾倍,後來 ATS 在寫入序列時會自動暫停同一塊 GPIB 卡上的量測。
  • RS-232:沒有 GPIB 卡也能用 UART 接,出廠是 9600 baud、偶同位、7 bits,要先送 SYST:REM 才能遠端控制(不然錯誤 550),用完送 SYST:LOC 還給面板。
  • 面板文字:DISP:TEXT "HELLO" 可以在電表螢幕上顯示字,最多 12 個字元,只能英數。

指令集是一個 YAML 檔(instruments/34401A/commands.yaml),量測功能、錯誤碼、說明都在裡面,之後要加常用指令或改說明,直接編輯這個檔就好,不用改程式。

A Stepper Motor Turntable over RS-232 on the ATS Console: Live Angle Dial and Angle Sweep Scripts | 用 ATS 操作台控制步進馬達轉台:UART 指定型號、即時角度錶盤與掃角腳本

量 UWB 的 AoA(到達角)要把待測物放在轉台上,一格一格轉角度量。我們手邊的轉台是步進馬達加一台 3 軸微步進馬達驅動控制器(開機訊息 CNC3D-3X),走 RS-232。以前都是開超級終端機手打 :U36000,這次把它接進 ATS 網頁操作台:選好型號就有指令集、工具列即時顯示角度,掃角度變成一個腳本按一下就跑完。

說明:本文截圖是在開發機上用模擬轉台拍的(回應格式照實機),數值只是示意;接線、速度和踩坑紀錄都是實機(筆電 COM27)測出來的。

控制器指令速查

RS-232 9600 8-N-1,指令以冒號開頭、數字直接接在後面、結尾送 CR。數字一律是「步」。

指令意思實機回應
:X36000X 軸轉到絕對座標 36000 步(不回)
:U-400X 軸相對轉 -400 步(不回)
:RX/:RP讀 X/XYZ 座標X0/X0,Y0,Z0
:RL極限開關狀態(X+ X- Y+ Y- Z+ Z-)L001111
:SX0不轉,把目前座標設成 0(不回)
:SI500,2000,800速度:初速、高速(PPS)、加減速步數(不回)
:SM63/:SM0極限保護開/關(不回)
r即時:是否在動(不用 Enter,轉動中也能問). 移動中、> 就緒、L 極限
a即時:讀 XYZ 座標X0,Y0,Z0
b緊急停止

換算:馬達 1600 步/圈(1/8 微步),轉台齒輪比 1:90,所以 400 步 = 1 度,90 度是 36000 步、一整圈 144000 步(實機送 :X400 刻度剛好走 1 度確認過)。

跟說明書不一樣的地方

  • 不回顯:說明書畫面上的 :RXX0 其實是終端機自己回顯加上回應;控制器只回 X0,移動指令什麼都不回。
  • r 只回一個字、沒有換行:程式如果等「一行」會永遠等不到,要直接讀一個字元。
  • :RL 前面多一個 L,而且沒接的 Y、Z 軸讀 1,所以正常是 L001111。也因為這樣,停下來時 r 常回 L 而不是 >,等它停要兩個都接受。
  • 旋轉台只有一個負向極限開關,移動台才有正負兩個。

UART 連線+手動指定型號

GPIB 儀器連上會自動問 *IDN? 辨識型號,但這台控制器不會回答。所以 ATS 這次加了「UART 手動指定型號」:連線後在工具列類型選單選「裝置:轉台 CNC3D-3X」,就會載入這台的指令集和腳本,送出列的行尾也自動切成 CR。選擇記在瀏覽器,下次連同一個 COM 埠會自動套用。


指令集照說明書整理成分類清單(移動、相對移動、讀取、停止、設定、手動模式),可以搜尋,點一下就填進輸入框。實機測出來的兩組速度也收進去了:

即時角度錶盤

指令集的 yaml 裡多了一段 position 設定:每 0.5 秒送一次即時指令 a,用正規表示式 X(-?\d+) 抓出步數,乘 0.0025 換成度數,畫在工具列的小錶盤上(轉動中變藍色)。這些查詢不會進收發紀錄,剛送過指令的 1 秒內也會先跳過,避免搶到別的指令的回應。

position:
  label: 轉台
  query: a          # 即時指令,轉動中也能讀
  eol: none
  regex: 'X(-?\d+)'
  scale: 0.0025     # 1:90 → 400 步 = 1 度
  unit: °
  period: 0.5
  wrap: 360

腳本:轉 90 度、掃 -90~+90 度

控制器的移動指令不回應,所以腳本要自己等它轉完。ATS 腳本的 @until 原本只能比對「等於」,這次加了正規表示式:

:SM63                  # 極限保護開著
:SI500,2000,800        # 降速(原因見下面踩坑)
:U36000                # 正轉 90 度
@until r ~ [L>] 60     # 每秒問 r,回 L 或 > 就往下,最多等 60 秒
:RX

轉動中控制器忙著發脈衝,偶爾來不及回 r,所以 @until 碰到沒回應不會中斷,而是繼續問到時限為止。

量 AoA 用的是「-90~+90 度每 15 度停 3 秒」:先轉到 -90 度(:X-36000),之後每次走 6000 步、停 3 秒,13 個點,最後回 0 度。開始前先把轉台對準正前方,跑一次「目前位置設成 0 度」(:SX0)。另外還有讀位置、反轉 90 度、回到 0 度、緊急停止等腳本,都可以在 ATS 裡直接改。

刻度校正

控制器的座標每次開機都歸零,跟轉台盤面上的刻度沒有關係。實機對照::X-400 時刻度約 276.6°、:X400 約 278.5°,步數變大刻度也變大,800 步剛好 2 度。所以錶盤做成可以點:點一下輸入「現在刻度的讀數」,之後就顯示刻度角度(0~360 度循環),旁邊小字保留控制器步數。控制器關電重開或用 :SX 改座標後要重新校正;輸入空白就取消。

實機踩坑:高速轉大角度會失步卡死

第一版腳本用控制器預設速度(高速 4000 PPS)直接 :X-36000 轉 -90 度,結果馬達發出「卡卡」聲、不轉,r 5 秒都沒回應,腳本逾時停下。之後不管送什麼都不動::RL 從 L001111 變成 L111111,關掉極限保護 :SM0 也沒用。

一開始以為是極限開關擋住,其實是失步:轉台負載加上 1:90 減速,馬達跟不上 4000 PPS 的脈衝,控制器就進入異常。處理方法:

  1. 先送 b 緊急停止,然後關掉控制器電源重開,:RL 回到 L001111 才正常。
  2. 降速::SI500,2000,800(初速 1.25 度/秒、高速 5 度/秒),正反轉 90 度都正常,90 度約 18 秒。中速 :SI1000,3000,1000(90 度約 12.5 秒)也收進指令集,大角度還沒長時間驗證。
  3. 所有會轉動的腳本開頭都先送 :SM63(極限保護開著)和 :SI500,2000,800,不依賴控制器開機時的預設速度。

另外提醒:插拔 RS-232 的 9 pin 接頭前先關控制器電源;如果是 12 軸版控制器,把指令開頭的冒號換成 @0~@3 選控制器,讀位置/是否在動分別用 a/c/d/e 和 r/s/t/u。