Raspberry Pi Multi-Camera Adapter Module V2.2を使用し、カメラを制御する方法

　サークルでロボットに着けるカメラをAruducam製、Raspberry Pi Multi-Camera Adapter Module V2.2で制御しようと思い購入しました。付属している説明書が正しくなかったり（AruducamのGitHubに行くと正しいセットアップやサンプルコードが手に入りました）、ネットにもあまり使い方について書いているページを見かけなかったりして使うのにかなり苦労したため、備忘録として残したいと思います。また、プログラミングや電装は独学で学んだため、かなり怪しいところがあります。あくまで参考程度にしてください。

##使用したもの
Raspberry Pi 4B(以下　Raspberry Pi)
Aruducam製、Raspberry Pi Multi-Camera Adapter Module V2.2（以下　カメラモジュール）
Raspberry Pi Camera V2 4個（以下　ラズパイカメラ）

##初めに
Raspberry Piの設定からカメラとI2Cの設定を有効にしておく。
カメラモジュールにラズパイカメラを接続した後（配線の向きに注意してください）、Raspberry Piのカメラポートにカメラモジュールを接続する。
接続後、カメラモジュールのピンソケットにRaspberry Piのピンを接続する。


##カメラテスト
　[AruducamのGitHub](https://github.com/ArduCAM/RaspberryPi/tree/master/Multi_Camera_Adapter/Multi_Adapter_Board_4Channel)を参考にカメラのテストを行います。初めに、カメラモジュールを動かすのに必要なものrをRaspberry Piにインストールします。ターミナルで以下の操作を行ってください。

```
$ sudo apt-get install wiringpi
$ sudo apt-get install libopencv-dev
```
インストール後、Raspberry Pi 4Bにカメラモジュールを対応させるため以下の処理を行います。

```
$ cd /tmp
$ wget https://project-downloads.drogon.net/wiringpi-latest.deb
$ sudo dpkg -i wiringpi-latest.deb
```

AruducamのGitHubからサンプルコードをダウンロードし、カメラテストをします。

```
$ git clone https://github.com/ArduCAM/RaspberryPi.git
$ cd RaspberryPi/Multi_Camera_Adapter/Multi_Adapter_Board_4Channel/Multi_Camera_Adapter_V2.2_python/ 
$ sudo chmod +x init_camera.sh
$ sudo ./init_camera.s
```

GitHubではC++でカメラテストしていますが、私はpythonでカメラテストをしました。
Multi_Camera_Adapter_V2.2_pythonファイルは、print文の"( )"が抜けているのでエラーが入ると思います。（2021/03/02現在）ファイルを開いてすべてのprint文に"( )"を入れてあげてください。
5秒間隔でカメラモジュールに接続されたカメラが順番に起動し、写真を取れたら成功です。

##応用する
　pythonのサンプルコードではプログラムから、ターミナルに"i2cset"と"raspistill"を入力し写真を撮っていることが分かりました。私は、最終的にロボットカメラで得た映像をリアルタイムで操縦者に提供することをしたいので、ターミナルのコマンドから映像を得る方法では少し不便だなと感じました。そこで、"pigpio"、"picamera"、"opencv"のライブラリを使用し、キーボートのアクセスでカメラを順番に切り替えるプログラムを作成しました。

```
import pigpio
import cv2
import picamera
import picamera.array

pi = pigpio.pi()

pi.set_mode(4,pigpio.OUTPUT)
pi.set_mode(17,pigpio.OUTPUT)
pi.set_mode(18,pigpio.OUTPUT)

pi.set_mode(22,pigpio.OUTPUT)
pi.set_mode(23,pigpio.OUTPUT)
pi.set_mode(9,pigpio.OUTPUT)
pi.set_mode(25,pigpio.OUTPUT)

pi.write(17,1)
pi.write(18,1)
pi.write(22,1)
pi.write(23,1)
pi.write(9,1)
pi.write(25,1)

width=400
high=260

def camera():
	with picamera.PiCamera(0) as camera:
		with picamera.array.PiRGBArray(camera) as stream:
			camera.resolution = (width,high)
			while True:
				camera.capture(stream,'bgr',use_video_port=True)
				cv2.imshow('frame',stream.array)
				if cv2.waitKey(1)&0xFF==ord('q'):
					cv2.destroyAllWindows()
					break
				stream.seek(0)
				stream.truncate(0)


def main():
	print("Start test the camera A")
	h=pi.i2c_open(1,0x70)
	pi.i2c_write_byte_data(h,0x00,0x04)
	
	pi.write(4,0)
	pi.write(17,0)
	pi.write(18,1)
	camera()
				
				
	print("Start test the camera B")
	pi.i2c_write_byte_data(h,0x00,0x05)
	pi.write(4,1)
	pi.write(17,0)
	pi.write(18,1)
	camera()
				
						

	print("Start test the camera C")
	pi.i2c_write_byte_data(h,0x00,0x06)
	pi.write(4,0)
	pi.write(17,1)
	pi.write(18,0)
	camera()
				

	print("Start test the camera D")
	pi.i2c_write_byte_data(h,0x00,0x07)
	pi.write(4,1)
	pi.write(17,1)
	pi.write(18,0)
	camera()

	

if __name__ =="__main__":
	main()

	gp.write(4,0)
	gp.write(17,0)
	gp.write(18,1)
```

　せっかく、opencvを使用しているのでカメラ映像を"cv2.VideoCapture(0)"で読み込みたかったのですが、なぜか"cv2.VideoCapture(0)"ではカメラを一つしか認識しませんでした。そのため、"picamera"のライブラリを使用しています。また、サンプルプログラムでは、"RPi.GPIO"のライブラリでGPIOを制御していますが、私は "RPi.GPIO"ライブラリがうまく扱えないので、"pigpio"で制御しています。そのため、サンプルプログラムとピンの番号が違っていますが、やっていることは同じです。
　要は、I2C通信でカメラモジュールのアドレス0x07（サンプルも、私も同じアドレスでした）にアクセスし、register（サンプルも、私も0x00でした）に各カメラの[vlue]（カメラAなら0x04）を書き込んであげて、各カメラに対応するgpioピンをアクティブにしてあげれば動くと思います。