今回の機材
- Jetson Orin Nano 開発者キット
- Raspberry Pi Camera Module 2
- Raspberry Pi Zero用カメラケーブル(15-pin to 22-pin FFC cable)
Camera Module 2 接続
XavierNXまではraspberrypiと同じ15ピン 1.0mmピッチのコネクタでしたが、Orin Nanoから22ピン 0.5mmピッチに変わっており、XavierNXまでで使えていたCSIカメラをそのまま繋ぐことは出来ません。
ですが、22ピン 0.5mmピッチはRaspberry Pi Zero Wと同じタイプです。
おおよそ同じピン配置なのでPi cameraの15-pin to 22-pin FFC cableが使えます。
RaspberryPiのコネクタのpin配置はarducamのサイトにわかりやすく図も乗っています。
画像を引用しました。
Pin#15から3V3、I2Cとなっています。
15-22pinの場合は以下の図の通り、間にある2レーン分を未接続にしてつないでいます。
Orin NanoについてはJetson Download CenterのCarrier Board Specificationを参照しましょう。
OrinNanoの場合はButtomHeaderがある方がPin#1で、こちらから3V3, I2Cとなっています。
PinNoはRaspberryPiとは逆ですが、並びは同じなのでこの図にある通り、基板側に電極が来るようにつなげればOKです。
スライドを引き、少し上に持ち上げ、FFC電極面がキャリアボード側を向くように差して止めます。
差し込み感がわかりにくいですがJetsonHacks Using the Jetson Orin Nano with CSI Cameras
に動画があるのでそちらも参考にしてください。
とりあえずCAM0につないでRebootをするとdmesg
に次のようなログがあるはずです
これでドライバのロードもされてIMX219が認識されているはずです
imx219 9-0010: tegracam sensor driver:imx219_v2.0.6
tegra-camrtc-capture-vi tegra-capture-vi: subdev imx219 9-0010 bound
v4l2-ctl --list-devices
NVIDIA Tegra Video Input Device (platform:tegra-camrtc-ca):
/dev/media0
vi-output, imx219 9-0010 (platform:tegra-capture-vi:1):
/dev/video0
撮影
失敗編(CAM0)
撮影してみましょう。
RAW画像をそのまま保存してみます。
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat=RG10 --set-ctrl bypass_mode=0,sensor_mode=0 --stream-mmap --stream-count=1 --stream-to=test.raw
結果が出てこない場合はdmesgを見ましょう。
エラーに uncorr_err: request timed out after 2500 ms
とある場合、ビデオ入力を受け取るtegra-capture-vi
が入力のシグナルを受け付けなかったというエラーです。
実はこれ35.3.1ではデバイスツリーの設定不具合があって基本的に成功しません。
諦めてCAM1を使いましょう。
tegra-camrtc-capture-vi tegra-capture-vi: uncorr_err: request timed out after 2500 ms
tegra-camrtc-capture-vi tegra-capture-vi: err_rec: attempting to reset the capture channel
(NULL device *): vi_capture_control_message: NULL VI channel received
t194-nvcsi 13e40000.host1x:nvcsi@15a00000: csi5_stream_close: Error in closing stream_id=0, csi_port=0
(NULL device *): vi_capture_control_message: NULL VI channel received
t194-nvcsi 13e40000.host1x:nvcsi@15a00000: csi5_stream_open: VI channel not found for stream- 0 vc- 0
tegra-camrtc-capture-vi tegra-capture-vi: err_rec: successfully reset the capture channel
成功編(CAM1)
CAM1につなぐとカメラ imx219 9-0010
-> imx219 10-0010
となって認識できます。
imx219 10-0010: tegracam sensor driver:imx219_v2.0.6
tegra-camrtc-capture-vi tegra-capture-vi: subdev imx219 10-0010 bound
$ v4l2-ctl --list-devices
NVIDIA Tegra Video Input Device (platform:tegra-camrtc-ca):
/dev/media0
vi-output, imx219 10-0010 (platform:tegra-capture-vi:2):
/dev/video0
RAW取得コマンドも以前とことなり正常に終了してRAWデータが得られています。
$ v4l2-ctl -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat=RG10 --set-ctrl bypass_mode=0,sensor_mode=0 --stream-mmap --stream-count=1 --stream-to=test.raw
<
Argus
実際の映像も確認しましょう。
Jetson Orin NanoにもISPが乗っているのでArgusAPI経由でデベイヤーした画像が得られます。
argus_camera(実機)
argus_cameraで動作確認します。
以下のようなMakefileでmake setup
を実行したら、argus_cameraのバイナリが実行したディレクトリにできます。
実行したらカメラの画像が見れると思います。
なお、SSHでX11 Forwardしている場合はArgusAPIを叩くときにEGLの周りでエラーで動かないことがあります。
実機で見るか、unset DISPLAY
してGStreamerで動画記録の方法をおすすめします。
.PHONY: setup
setup:
sudo apt update
sudo apt install -y nvidia-l4t-jetson-multimedia-api \
cmake build-essential pkg-config libx11-dev libgtk-3-dev \
libexpat1-dev libjpeg-dev libgstreamer1.0-dev v4l-utils tree
cp -r /usr/src/jetson_multimedia_api .
cd jetson_multimedia_api/argus/ && \
mkdir -p build && \
cd build && \
cmake .. && \
make
cp jetson_multimedia_api/argus/build/apps/camera/ui/camera/argus_camera .
Record Video by GStreamer
リモートでするならgstreamerからファイル保存をするのも楽です。
残念ながらOrinNanoにHW Encoderは載っていないのでx264enc
を使います。
出来たファイルをLocalMachineに持ってきて撮影できているか確認してください。
gst-launch-1.0 nvarguscamerasrc num-buffers=30 ! nvvidconv ! x264enc ! mp4mux ! filesink location=test.mp4
まとめ
-
15-pin to 22-pin FFC cableがあればRaspberryPiのカメラが使える
- switch-scienceで買うならRPI-A-003
- CAM0ポートでは動作しない
- L4T35.3.1のデフォルトのデバイスツリーでは動かない設定でした
- 下記原因究明編を参照してください
余談
XavierNXのキャリアボードからピンのアサインと関わっていました。
今回のピン配置ですが以下のとおりです。
左からIMX219カメラの15pinを22pin変換したもの、OrinのCAM0,1とXavierNXのJ1(CAM1とスクリーン印刷されていますが実際にはCAM0)
XavierNXのときにはCSI0がつながっていましたがOrinNanoではCSI1になっています。
Pin # | IMX219 Camera with Cable | Orin Nano CAM0 | Orin Nano CAM1 | XavierNX J1 |
---|---|---|---|---|
1 | 3V3 | 3V3 | 3V3 | 3V3 |
2 | CAM_SDA | CAM_I2C_SDA | CAM_I2C_SDA | CAM_I2C_SDA |
3 | CAM_SCL | CAM_I2C_SCL | CAM_I2C_SCL | CAM_I2C_SCL |
4 | GND | GND | GND | |
5 | CAM_IO1 | CAM0_MCLK | CAM0_MCLK | CAM0_MCLK |
6 | CAM_IO0 | CAM0_PWDN | CAM0_PWDN | CAM0_PWDN |
7 | GND | GND | ||
8 | CSI0_D1_P | CSI3_D1_P | ||
9 | CSI0_D1_N | CSI3_D1_N | ||
10 | GND | GND | ||
11 | CSI0_D0_P | CSI3_D0_P | ||
12 | CSI0_D0_N | CSI3_D0_N | ||
13 | GND | GND | GND | GND |
14 | CAM_CK_P | CSI1_CLK_P | CSI2_CLK_P | CSI0_D1_P |
15 | CAM_CK_N | CSI1_CLK_N | CSI2_CLK_N | CSI0_D1_N |
16 | GND | GND | GND | GND |
17 | CAM_D1_P | CSI1_D1_P | CSI2_D1_P | CSI0_D0_P |
18 | CAM_D1_N | CSI1_D1_N | CSI2_D1_N | CSI0_D0_N |
19 | GND | GND | GND | GND |
20 | CAM_D0_P | CSI1_D0_P | CSI2_D0_P | CSI0_CLK_P |
21 | CAM_D0_N | CSI1_D0_N | CSI2_D0_N | CSI0_CLK_N |
22 | GND | GND | GND | GND |
またOrinシリーズのCSI0,1はデータレーンの極性がswapしているので特別な指定が必要となってます。
L4Tソースのtegra234-p3768-0000-a0.dtsi
にその記述があるので、カメラドライバを移植する時は変更をお忘れなく。
tegra-capture-vi {
ports {
port@0 {
endpoint {
port-index = <1>;
};
};
};
};
host1x@13e00000 {
nvcsi@15a00000 {
csi_chan0 {
ports {
port@0 {
endpoint@0 {
port-index = <1>;
};
};
};
};
};
};
cam_i2cmux{
i2c@0 {
rbpcv2_imx219_a@10 {
mode0 {
# CSI1(CSI-B)を指定
tegra_sinterface = "serial_b";
# CSIx_D1とCSIx_D0のスワップ
lane_polarity = "6";
};
mode1 {
tegra_sinterface = "serial_b";
lane_polarity = "6";
};
mode2 {
tegra_sinterface = "serial_b";
lane_polarity = "6";
};
mode3 {
tegra_sinterface = "serial_b";
lane_polarity = "6";
};
mode4 {
tegra_sinterface = "serial_b";
lane_polarity = "6";
};
ports {
port@0 {
endpoint {
port-index = <1>;
};
};
};
};
rbpcv3_imx477_a@1a {
mode0 {
tegra_sinterface = "serial_b";
lane_polarity = "6";
};
mode1 {
tegra_sinterface = "serial_b";
lane_polarity = "6";
};
ports {
port@0 {
endpoint {
port-index = <1>;
};
};
};
};
};
};
};
CAM0原因究明編
なぜCAM0だけ機能しないのでしょう。
それはOrinNanoDevKitのピン設定と上のデバイスツリー設定に原因があります。
CAM0ポートは従来と違ってCSI1(別名CSI-B)が繋がっています。
TRMの接続経路を見てみると以下のようにCSI-AB Pad -> RX SCIL0 -> PP1 -> VIへと入力されます。
従来とはroutingが異なるわけですね。
それを反映するのが上のデバイスツリーです。
大本のデバイスツリーではport_index=<0>
だったものを<1>
に書き換えることで、OrinNXとOrinNanoの両方に対応しているわけですね。
で、上の設定には一箇所だけ設定不具合があり、以下が正しい設定となります。
host1x@13e00000 {
nvcsi@15a00000 {
- csi_chan0 {
+ channel@0 {
ports {
port@0 {
endpoint@0 {
port-index = <1>;
};
};
};
};
};
};
csi_chan0
はシンボルなので実ツリーの指定が必要というわけでした。
ブロック単位でのroutingは正しくともPAD設定が繋がっていなかったのでデータ無しのエラーだったということです。