| 名称 | Raspberry Pi カメラ・モータ制御PoC開発記録 |
|---|---|
| 番号 | MIRS2602-REPT-0007 |
| 版数 | 最終更新日 | 作成 | 承認 | 改訂記事 |
|---|---|---|---|---|
| A01 | 2026.09.21 | 宮崎久生 | 初版 |
MIRSプロジェクトで使用するカメラ昇降機構の検討に向けて、Raspberry Piを用いた USBカメラ映像の取得・配信とモータ制御を実現できるかを確認する。 PCからRaspberry Piへネットワーク経由で接続し、カメラ映像の確認およびサーボモータ・ ステッピングモータの制御を行うためのPoC(概念実証)として実装・検証した。
| 項目 | 内容 |
|---|---|
| コンピュータ | Raspberry Pi |
| カメラ | USBカメラ(/dev/video0) |
| カメラ処理 | OpenCV cv2.VideoCapture |
| Webサーバ | Flask |
| 通信 | PCとRaspberry Piを同一ネットワーク上で接続 |
| モータ | サーボモータ、ステッピングモータ |
| 操作画面 | Webブラウザから操作するHTMLコントロールパネル |
当初はPicamera2を使用してカメラを初期化していたが、使用しているカメラはUSBカメラであり、 Picamera2からは「No cameras available」となった。 そこで、Linux上のV4L2デバイスとして認識されているUSBカメラをOpenCVから直接取得する方式に変更した。
camera = cv2.VideoCapture(0)
if not camera.isOpened():
raise RuntimeError("Cannot open USB camera")
変更後、起動時に「USB camera initialized」と表示され、カメラの初期化が成功することを確認した。
OpenCVでカメラからフレームを取得し、JPEGへ変換してFlaskから
/snapshot.jpgとして返す処理を実装した。
ブラウザからURLを直接開くことで、カメラ画像が表示されることを確認した。
連続映像については、Flaskのジェネレータを使用してJPEG画像を繰り返し送信する
MJPEG方式の/streamを実装した。
def camera_stream():
global camera_error
while running:
try:
jpg = frame_to_jpeg()
except Exception as exc:
camera_error = str(exc)
jpg = error_jpeg(camera_error)
time.sleep(0.5)
yield b"--frame\r\nContent-Type: image/jpeg\r\n\r\n" + jpg + b"\r\n"
time.sleep(0.03)
ただし、現時点では連続映像として表示した際にフレームが更新されず、同じ画像が表示され続ける問題が残っている。 そのため、MJPEG配信機能そのものは実装済みであるが、連続映像としての動作確認は未完了である。
FlaskでAPIを用意し、PC側のHTMLコントロールパネルからRaspberry Piへ操作要求を送信する構成とした。 カメラ映像の確認に加えて、サーボモータの往復・停止・角度指定、ステッピングモータの回転・停止などを ブラウザから操作できるようにした。
GPIOを使用してサーボモータとステッピングモータを制御する処理を実装した。 サーボモータについてはPWMによる角度制御、ステッピングモータについてはGPIOを用いた ステップ制御を行う。
| # | 項目 | 判定 | 結果 |
|---|---|---|---|
| K1 | USBカメラの認識 | 確認済み | OpenCVのVideoCapture(0)でカメラを初期化でき、「USB camera initialized」と表示された。 |
| K2 | 静止画取得 | 確認済み | /snapshot.jpgをブラウザで開くとカメラ画像が表示された。 |
| K3 | Flaskサーバ起動 | 確認済み | 0.0.0.0:5000でサーバを起動でき、PCから接続できた。 |
| K4 | API通信 | 確認済み | ステータスAPIへのアクセスがHTTP 200で返ることを確認した。 |
| K5 | モータ制御 | 確認済み | サーボモータおよびステッピングモータの制御処理を実装し、動作確認を行った。 |
| K6 | 連続カメラ映像 | 未完了 | ストリーム処理は実装済みだが、表示中のフレームが更新されない問題が残っている。 |
Flaskのログに、次のような400エラーが繰り返し表示された。
code 400, message Bad request version ('\x13\x01\x13\x03...')
これはHTTPサーバに対してHTTPS/TLSの通信が送られている場合に発生する形式のエラーであり、
カメラ自体のエラーではない。FlaskのサーバはHTTPで動作しているため、
ブラウザからはhttp://Raspberry-PiのIPアドレス:5000でアクセスする必要がある。
起動時に「This channel is already in use」というGPIOの警告が表示されることがある。 現時点では警告であり、サーバ起動やモータ制御を停止させるエラーではない。 終了時にGPIOの解放処理を行っているため、今後必要に応じて初期化・終了処理を見直す。
/snapshot.jpgをブラウザで直接開くと画像が表示される一方、
連続表示ではカメラを物理的に動かしても表示画像が更新されない問題が確認された。
原因として、カメラフレームの取得方法やバッファリング、複数箇所からの
camera.read()による競合などが考えられる。
現時点では原因を確定しておらず、専用のカメラ取得処理で常に最新フレームを保持する方式などを
今後検証する必要がある。
現在、Raspberry Pi側のサーバはOpenCVを使用したUSBカメラ構成で起動できている。 カメラの認識、静止画取得、Flaskサーバ、API通信、サーボモータ・ステッピングモータの 制御処理までの基本機能は確認できている。
一方、PC側でカメラ映像を連続表示する機能については未完成である。 MJPEGストリームの処理自体は実装しているが、フレームが更新されないため、 連続映像として実用できる状態にはなっていない。