13.3.1.6. API 參考¶
openmv 套件的公開介面是用於與相機通訊的 Camera 類別,以及用於處理通訊協定錯誤的 OMVException 階層。兩者皆記錄於本頁。
13.3.1.6.1. Camera 類別¶
- class openmv.Camera(port: str, *, baudrate: int = 921600, crc: bool = True, seq: bool = True, ack: bool = True, events: bool = True, timeout: float = 1.0, max_retry: int = 3, max_payload: int = 4096, drop_rate: float = 0.0)¶
透過 USB 序列埠連接 OpenMV 相機的主機端代理。
- 參數:
port -- 序列裝置路徑。在 Linux 上,USB CDC 為
/dev/ttyACMx,USB 轉 UART 橋接器為/dev/ttyUSBx。在 macOS 上為/dev/tty.usbmodem...或/dev/cu.usbmodem...。在 Windows 上為COMx。baudrate -- 序列鮑率。透過 USB 連線時,
921600是將相機從 MicroPython REPL 切換到 OpenMV 通訊協定的神奇值——在 USB 連結上使用任何其他值都會讓相機停留在 REPL 模式,因此必須使用預設值。透過 UART 連結時,此值為實際的線路鮑率,可在兩端自由設定。crc -- 對每個封包啟用 CRC 驗證。
seq -- 啟用每個封包的序號。
ack -- 要求封包確認。
events -- 啟用來自相機的事件通知。
timeout -- 每次操作的逾時秒數。
max_retry -- 封包失敗時引發例外前的重試次數。
max_payload -- 協商後的最大酬載大小(位元組)。相機可能會向下協商。
drop_rate -- 僅供測試使用的丟棄封包機率,範圍為
[0.0, 1.0]。正式環境請保持為0.0。
此類別支援情境管理器協定;
with Camera(port) as cam:會在進入時呼叫connect(),在離開時呼叫disconnect()。
13.3.1.6.2. 連線¶
13.3.1.6.3. 指令碼執行¶
13.3.1.6.4. 串流¶
- Camera.streaming(enable: bool, raw: bool = False, resolution: tuple[int, int] | None = None) None¶
開啟或關閉影格串流,並選擇傳輸線上的格式。
- 參數:
enable --
True啟用串流,False停用串流。raw -- 為
False(預設)時,相機會先對每個影格進行 JPEG 壓縮再放入串流通道,並由read_frame()在主機端解壓縮。為True時,相機會以未壓縮方式傳送擷取的像素緩衝區——這是不具硬體 JPEG 支援的相機的正確選擇,因為軟體壓縮是迴圈中最慢的步驟。resolution -- 相機在傳送前將每個原始影格縮放到的目標
(width, height),因為未壓縮影格遠大於 JPEG 壓縮的影格。當raw=True時為必填;否則會被忽略。
13.3.1.6.5. 自訂通道¶
- Camera.channel_write(name: str, data: bytes) bool¶
將
data寫入自訂通道。超過酬載大小的寫入會自動分割成多個封包。- 參數:
name -- 由相機端指令碼註冊的通道名稱。
data -- 要傳送的類位元組酬載。
- 回傳:
若通道存在且寫入已送出則為
True,否則為False。
13.3.1.6.6. 裝置自我檢視¶
- Camera.version() dict¶
回傳相機的通訊協定、bootloader 與韌體版本三元組。在
connect()之後快取。每個三元組為int的(major, minor, patch)元組:protocol_version——相機實作的 OpenMV 線路通訊協定版本。bootloader_version——常駐於快閃記憶體中的 bootloader 映像檔。firmware_version——目前執行中的 MicroPython 韌體。
- Camera.system_info() dict¶
回傳相機的硬體能力與記憶體資訊。在
connect()之後快取。回傳的字典鍵值分為四組。識別
cpu_id——32 位元 CPU 識別碼。device_id——由三個 32 位元字組成的元組,即燒錄於晶片中的唯一裝置序號。chip_id——由三個 32 位元字組成的元組,每個連接到相機的影像感測器各一筆。usb_vid——USB 廠商 ID。usb_pid——USB 產品 ID。
記憶體大小(皆以 KB 為單位)
flash_size_kb——內部快閃記憶體總量。ram_size_kb——RAM 總量。framebuffer_size_kb——保留供影像擷取使用的 RAM。stream_buffer_size_kb——保留供將影格傳送至主機的串流通道使用的 RAM。
能力旗標(每項功能一個布林值,皆命名為
<feature>_present)gpu_present——圖形處理單元。npu_present——神經處理單元。isp_present——影像訊號處理器。venc_present——視訊編碼器。jpeg_present——JPEG 硬體編碼器。dram_present——外部 DRAM。crc_present——CRC 加速器。pmu_present——效能監控單元。wifi_present——Wi-Fi 無線電。bt_present——藍牙無線電。sd_present——SD 卡插槽。eth_present——乙太網路 PHY。multicore_present——多個 CPU 核心。
其他
usb_highspeed——布林值,當 USB 以高速模式(USB 2.0 HS,480 Mbps)列舉時為True。pmu_eventcnt——可用的 PMU 事件計數器數量;無 PMU 時為0。
13.3.1.6.7. 診斷¶
13.3.1.6.8. 分析器¶
分析器會回報已插樁的韌體模組——目前為 image、ml 與 ulab——的每個函式呼叫次數,以及最小/最大/總執行時間。函式的進入與離開在編譯時被攔截;執行階段在每次進出時對單調遞增的微秒計數器取樣,依函式累加結果,並透過 profile 通道將此表格揭露給主機。
只有在傳遞 PROFILE_ENABLE=1 給 make 時,分析器才會內建於韌體中。標準韌體映像檔不包含它——建置時為被追蹤模組加入的 -finstrument-functions 旗標具有不可忽視的執行階段額外負擔,因此分析建置是針對需要它的特定除錯工作從原始碼產生的。當韌體未以該旗標建置時,profile 通道不會註冊,且本頁的每個分析器方法都會靜默回傳而不執行任何操作。
Arm 效能監控單元(PMU)是 Cortex-M55 的硬體計數器區塊——一組可設定的小型計數器,可在不拖慢受測程式碼的情況下追蹤週期數、快取命中與未命中、分支行為,以及其他架構定義的事件。在具備 PMU 的相機上——AE3 與 N6,這兩款是 OpenMV 產品線中環繞 M55 打造的相機——分析器會在取得計時資料的同時對這些計數器取樣,事件總計則出現在每個函式記錄中。不具 PMU 的相機仍會產生計時記錄;事件欄位會回傳為零,且 profiler_event() 為無操作。
- Camera.profiler_mode(exclusive: bool = False) None¶
在包含式與排除式計時之間切換。包含式計時將被呼叫者的時間計入呼叫者;排除式計時則不會。
- 參數:
exclusive --
True選擇排除式計時,False選擇包含式計時。
- Camera.profiler_reset(config: list | None = None) None¶
清除所有分析計數器。
config=None也會還原預設的 PMU 事件指派。- 參數:
config -- 保留供未來的個別計數器設定覆寫使用。傳入
None以保留預設值。
13.3.1.6.9. 子類別化與通道內部機制¶
上述記錄的方法涵蓋了套件的所有常見用法。少數模式——處理主機想要回應的相機端事件、為多步驟交換鎖定通道、與承載結構化資料而非位元組串流的通道通訊,或驅動通道專屬的控制指令——需要 Camera 以底線前綴保留的方法。這些名稱依慣例為私有(Python 並不會對它們進行名稱重整),需要使用它們的應用程式預期應子類別化 Camera 或直接呼叫這些方法。
子類別化以回應事件。 相機發出的每個事件都會透過 Camera._handle_event() 抵達。子類別化 Camera 並覆寫該方法是應用程式回應其相機端指令碼所引發事件的方式;事件 頁面完整說明了此模式。
- Camera._handle_event(channel_id: int, event: int) None¶
派發來自相機的一個事件。每當事件封包抵達時由傳輸層呼叫。在子類別中覆寫以加入應用程式專屬的處理;呼叫
super()._handle_event(...)以保留預設行為(在CHANNEL_REGISTERED時重新整理通道清單、在stream通道上追蹤影格就緒狀態、stdin通道的啟動/停止記錄)。- 參數:
channel_id -- 系統事件為
0,否則為已註冊的通道 ID。event -- 事件識別碼;系統事件的值來自
EventType列舉,通道事件的值則來自相機端通道後端所選擇的值。
若子類別加入自己的通訊協定方法,應以 retry_if_failed() 加以裝飾,使它們繼承本頁每個出貨方法所具備的相同重新同步與重試行為。
- static Camera.retry_if_failed(func)¶
裝飾器。包裝實例方法,使其在傳輸層引發
ResyncException時重試一次。任何呼叫_send_cmd_wait_resp()(直接呼叫或透過某個_channel_*包裝器)的方法都應帶有此裝飾器:class MyCamera(Camera): @Camera.retry_if_failed def my_custom_command(self, payload): return self._send_cmd_wait_resp(Opcode.MY_CMD, 0, payload)
通道鎖定可確保通道狀態不會在兩個相關操作之間改變(例如在持續附加資料的通道上,_channel_size() 之後接著 _channel_read())。read_frame() 與 read_profile() 在內部使用此機制;以多步驟存取驅動自訂通道的應用程式也應如此。
- Camera._channel_lock(channel_id: int) bool¶
取得通道的互斥鎖。對同一通道的其他主機操作會封鎖,直到鎖被釋放。
- 參數:
channel_id -- 數字通道 ID,通常以
get_channel()解析。- 回傳:
鎖被授予時為
True。
- Camera._channel_unlock(channel_id: int) bool¶
釋放先前以
_channel_lock()取得的鎖。務必與鎖定呼叫成對使用;使用try/finally確保即使中間的讀取引發例外,解鎖仍會發生。- 參數:
channel_id -- 數字通道 ID,通常以
get_channel()解析。
形狀化通道承載結構化記錄而非平坦的位元組串流。分析器通道是出貨的範例:其形狀為 (record_count, record_size),想知道有多少筆記錄等待的主機會讀取形狀而非位元組大小。
- Camera._channel_shape(channel_id: int) tuple[int, ...]¶
讀取通道的形狀描述子。
- 參數:
channel_id -- 數字通道 ID,通常以
get_channel()解析。- 回傳:
描述通道配置的無號 32 位元整數元組。其意義為通道專屬。
通道專屬的控制指令——啟動、停止、重置、設定——皆搭載於單一作業碼(CHANNEL_IOCTL)之上,並帶有通道專屬的指令編號與選用的 struct.pack 酬載。像 stop()、exec() 與 streaming() 這類出貨方法都是針對 stdin 與 stream 通道的 _channel_ioctl() 呼叫的輕薄包裝;定義自己 ioctl 選單的自訂相機端通道也以相同方式驅動。
- Camera._channel_ioctl(channel_id: int, cmd: int, fmt: str | None = None, *args) bytes | None¶
對通道發出 ioctl 指令。
- 參數:
channel_id -- 數字通道 ID,通常以
get_channel()解析。cmd -- 由相機端通道後端定義的指令編號。
args -- 符合
fmt的值。
- 回傳:
通道回傳的任何酬載,或
None。
公開通道方法的依 ID 位元組串流變體會略過名稱到 ID 的查詢,並接受明確的位元組 offset——對於從大型緩衝區中間讀取一段資料(例如 profile 通道記錄)相當有用。
- Camera._channel_size(channel_id: int) int¶
- 參數:
channel_id -- 數字通道 ID,通常以
get_channel()解析。- 回傳:
通道上目前可用的位元組數。
- Camera._channel_read(channel_id: int, offset: int, length: int) bytes¶
從
offset開始讀取length個位元組。多封包讀取會自動重組。- 參數:
channel_id -- 數字通道 ID,通常以
get_channel()解析。offset -- 開始讀取的位元組偏移量。
length -- 要讀取的位元組數。
- Camera._channel_write(channel_id: int, data: bytes, offset: int = 0) None¶
在給定的
offset寫入data。多封包寫入會自動分割成多個封包。- 參數:
channel_id -- 數字通道 ID,通常以
get_channel()解析。data -- 要寫入的類位元組酬載。
offset -- 開始寫入的位元組偏移量。
通訊協定原語是此類別所揭露的最低層級——上述所有功能最終都建構於其上的原始送出指令、擷取原始通道清單,以及手動重新同步項目。當應用程式要送出類別尚未包裝的作業碼,或在子類別中實作自訂復原時,便會用到它們。
- Camera._send_cmd_wait_resp(opcode: int, channel: int = 0, data: bytes = b'') bytes | None¶
送出通訊協定指令並等待相機的回應。本節中所有其他方法皆建構於此原語之上。
- 參數:
opcode -- 指令編號。出貨的
Opcode列舉列出了韌體隨附的代碼,但此參數只是一個整數——自訂韌體建置可定義並回應自己的代碼。channel -- 通道 ID,系統指令則為
0。data -- 指令專屬的酬載。
- 回傳:
回應酬載,對於像
Opcode.SYS_RESET與Opcode.SYS_BOOT這類會中斷連線的指令則為None。
- Camera._channel_list() dict¶
從相機擷取目前的通道清單,但不觸及
update_channels()所填入的快取channels_by_id與channels_by_name字典。對於想要直接檢視相機通道狀態的子類別相當有用。- 回傳:
將通道 ID 對應到
{'name': str, 'flags': int}的字典。
- Camera._resync() None¶
從頭重新執行通訊協定交握。由
connect()在初次連線時自動呼叫,並由每個從傳輸層捕捉到OMVException的公開方法呼叫。在子類別中實作自身復原迴圈的應用程式可在處理底層錯誤後直接呼叫此方法。
13.3.1.6.10. 例外¶
- exception openmv.OMVException¶
所有通訊協定層級錯誤的基底類別。下列三個子類別皆繼承自它,因此單一個
except OMVException即可涵蓋整個錯誤範圍。
- exception openmv.TimeoutException¶
相機未在設定的逾時內回應。
OMVException的子類別。
- exception openmv.ChecksumException¶
封包的 CRC 不相符。在通訊協定耗盡其重試額度後引發。
OMVException的子類別。
- exception openmv.SequenceException¶
重試後抵達的封包帶有非預期的序號。
OMVException的子類別。