上電時序、PLL 位元級、MIPI、決策樹
| 步 | 電源域 | 電壓 | 時序要求 |
|---|---|---|---|
| 1 | AVDD(analog) | 2.8 V | 先穩定 |
| 2 | DOVDD(I/O) | 1.8 V | 可與 AVDD 同時或稍後 |
| 3 | DVDD(digital) | 1.5 V | 在 DOVDD 後 |
| 4 | XCLK | 24 MHz | 電源穩定後 |
| 5 | RESET 釋放 | — | XCLK 穩定後 ≥ 若干 ms |
| 6 | I2C | — | RESET 後才可通 |
reset 腳位保持低位 → 上電 → XCLK → 釋放 reset → 等 → 下 I2C。OV5647 由 XCLK(典型 24 MHz)經內部 PLL 產生主時脈。關鍵 register:
| Register | 欄位 | 典型值 | 意義 |
|---|---|---|---|
| 0x3034 | PLL pre-divider | 0x18 | XCLK 輸入分頻 |
| 0x3035 | PLL divider | 0x31 | VCO 分頻 |
| 0x3036 | PLL multiplier | 0x69 | VCO 倍頻 |
| 0x3037 | PLL control | 0x11 | 含 lock 狀態位元 |
ov5647_2lane_480Mbps init 表為唯一正確依據(不要自行亂配)。| Register | 功能 | 典型值 | 備註 |
|---|---|---|---|
| 0x4740 | MIPI 介面控制 | 0x22 | — |
| 0x4741 | lane 數設定 | 0x00 | 0x00 = 2-lane |
| 0x4742 | clock/data 設定 | 0x0b | — |
lane 數若與 DT overlay 宣告不一致 → 串流失敗。這是「驅動 vs 硬體」不一致的典型。
- entity 3: ov5647 0-0036 (1 pad, 1 link)
type V4L2 subdev
pad0: Source [fmt:SGBRG10_1X10/2592x1944]
- entity 6: unicam (1 pad, 1 link)
type V4L2 subdev
pad0: Sink [fmt:SGBRG10_1X10/2592x1944]看到感測器 pad 的格式 → 管線已設定。格式不匹配(source 與 sink)→ 串流失敗。
1. rpicam-hello --list-cameras ├─ 空 ───────────────────────────────→ 步驟 A └─ 有 ─┐ 2. i2cdetect -y 22 看到 0x36? ├─ 無 ─→ 步驟 B └─ 有 ─┐ 3. 讀 0x300A/B = 0x56/0x47? ├─ 錯 ─→ 步驟 C └─ 對 ─┐ 4. rpicam-hello 預覽 ├─ 黑 ─→ 曝光 0?AE 關?鏡頭蓋?→ 單元 10 └─ 有畫面 ── 基本 bring-up ✅ 步驟 A(list 不到):dmesg | grep -i -E "ov5647|unicam|error" ├─ probe failure → 電源/clock/位址(檢查 DT) └─ 排線/連接器 → 重插、換排線 步驟 B(無 0x36):上電?RESET?位址(7-bit vs 8-bit)?匯流排對嗎(22/10)? 步驟 C(ID 錯):是別顆感測器?I2C 位址衝突?換過板子?
for r in 0x300a 0x300b 0x3034 0x3035 0x3036 0x3037 0x3500 0x3501 0x3502 0x3503 0x350a 0x350b; do
h=${r:2:2}; l=${r:4:2}
printf "%s: " "$r"; sudo i2ctransfer -y 22 w2@0x36 0x$h 0x$l r1
done| dmesg 片段 | 意義 |
|---|---|
ov5647 0-0036: Probing | 驅動開始 probe |
ov5647: Chip ID 0x5647 | ID 讀取成功(若 log 有) |
unicam: Failed to... | CSI 收資料失敗 |
| 無任何 ov5647 訊息 | DT 沒掛 overlay / 驅動沒載 |
感測器開機後不是「能用」,而是需要驅動寫入一整串 init register(時序、解析度、增益、AWB…)。ov5647.c 內含 ov5647_2lane_480Mbps 等表格,就是這份 init。
曝光時間(行數)不能超過幀總行數(frame length)。若設的曝光 > 幀長,感測器會「卡在曝光」→ 幀率掉或全黑。
# 讀曝光 register sudo i2ctransfer -y 22 w2@0x36 0x35 0x01 r1 sudo i2ctransfer -y 22 w2@0x36 0x35 0x02 r1 # 讀 frame length(0x380E/0x380F) sudo i2ctransfer -y 22 w2@0x36 0x38 0x0e r1
場景:你拿到一塊新的 OV5647 客製板,接上 RPi5 後 list-cameras 為空。需要從零開始走完整決策樹。
# === 步驟 1:確認 overlay 是否載入 === sudo dtoverlay -a | grep ov5647 # 若空 → 加入 /boot/firmware/config.txt: # dtoverlay=ov5647 # 重開機 # === 步驟 2:dmesg 看 probe 狀態 === dmesg | grep -i -E "ov5647|unicam|error" | tail -20 # 預期看到 "ov5647 0-0036: Probing" # 若看到 "probe failed" → 進入步驟 3 # === 步驟 3:I2C 掃描 === sudo i2cdetect -y 22 # 看到 0x36 → I2C 通 # 全空 → 檢查排線/電源 # === 步驟 4:讀 sensor ID === sudo i2ctransfer -y 22 w2@0x36 0x30 0x0a r1 # 應回 0x56 sudo i2ctransfer -y 22 w2@0x36 0x30 0x0b r1 # 應回 0x47 # === 步驟 5:PLL 暫存器快照 === for r in 0x3034 0x3035 0x3036 0x3037; do h=${r:2:2}; l=${r:4:2} printf "%s: " "$r" sudo i2ctransfer -y 22 w2@0x36 0x$h 0x$l r1 done # === 步驟 6:出圖驗證 === rpicam-hello --list-cameras rpicam-still --raw -o test.dng --shutter 20000 --gain 1
OV5647 的 PLL 暫存器決定了 pixel clock 與 MIPI data rate,兩者不匹配會導致串流失敗:
| 症狀 | 可能原因 | 解決方案 |
|---|---|---|
| probe 成功但 streaming 時 dmesg 出現 CSI error | MIPI data rate 與 ISP 接收速率不匹配 | 對照 PLL 暫存器與 datasheet 的建議值;確認 lane 數一致 |
| i2cdetect 掃到 0x36 但讀回 ID 全為 0xFF | 感測器在低功耗模式,需要 XCLK 才能回應 | 確認 XCLK GPIO 已輸出 24MHz;用示波器量 XCLK 腳位 |
| dmesg 出現「PLL not locked」 | PLL 暫存器配置錯誤或 XCLK 頻率偏差 | 確認 XCLK 頻率(示波器);還原 PLL 暫存器到 init table 值 |
| rpicam-hello 預覽前 1-2 秒色彩偏移 | PLL lock 延遲 + AWB 初始值不準 | 在 tuning 檔中增加 AWB convergence delay;或等 AE/AWB 穩定後再擷取 |
| 換板子後完全沒畫面(但 dmesg 顯示 probe 成功) | 排線阻抗不匹配導致 MIPI HS 訊號劣化 | 用已知良品排線交叉測試;量測 MIPI 差動阻抗 |
ov5647_2lane_480Mbps init table 的每一行暫存器的作用,畫出「暫存器 → 功能」對照表。場景:生產線要驗證每塊客製板,不能靠人肉一步步打指令。本專案把單元 6 的決策樹寫成自動化腳本:依序驗證 overlay → I2C → ID → PLL → 出圖,任何一步失敗立即中斷並報出根因。整合單元 6(決策樹)、3(I2C)、4(overlay)、5(出圖)。
#!/bin/bash
set -e
BUS=22; ADDR=0x36
fail() { echo "✗ FAIL: $1"; exit 1; }
pass() { echo "✓ $1"; }
# 步驟 1:overlay 就緒
dtoverlay -a | grep -q ov5647 && pass "overlay 就緒" || fail "無 ov5647 overlay"
# 步驟 2:I2C 有回應
sudo i2cdetect -y $BUS | grep -q 36 && pass "I2C 0x36 回應" || fail "I2C 無回應"
# 步驟 3:讀感測器 ID
HI=$(sudo i2ctransfer -y $BUS w2@$ADDR 0x30 0x0a r1)
LO=$(sudo i2ctransfer -y $BUS w2@$ADDR 0x30 0x0b r1)
[ "$HI$LO" = "0x560x47" ] && pass "ID=$HI$LO" || fail "ID 錯誤=$HI$LO"
# 步驟 4:PLL 快照(記錄於 log)
for r in 3034 3035 3036 3037; do
printf "PLL %s=%s\n" "$r" "$(sudo i2ctransfer -y $BUS w2@$ADDR 0x${r:0:2} 0x${r:2:2} r1)"
done
# 步驟 5:出圖驗證
rpicam-hello --list-cameras | grep -q ov5647 && pass "libcamera 偵測" || fail "list-cameras 空"
rpicam-still --raw --shutter 20000 --gain 1 -o /tmp/bringup.dng && pass "出圖 OK"
echo "=== bring-up 全部通過 ==="ov5647: Probing 與 Chip ID 訊息。| 面向 | RPi5 | Orange Pi | Orin Nano | Thor |
|---|---|---|---|---|
| 上電管理 | overlay 的 reset/pwdn GPIO | BSP 驅動自管 | tegracam + device tree | tegracam / Holoscan |
| XCLK 來源 | cam_clk(可調頻率) | CLK 控制器 | sensor clock tree | HSB 時脈 |
| PLL 檢查 | i2ctransfer 讀 0x3034-0x3037 | 同(register 相同) | 同(register 相同) | 同(register 相同) |
| 坑 | RESET 未釋放即下 I2C | 上電順序在 BSP 黑箱 | 需 NVIDIA driver 先載 | 感測器經乙太、時序不同 |
| 暫存器範圍 | 用途 | dump 指令範例 |
|---|---|---|
| 0x3000-0x3005 | 感測器控制(stream on/off) | for i in $(seq 0x3000 0x3005); do printf "0x%04X: " $i; i2cget -y 1 0x3C $i w; done |
| 0x3500-0x3503 | AEC 曝光設定 | 同上改範圍 0x3500-0x3503 |
| 0x3034-0x3037 | PLL 設定 | 同上改範圍 0x3034-0x3037 |
| 0x3800-0x3821 | 整合窗口 | 同上改範圍 |
| 0x5001-0x501F | ISP 控制 | 同上改範圍 |
決策樹 A:I2C scan 找不到感測器
I2C 找不到 ├─ 檢查 A:GPIO 供電是否正常 │ ├─ cam0_reg/cam1_reg = 0V → 電源 IC 異常 / overlay 未設定 power GPIO │ └─ 供電正常 → 繼續 ├─ 檢查 B:排線方向與位置 │ ├─ 排線反插 → 重插正確方向 │ └─ 正確 → 繼續 ├─ 檢查 C:I2C pull-up 是否存在 │ ├─ 無 pull-up → SCL/SDA 處於 floating → 加 2.2kΩ pull-up to 3.3V │ └─ 有 pull-up → 繼續 └─ 檢查 D:嘗試另一個 I2C bus(GPIO 0/1 vs GPIO 2/3) ├─ 另一個 bus 有回應 → overlay 指定了錯誤的 I2C bus └─ 都無回應 → 排線 / 感測器硬體問題
決策樹 B:影像有嚴重 color cast
Color cast ├─ 檢查 A:AWB 是否啟用 │ ├─ 未啟用 → tuning 檔案中 AWB 模組關閉 │ └─ 已啟用 → 繼續 ├─ 檢查 B:CCM (Color Correction Matrix) 是否為 identity │ ├─ 是 → 需設定正確 CCM 係數 │ └─ 否 → 繼續 ├─ 檢查 C:光源色溫是否在 AWB 覆蓋範圍 │ ├─ 不在 → AWB 演算法收斂失敗 → 加入該色溫範圍 │ └─ 在範圍內 → 繼續 └─ 檢查 D:感測器 IR filter 是否正確 ├─ 無 IR filter → 近紅外光干擾 → 加 IR cut filter └─ 有 IR filter → CCM 矩陣需針對實際光源校正
| 面向 | RPi5 | Orange Pi | Orin Nano | Thor | 推薦 |
|---|---|---|---|---|---|
| 除錯工具 | i2c-tools + dmesg | i2c-tools + dmesg | NV debug tools | NV debug + Holoscan | RPi5 最直覺 |
| Register dump | i2cget 逐個讀 | i2cget | NV 驅動內建 | NV 驅動內建 | RPi5 最透明 |
| 常見坑 | overlay 未生效 | BSP 版本不匹配 | NV closed source | 文件不足 | 各平台有各自坑 |
| 社群除錯 | 論壇活躍 | 較少 | Jetson 專區 | 新、少 | RPi5 + Jetson 社群最活躍 |