單元 16 · 多感測器與實作案例

客製 OV 接入

多相機

支援多 CSI 的板卡(如 RK3588)可接多顆;用 media-ctl 建多條管線,每顆一個 video device。

客製 OV 接入四步

  1. 確認驅動:OV5640 等有 mainline 驅動。
  2. 改 device tree:I2C 位址、reset/clock、MIPI 通道。
  3. 改驅動 init table:依公開 register 調整。
  4. 驗證出圖 → 再校正。
NDA 提醒:完整 register 表常需 NDA;本站只用公開資料。

完整案例:Orange Pi 調校 OV5640

改 DTprobe 成功取流曝光/白平衡後處理
  1. dmesg 確認 ov5640 probe、讀到 ID。
  2. v4l2-ctl 取一幀,確認格式。
  3. 手動曝光/增益確認曝光正確。
  4. 關 AWB 手動調 gains 確認中性。
  5. 後處理補 LSC/NR/Sharpen。
  6. 不同場景回歸。

最佳實踐

16.4 深入:客製 OV5640 接入的檢查清單

checklist
□ 硬體:CSI lane / I2C / reset / clock
□ DT overlay:compatible / reg / clocks / reset-gpios
□ 驅動:現成 or 改 init table
□ dmesg:probe 成功?讀到 ID?
□ 出圖:能取到幀?
□ RAW:Bayer order / 黑位 / 缺陷像素
□ 調校:黑位 → LSC → AWB/CCM → NR/Sharpen
紀律:一次只換一個變數,保留官方模組當對照組。

16.6 深入原理:多感測器與 virtual channel

多相機不是「多接一顆」那麼簡單——兩顆感測器可能共享同一組 MIPI lanes,靠 virtual channel(VC) 區分資料流。

接法資料路徑Orange Pi 情境
每顆各自 lanes各自的 CSI receiverRK3588 多組 receiver
共享 lanes + VC同一 D-PHY 帶 VC 標籤需要接收器支援多 VC
時序多工分時切換不適合即時雙流

在 media graph 中,每顆感測器是獨立的 subdev entity,各自連到(可共享的)CSI 接收器。啟動時要對「每一條管線」分別設定格式與 link,並確認 video 節點一一對應。

實務重點:多相機的雷多在「共享資源」——MIPI lane、ISP 頻寬、記憶體頻寬。先算清楚每路解析度/幀率(單元 11 的頻寬公式)再決定能不能同時跑。

16.7 完整 Worked Example:客製 OV5640 接入的完整流程

步驟 1|硬體確認
# 確認 CSI lane / I2C bus / reset GPIO / XCLK
sudo i2cdetect -l
cat /sys/kernel/debug/gpio | grep -i reset
步驟 2|改 DT overlay 並重啟
# 假設 overlay 新增節點:
# &i2c3 { ov5640: ov5640@3c { compatible="ovti,ov5640"; reg=<0x3c>;
#           clocks=<&clk_xclk>; clock-frequency=<24000000>; ... }; };
sudo dtoverlay overlay-name.dtbo
sudo reboot
步驟 3|probe 驗證
dmesg | grep -i -E "ov5640|csi|probe"
sudo i2cget -y 3 0x3c 0x300a   # 應回 0x56
步驟 4|建管線取流
media-ctl -d /dev/media0 -r
media-ctl -d /dev/media0 -l "'ov5640 3-003c':0->'csi2':0[1]"
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1280,height=720,pixelformat=UYVY \
  --stream-mmap=3 --stream-count=1 --stream-to=shot.yuv
步驟 5|RAW 品質檢查
# 蓋鏡頭拍黑幀定黑位;拍灰卡驗 Bayer order 與 LSC(回單元 2/8/12)
python3 - <<'EOF'
import numpy as np
raw = np.fromfile('dark.raw', dtype=np.uint16).reshape(720,1280)
print('OB =', np.median(raw[600:700,400:880]))
EOF
完成標準:五步全過:probe 成功 → 讀到 ID → 取到幀 → RAW 黑位合理 → 可進入調校(黑位→LSC→AWB→NR 各回對應單元)。

16.8 疑難排解決策樹:客製接入失敗

節點失敗方向
DToverlay 沒載入/編譯錯dmesg 看 dtoverlay 錯誤、檢查 compatible/reg/clocks
Probeprobe failure回單元 6:電源/clock/reset/位址
ID讀不到 0x5640回單元 3 I2C 決策樹
出圖無資料MIPI lane count/VC 設定、格式對齊
RAWBayer/黑位錯回單元 2/8 驗證
多相機第二路沒資料檢查 VC/共享資源頻寬(單元 11)
常見錯誤與陷阱:① DT 的 clock-frequency 與實際 XCLK 不符——PLL 全錯;② reset GPIO 極性反;③ 兩顆感測器用相同 I2C 位址沒改——衝突;④ 一次改多個變數——保留官方模組當對照組,一次只換一個。

16.9 練習

  1. 模擬/實作客製 OV5640 接入五步,產出每一步的證據。
  2. 寫一份「你的 bring-up SOP」(含指令與預期輸出)。
  3. 寫一份「你的調校工作流」(含參數與 log 範本),放進 repo。
  4. 若接第二顆感測器,記錄 VC 設定與頻寬計算。

16.10 總複習:寫下你的 SOP

  1. 寫一份「你的 bring-up SOP」。
  2. 寫一份「你的調校流程與參數」。
  3. 放進 repo 成為團隊資產。

16.12 進階真實情境 Worked Example:RK3588 多感測器即時切換——OV5640 ↔ OV9281

場景:Orange Pi 5 Plus(RK3588)同時接 OV5640(RGB)與 OV9281(IR),設計即時切換管線。

步驟 1|確認兩路 video device
v4l2-ctl --list-devices | grep -A3 "ov5640\|ov9281"
ls /dev/video0 /dev/video2   # 假設 0=OV5640, 2=OV9281
步驟 2|GStreamer 管線即時切換(用 tee + valve)
gst-launch-1.0 \
  v4l2src device=/dev/video0 name=rgb ! 'video/x-raw,width=1280,height=720' ! tee name=t \
  v4l2src device=/dev/video2 name=ir  ! 'video/x-raw,width=1280,height=720' ! t. \
  t. ! queue ! valve drop-bytes=1 ! autovideosink
步驟 3|用 v4l2-ctl 手動切換(逐路啟停)
# 啟 OV5640
v4l2-ctl -d /dev/video0 --stream-mmap=3 --stream-count=10
# 停 OV5640,啟 OV9281
v4l2-ctl -d /dev/video2 --stream-mmap=3 --stream-count=10
設計決策:RK3588 的兩路 CSI 接收器獨立——可以同時 streaming,也可以逐路啟停。但 GStreamer 的 tee + valve 管線有約 2-3 frame 延遲(queue 緩衝),若需要「零延遲切換」,直接用 v4l2-ctl 逐路操作更可靠。

16.13 深入原理擴充:OV9281 IR 感測器在 RK3588 的 MIPI 設定陷阱

OV9281 是單色 IR 感測器,但在 RK3588 上有一些與 OV5640 不同的 MIPI 設定:

項目OV5640OV9281
MIPI lanes2 lanes1 lane(通常)
Clock 頻率最高 160MHz最高 480MHz(但實際用較低)
格式SRGGB10 / YUYVY8 / Y10(無 Bayer)
Frame rate 上限30fps(1080p)120fps(720p)
DT 位址0x3c0x60

容易忽略的邊界案例:OV9281 的 MIPI clock 可以跑很高(480MHz),但 RK3588 的 CSI receiver 在 1 lane 模式下可能有 clock 上限——如果你的 DT 設了 480MHz 但硬體只支援 360MHz,會出現 frame sync 失敗(偶發黑幀)而非直接失敗。這需要量測 MIPI clock 來確認。

16.14 診斷式疑難排解表

症狀可能原因解決方案
OV9281 取流偶發黑幀MIPI clock 超 CSI receiver 1-lane 上限降低 DT 的 clock-frequency 到 360MHz 以下
OV5640 + OV9281 同時 streaming 有 frame dropDDR 頻寬不足降低兩路解析度;確認 DDR DT 設定
GStreamer tee 切換延遲 >3 framequeue 緩衝造成減少 queue 的 max-size-buffers
OV9281 出 Y8 格式但 RK3588 要求 SRGGBformat 設錯OV9281 是單色,應設 greyscale 格式(Y8)
多感測器 I2C 衝突(同 bus 不同位址)address strap 設定相同改其中一顆的 SCCB_ID 腳(0x60 vs 0x3c)

16.15 進階挑戰題

  1. 在 RK3588 上,同時 streaming OV5640(1080p@30fps)+ OV9281(720p@60fps),量測 DDR 頻寬使用率。找出什麼解析度組合會開始掉幀。
  2. 設計一個「感測器健康監控」腳本:每 N 秒自動讀兩路感測器的 ID register、frame count、error count,超標就印警告。
  3. 在 RK3588 上,實作「OV5640 出 RAW → ISP3 做 NR/AWB → RGA 旋轉 90° → MPP 編碼」的完整管線,找出每一級的延遲瓶頸。

16.16 專案級 Worked Example:多相機系統端到端 bring-up 專案

把單元 16(多感測器)與單元 1–6 串成完整多相機 bring-up 專案:在 RK3588 上同時 bring-up OV5640(RGB)與 OV9281(IR),建立兩條獨立管線並驗證同時取流。這是本課程的「畢業專案」。

階段 1|硬體與 DT 確認(單元 1/6)
sudo i2cdetect -l
# 確認兩顆感測器分掛不同 bus:bus3=OV5640(0x3c),bus4=OV9281(0x60)
sudo i2cget -y 3 0x3c 0x300a   # 0x56
sudo i2cget -y 4 0x60 0x300a   # 0x92
階段 2|確認兩路 video device(單元 4/5)
v4l2-ctl --list-devices
# 假設 /dev/video0=OV5640, /dev/video2=OV9281
media-ctl -p -d /dev/media0 | grep -E "ov5640|ov9281|csi"
階段 3|建立兩條管線(單元 16.6)
media-ctl -d /dev/media0 -r
media-ctl -d /dev/media0 -l "'ov5640 3-003c':0->'csi2_a':0[1]"
media-ctl -d /dev/media0 -V "'ov5640 3-003c':0[fmt:UYVY8_2X8/1280x720]"
media-ctl -d /dev/media1 -l "'ov9281 4-0060':0->'csi2_b':0[1]"
media-ctl -d /dev/media1 -V "'ov9281 4-0060':0[fmt:Y8_1X8/1280x720]"
階段 4|同時取流驗證(單元 11 頻寬)
v4l2-ctl -d /dev/video0 --stream-mmap=3 --stream-count=30 --stream-to=rgb.yuv &
v4l2-ctl -d /dev/video2 --stream-mmap=3 --stream-count=30 --stream-to=ir.yuv &
wait
ls -l rgb.yuv ir.yuv
# 兩檔大小符合各自格式理論值 = 兩路同時成功
專案完成標準:兩顆感測器同時取流成功,且你能回答「頻寬夠不夠、VC 用不用、兩路各自 media device 對應」三個問題。這就是多感測器系統的完整 bring-up 能力。

16.17 量測/驗證 SOP:多感測器系統驗收

步驟作法通過判據
1. 硬體盤點i2cdetect + 讀 ID每顆感測器位址與 ID 正確
2. 節點對應v4l2-ctl --list-devices每顆感測器有獨立 video node
3. 單路測試逐路單獨取流各路皆可獨立出圖
4. 同時測試兩路並行取流無 frame drop / 無資源衝突
5. 頻寬計算算總 bitrate vs DDR/CSI 上限未超過上限(單元 11)
6. 長期穩定同時跑 10 分鐘0 掉幀、0 逾時
SOP 紀律:多相機的雷多在「共享資源」——先單路確認、再同時測試,一旦同時出問題,用「逐路停用」二分法縮小範圍(是資源不足,還是某路驅動不穩)。

16.18 平台間對照:多感測器支援

面向Orange PiRPi5Orin NanoThor
多 CSIRK3588 4× / H618 1×2× CSI(4-lane)多路 CSI多路 CSI
Virtual ChannelRK3588 支援 VC0-3支援支援支援
同時取流可行(RK3588)可行可行可行
工具media-ctl 逐路設定libcamera multi-cameraArgus 多 cameraHoloscan 多 stream
頻寬瓶頸DDR 為主ISP/記憶體NVIDIA 強(多路 4K)最強(多路高解析)
核心領悟:「先單路、再並行、用二分法找瓶頸」是多相機除錯的通用流程,四平台皆然。Orange Pi 的 RK3588 有 4 組 receiver,是練習多相機最划算的硬體。

16.19 互動式檢核清單:本單元進階驗收

checklist
- [ ] 我能完成多相機 bring-up 專案並讓兩路同時取流。
- [ ] 我能列出每顆感測器的 bus、位址、video node 對應。
- [ ] 我會用「單路→並行→二分法」排查多相機問題。
- [ ] 我能計算兩路同時取流的總頻寬需求。
- [ ] 我能說明 virtual channel 與獨立 lanes 的差異。
- [ ] 我已驗證多路 10 分鐘長期穩定無掉幀。

16.20 Register 位元級完整工作流

多感測器與實作案例的「讀→改→寫→驗證」是進階應用的基礎:

步驟操作指令預期值
1. 掃描所有 I2Ci2cdetect -y 3i2cdetect -y 3兩顆感測器位址
2. 讀第一顆 ID0x300A + 0x300Bi2cget -y 3 0x3c 0x300a0x56
3. 讀第二顆 ID0x300A + 0x300Bi2cget -y 3 0x3c 0x300a(不同 bus)0x56
4. 建兩路 media linkmedia-ctl -lmedia-ctl -l "...; ..."兩條 link active
5. 設定兩路 formatmedia-ctl -Vmedia-ctl -V "...; ..."兩路格式正確
6. 同時取流v4l2-ctlv4l2-ctl --stream-mmap=1 -d /dev/video0 & v4l2-ctl ... -d /dev/video1兩路同時成功
位元級關鍵: 多感測器的關鍵是「獨立 I2C bus + 獨立 CSI receiver + 獨立 video device」。先確認每顆的 I2C 位址不衝突,再依序建立 link。

16.21 多層疑難排解決策樹

決策樹 A:兩路同時取流失敗

決策樹 A
兩路同時取流?
├─ 一路成功一路失敗
│  ├─ 失敗的那路 I2C 問題 → i2cdetect 確認
│  └─ CSI receiver 不足 → 檢查 DT lane 數
├─ 兩路都失敗
│  ├─ DDR 頻寬不足 → 降低解析度
│  └─ ISP 處理量不足 → 嘗試不同組合
└─ 兩路成功但掉幀
   └─ 用「先單路→再並行→二分法」找瓶頸

決策樹 B:客製 OV 接入四步

決策樹 B
新感測器接入四步:
├─ 1. I2C 位址確認 → i2cdetect
├─ 2. DT overlay 建立 → i2c + sensor 節點
├─ 3. 驅動 probe → dmesg 看 probe 結果
└─ 4. media graph 建立 → media-ctl -l -V

16.22 量測驗證完整 SOP

步驟指令預期輸出判讀標準
1. 掃描 I2Ci2cdetect -y 3兩顆感測器位址不衝突
2. 讀兩顆 IDi2cget -y 3 0x3c 0x300a0x56 + 0x56兩顆都正常
3. 建兩路 linkmedia-ctl -l兩條 link active正確 pad
4. 設定兩路 formatmedia-ctl -V兩路格式正確依各感測器能力
5. 同時取流v4l2-ctl --stream-mmap=1 & v4l2-ctl ...兩路成功無 timeout
6. 長期穩定10 分鐘測試無掉幀穩定

16.23 四平台終極對照

面向Orange PiRPi5Orin NanoThor推薦
CSI 接收器4× / 1×2× (4-lane)多路 CSI多路 CSI多相機→RK3588
同時取流可行(RK3588)可行可行可行多路→RK3588
工具media-ctl 逐路libcamera multiArgus multiHoloscan multi底層→media-ctl
頻寬瓶頸DDR 為主ISP/記憶體強(多路 4K)最強(多路)高解析→NVIDIA
學習成本中(完全手動)低(libcamera)低(封裝好)低(封裝好)學習→Orange Pi

16.24 完整 Bring-up 專案 Checklist

checklist
- [ ] 完成「多相機 bring-up」專案並讓兩路同時取流
- [ ] 列出每顆感測器的 bus、位址、video node 對應
- [ ] 用「單路→並行→二分法」排查多相機問題
- [ ] 計算兩路同時取流的總頻寬需求
- [ ] 說明 virtual channel 與獨立 lanes 的差異
- [ ] 驗證多路 10 分鐘長期穩定無掉幀
- [ ] 用客製 OV 四步接入新感測器
- [ ] 產出「multi-camera setup guide」
- [ ] 用二分法找頻寬瓶頸
- [ ] 產出「multi-camera stability report」
看完這單元你應該能說出:
  • 多相機 media 管線。
  • 客製 OV 接入四步。
  • Orange Pi 調校 OV5640 完整案例。
  • 最佳實踐。

延伸閱讀