名称Raspberry Pi カメラ・モータ制御PoC開発記録
番号MIRS2602-REPT-0007

版数最終更新日作成承認改訂記事
A01 2026.09.21 宮崎久生 初版

1. 目的

MIRSプロジェクトで使用するカメラ昇降機構の検討に向けて、Raspberry Piを用いた USBカメラ映像の取得・配信とモータ制御を実現できるかを確認する。 PCからRaspberry Piへネットワーク経由で接続し、カメラ映像の確認およびサーボモータ・ ステッピングモータの制御を行うためのPoC(概念実証)として実装・検証した。

2. 検証対象

項目内容
コンピュータRaspberry Pi
カメラUSBカメラ(/dev/video0)
カメラ処理OpenCV cv2.VideoCapture
WebサーバFlask
通信PCとRaspberry Piを同一ネットワーク上で接続
モータサーボモータ、ステッピングモータ
操作画面Webブラウザから操作するHTMLコントロールパネル

3. 実装方法

3-1. USBカメラの認識

当初は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」と表示され、カメラの初期化が成功することを確認した。

3-2. 静止画取得

OpenCVでカメラからフレームを取得し、JPEGへ変換してFlaskから /snapshot.jpgとして返す処理を実装した。 ブラウザからURLを直接開くことで、カメラ画像が表示されることを確認した。

3-3. カメラ映像の連続配信

連続映像については、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配信機能そのものは実装済みであるが、連続映像としての動作確認は未完了である。

3-4. Webブラウザからの制御

FlaskでAPIを用意し、PC側のHTMLコントロールパネルからRaspberry Piへ操作要求を送信する構成とした。 カメラ映像の確認に加えて、サーボモータの往復・停止・角度指定、ステッピングモータの回転・停止などを ブラウザから操作できるようにした。

3-5. モータ制御

GPIOを使用してサーボモータとステッピングモータを制御する処理を実装した。 サーボモータについてはPWMによる角度制御、ステッピングモータについてはGPIOを用いた ステップ制御を行う。

4. 検証結果

#項目判定結果
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 連続カメラ映像 未完了 ストリーム処理は実装済みだが、表示中のフレームが更新されない問題が残っている。

5. 発生した問題と対応

5-1. HTTPS通信によるHTTP 400エラー

Flaskのログに、次のような400エラーが繰り返し表示された。

code 400, message Bad request version ('\x13\x01\x13\x03...')

これはHTTPサーバに対してHTTPS/TLSの通信が送られている場合に発生する形式のエラーであり、 カメラ自体のエラーではない。FlaskのサーバはHTTPで動作しているため、 ブラウザからはhttp://Raspberry-PiのIPアドレス:5000でアクセスする必要がある。

5-2. GPIOの使用中警告

起動時に「This channel is already in use」というGPIOの警告が表示されることがある。 現時点では警告であり、サーバ起動やモータ制御を停止させるエラーではない。 終了時にGPIOの解放処理を行っているため、今後必要に応じて初期化・終了処理を見直す。

5-3. 連続映像が更新されない

/snapshot.jpgをブラウザで直接開くと画像が表示される一方、 連続表示ではカメラを物理的に動かしても表示画像が更新されない問題が確認された。

原因として、カメラフレームの取得方法やバッファリング、複数箇所からの camera.read()による競合などが考えられる。 現時点では原因を確定しておらず、専用のカメラ取得処理で常に最新フレームを保持する方式などを 今後検証する必要がある。

6. 現在の状態

現在、Raspberry Pi側のサーバはOpenCVを使用したUSBカメラ構成で起動できている。 カメラの認識、静止画取得、Flaskサーバ、API通信、サーボモータ・ステッピングモータの 制御処理までの基本機能は確認できている。

一方、PC側でカメラ映像を連続表示する機能については未完成である。 MJPEGストリームの処理自体は実装しているが、フレームが更新されないため、 連続映像として実用できる状態にはなっていない。

7. 今後の検証項目

  1. カメラフレームを専用スレッド等で常時取得し、最新フレームを保持する方式の検証
  2. OpenCVカメラバッファの設定および古いフレームが残る問題の確認
  3. MJPEGストリームをPCのブラウザで連続表示できるかの再検証
  4. カメラ映像とサーボモータ・ステッピングモータを同時に動作させた場合の安定性確認
  5. 実際のカメラ昇降機構へ搭載した場合を想定した、通信遅延・映像遅延の確認
  6. 3 m程度のポール先端へ搭載することを想定した、Raspberry Pi・カメラ・モータ等の重量と配置の検討



MIRS DATABASE