錯誤處理與復原#
工業相機系統運作的環境中,故障不僅可能發生,而且是預料中的事。與一般的桌面應用程式不同,這些系統通常會持續執行數小時甚至數天,並與外部硬體互動。因此,錯誤 handling 並非可有可無,而是系統設計的核心環節。
常見的錯誤來源包括:
- 網路中斷,尤其是使用 GigE 相機時
- USB 斷線
- 遺失或不穩定的觸發訊號
- CPU 超載或影像處理速度過慢
- 頻寬限制
- 無效或相依於狀態的相機組態
以下視覺化內容說明了為什麼錯誤 handling 非常重要:
沒有妥善的 handling:
有妥善的 handling:
其目標並非預防所有可能發生的故障,而是讓故障能夠被看見、受到控制並可復原。
pypylon 中的錯誤類型#
不同的錯誤類型需要不同的 handling 策略。
擷取錯誤#
擷取錯誤是指傳回了擷取結果,但影像本身無效。
with camera.RetrieveResult(2000) as grab_result:
if grab_result.GrabSucceeded():
image = grab_result.Array
else:
print(grab_result.ErrorCode)
print(grab_result.ErrorDescription)
常見原因:
- GigE 連線期間封包遺失
- 頻寬不足
- 暫時性傳輸層問題
- 相機或驅動程式不穩定
此類錯誤通常僅影響單一畫格。應用程式通常可以記錄問題、略過該畫格並繼續擷取。
逾時錯誤#
發生逾時,而 RetrieveResult() 正在等待影像,但在設定的逾時時間內沒有收到影像。
with camera.RetrieveResult(
1000,
pylon.TimeoutHandling_ThrowException
) as grab_result:
image = grab_result.Array
常見原因:
- 已啟用 Trigger Mode 但未收到觸發訊號
- 相機未擷取影像
- Exposure Time 比預期長
- 逾時值設定過短
- 相機組態不一致
逾時在觸發系統中特別常見。逾時並不一定表示相機故障,通常表示應用程式正在等待一個永遠不會發生的事件。
執行階段例外狀況#
執行階段例外狀況表示除了單一畫格擷取之外的問題。
範例包括:
- 相機已拔除
- 網路連線中斷
- 裝置重設
- 無效的相機狀態
- 無效的 Property 存取
這些錯誤通常需要復原邏輯,例如停止擷取、等待、重新列舉相機或重新開啟裝置。
錯誤處理策略#
強固的系統通常會結合多種策略。
每張畫格處理#
當相機仍在運作但個別畫格可能失敗時,請使用此功能。
with camera.RetrieveResult(2000) as grab_result:
if grab_result.GrabSucceeded():
process(grab_result.Array)
else:
log_error(grab_result.ErrorDescription)
當偶爾遺失畫格是可以接受的時候,這種方法非常有用。它能保持擷取迴圈運作,並避免因為一張不良影像而停止整個系統。
使用
- 即時顯示
- 監控系統
- 非關鍵影像串流
例外狀況處理#
使用 try/except 針對可能在執行階段失敗的操作進行處理。
try:
with camera.RetrieveResult(
2000,
pylon.TimeoutHandling_ThrowException
) as grab_result:
if grab_result.GrabSucceeded():
process(grab_result.Array)
except Exception as e:
print("Error:", e)
這可防止應用程式立即崩潰。然而,僅僅捕捉例外情況是不夠的。應用程式還必須決定是要繼續、重試、重設擷取還是安全關閉。
復原迴圈模式#
復原迴圈將錯誤偵測與自動復原相結合。以下程式碼範例顯示了建構復原迴圈的建議模式。
import time
with pylon.InstantCamera(pylon.FirstFound) as camera:
while True:
try:
if not camera.IsGrabbing():
camera.StartGrabbing()
with camera.RetrieveResult(
2000,
pylon.TimeoutHandling_ThrowException
) as grab_result:
if grab_result.GrabSucceeded():
image = grab_result.Array
process(image)
else:
log_error(grab_result.ErrorDescription)
except Exception as e:
log_error(f"Acquisition error: {e}")
if camera.IsGrabbing():
camera.StopGrabbing()
time.sleep(0.5)
使用復原迴圈時的事件順序如下:
- 擷取正常執行。
- 發生錯誤。
- 引發例外情況。
- 例外處理常式會記錄該問題。
StopGrabbing()重設擷取管線。- 應用程式稍作等待。
- 迴圈重試擷取。
此模式允許系統在無需人工干預的情況下從暫時性故障中復原。
發生擷取錯誤後,內部緩衝區或取樣狀態可能不再代表乾淨的擷取管線。
這就是為什麼呼叫 StopGrabbing() 是復原迴圈的重要部分。它有助於實現以下目的:
- 停止目前的擷取操作
- 釋放或回收內部緩衝區
- 為相機準備乾淨的重新啟動
這無法解決所有可能的硬體故障,但通常是第一個安全的復原步驟。
相機斷線處理#
實體斷線是最常見的實際故障情況之一。
強固的應用程式應假設硬體隨時可能消失。
此處顯示了典型的復原順序:
Detect error
↓
Stop acquisition
↓
Wait briefly
↓
Re-enumerate cameras if needed
↓
Reconnect or report fatal failure
對於生產系統,重新連線邏輯通常實作在高於基本取樣迴圈的層級。
資源安全性#
使用 with 對於取樣結果而言至關重要。
這確保了即使區塊內部發生例外情況,取樣結果也會被釋放。
若沒有適當的清理,擷取可能會停滯:
這就是為什麼本指南中的所有範例都針對擷取結果使用了 context manager。
使用記錄而非列印#
例如, print() 簡單且易於讀取。在生產環境中,使用 Python logging 模組會是更好的選擇。
Logging 可為長時間執行的系統提供 Timestamp、嚴重性等級、持續性檔案以及更好的診斷功能。
可復原錯誤與嚴重錯誤#
並非所有錯誤都應以相同方式處理。
| 錯誤 | 典型處理方式 |
|---|---|
| 單張畫面擷取失敗 | 記錄並繼續 |
| Trigger Mode逾時 | 檢查觸發設定或重試 |
| 暫時性頻寬問題 | 記錄、降低負載、繼續 |
| 相機已中斷連線 | 停止、重新列舉、重新連接 |
| 啟動時遺失所需的相機 | 快速失敗 |
| 無效的組態 | 停止並回報錯誤 |
生產應用程式應明確區分可重試的錯誤以及需要操作人員介入的錯誤。
重點整理#
- 在工業環境中,錯誤是正常的。
- 同時處理畫面層級的錯誤與系統層級的例外狀況。
- 考慮使用逾時並指定適當的長度。
- 使用
with以確保資源釋放。 - 為無人看管的系統實作復原迴圈。
- 在生產環境中使用記錄功能和明確的錯誤分類。
完善的錯誤處理策略可確保相機應用程式穩定且自主地運行。