工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

携帯型リモート監視カメラロボット - Raspberry PiとArduinoで構築

必要な部品と材料

SparkFun Arduino Pro Mini 328 - 5V/16MHz ×1
タイヤ付きDCモーター(ギアボックス+ブラケット付き) ×1
SparkFun Dual H-Bridge モータードライバー L298 ×1
Raspberry Pi 3 Model B ×1
Raspberry Pi Camera Module ×1

必要な工具

プロジェクト概要

ロボット設計・製作から、Linux(Raspberry Pi)の高度な設定、Androidアプリ開発、リモート制御までをカバーする野心的なプロジェクトです。全体を通して多くの学びが得られます。

扱う技術と概念

Step 1: 必要なもの

携帯型リモート監視カメラロボット - Raspberry PiとArduinoで構築
携帯型リモート監視カメラロボット - Raspberry PiとArduinoで構築

パーツ: プレキシガラス板、プラスチック板、接着剤、タイヤ付きDCモーター(ギアボックス+ブラケット)、小型ナット/ボルト、六角スペーサー、全方向キャスター×2、小型LEDライト(ヘッドライト化)、Arduino Pro Mini 328P、赤外線障害物センサー×2、PCB、NPNトランジスタ(ライト駆動用)、L7805CV 5Vレギュレーター、L298 Hブリッジ、220Ω抵抗、USB Type-Aオスコネクター、Micro USBオスコネクター、各種配線、3.3Vレギュレーター(Pi通信用)、オス/メスPCBコネクター、電源スイッチ、XT-60メスLiPoコネクター、2S 1300mAh LiPoバッテリー、5Vモバイルバッテリー、Raspberry Pi 3、microSDカード、Piケース、Piカメラ

工具: FT232RLアダプター、Arduino IDE、ドリル、細刃ノコ、ドライバー、はんだごて、ニッパー

必要スキル: はんだ付け、基本的なArduinoプログラミング、Linuxサービス設定・パッケージ管理

Step 2: ロボットプラットフォーム製作

仕様:

携帯型リモート監視カメラロボット - Raspberry PiとArduinoで構築

ベースプレート: 18×13cm。DCモーターをブラケットで固定。Hブリッジを中央底面に配置。後輪は2cm六角スペーサーで取り付け。Hブリッジ付近に配線通し用の大きな穴を開ける。

トップ部分: L字型プレート2枚(12×13cm、6.5×13cm)を接着。電子部品カバー、ヘッドライトマウント、Piケース支持台を兼ねる。6cm六角スペーサーでベースと連結。

Step 3: 電子回路製作

携帯型リモート監視カメラロボット - Raspberry PiとArduinoで構築

ピンアサイン(Arduino側)

PCB組み立て手順

  1. Hブリッジをベース底面に固定済み。赤外線センサーを前後にL字金具で取り付け
  2. ヘッドライト: 5V LEDライトを加工し、トップ中央に接着。配線を穴通ししてコネクター化
  3. Raspberry Piケース組み立て(Pi、カメラ、microSDカード、カメラケーブル)
  4. メインPCB製作(Fritzing回路図参照)
    • コネクター類を基板裏面に半田付け
    • KF301-2Pコネクター、NPNトランジスタ+ベース抵抗、L7805CV、3.3Vレギュレーター(Pi通信Txライン用)を実装
    • Arduino Pro Miniにオスピン半田付け
    • 赤/黒/白の細線で配線(Fritzing図参照)
    • ヘッドライト用メスコネクター実装
  5. 各種コネクター製作
    • 5V USBバッテリー→Pi/Arduino給電ケーブル
    • LiPoバッテリー→電子基板用コネクター(XT-60、スイッチ経由)
    • 赤外線センサー、Hブリッジ、モーター接続
  6. 拡大鏡とマルチメーターで全配線確認後、Arduinoをソケットに装着

Step 4: Arduinoコード

なぜArduinoを中間層に置くのか?

  1. モジュール性: PiなしでもArduinoロボットとして再利用可能
  2. 安全性: 3$のPro Miniなら壊れても安心(Piは35$)
  3. リアルタイム性: OSの割り込みを受けず、PWM制御・センサーポーリングが確実
  4. フェイルセーフ: Pythonスクリプトエラーで暴走しても、Arduino側でタイムアウト停止可能
  5. デバッグ容易性: 疎結合システムは問題切り分けが容易

スケッチの機能:

  1. シリアル経由でモーター/ライトコマンド受信し駆動
    • M:-25:16; → 左-25、右16(前進しながら左旋回)
    • M:44:19; → 左44、右19(前進しながら右旋回)
    • L:1; ライトON / L:0; ライトOFF
  2. 前後赤外線センサーをポーリングし、距離データをシリアル送信
    • 形式: F=5:B=3; (前方障害物レベル5、後方レベル3)

ライブラリ: TextMotorCommandsInterpretter

// TextMotorCommandsInterpretter source: "https://github.com/danionescu0/arduino/tree/master/libraries/TextMotorCommandsInterpretter"
#include <SoftwareSerial.h>
#include <TextMotorCommandsInterpretter.h>

const char MOTOR_COMMAND = 'M';
const char LIGHT_COMMAND = 'L';
const long maxDurationForMottorCommand = 300; // コマンド有効期限(ms)
const byte maxPwmValue = 230;                 // 速度制限
const long transmitingInterval = 500;         // 距離データ送信間隔(ms)
const int maxObstacleDetection = 1000;        // アナログ最大検出値
const int minObstacleDetection = 500;         // アナログ最小検出値

const byte FLASH_PIN = 3;
const byte RIGHT_MOTOR_PWM_PIN = 5;
const byte RIGHT_MOTOR_EN1_PIN = A4;
const byte RIGHT_MOTOR_EN2_PIN = A5;
const byte LEFT_MOTOR_PWM_PIN = 6;
const byte LEFT_MOTOR_EN1_PIN = A3;
const byte LEFT_MOTOR_EN2_PIN = A2;
const byte FRONT_DISTANCE_SENSOR = A0;
const byte BACK_DISTANCE_SENSOR = A1;

SoftwareSerial masterComm(11, 10); // RX, TX (Pi通信用)
TextMotorCommandsInterpretter motorCommandsInterpretter(-50, 50, -50, 50);

String currentCommand;
long lastCheckedTime;
long lastTransmitTime;
boolean inMotion = false;

void setup() {
  Serial.begin(9600);
  masterComm.begin(9600);
  masterComm.setTimeout(10);
  pinMode(FLASH_PIN, OUTPUT);
  pinMode(LEFT_MOTOR_PWM_PIN, OUTPUT);
  pinMode(LEFT_MOTOR_EN1_PIN, OUTPUT);
  pinMode(LEFT_MOTOR_EN2_PIN, OUTPUT);
  pinMode(RIGHT_MOTOR_PWM_PIN, OUTPUT);
  pinMode(RIGHT_MOTOR_EN1_PIN, OUTPUT);
  pinMode(RIGHT_MOTOR_EN2_PIN, OUTPUT);
  lastCheckedTime = millis();
  lastTransmitTime = millis();
}

void loop() {
  if (masterComm.available() > 0) {
    currentCommand = masterComm.readString();
    processCommand();
  }
  if (inMotion && millis() - lastCheckedTime > maxDurationForMottorCommand) {
    stopMotors();
  }
  if (millis() - lastTransmitTime > transmitingInterval) {
    lastTransmitTime = millis();
    masterComm.print(getObstacleData());
    Serial.print(analogRead(BACK_DISTANCE_SENSOR));Serial.print("---");
    Serial.println(getObstacleData());
  }
}

String getObstacleData() {
  int frontDistance = analogRead(FRONT_DISTANCE_SENSOR);
  int backDistace = analogRead(BACK_DISTANCE_SENSOR);
  frontDistance = map(frontDistance, maxObstacleDetection, minObstacleDetection, 0, 10);
  backDistace = map(backDistace, maxObstacleDetection, minObstacleDetection, 0, 10);
  return String("F=" + String(frontDistance) + ":B=" + String(backDistace) + ";");
}

void processCommand() {
  switch (currentCommand.charAt(0)) {
    case (MOTOR_COMMAND): steerCar(); break;
    case (LIGHT_COMMAND): toggleLight(currentCommand.charAt(2)); break;
  }
}

void steerCar() {
  motorCommandsInterpretter.analizeText(currentCommand);
  float percentLeftMotor = motorCommandsInterpretter.getPercentLeft();
  float percentRightMotor = motorCommandsInterpretter.getPercentRight();
  Serial.write("Left=");Serial.println(percentLeftMotor);
  Serial.write("Right=");Serial.println(percentRightMotor);
  setMotorsDirection(motorCommandsInterpretter.getDirection());
  analogWrite(LEFT_MOTOR_PWM_PIN, percentLeftMotor * maxPwmValue);
  analogWrite(RIGHT_MOTOR_PWM_PIN, percentRightMotor * maxPwmValue);
  inMotion = true;
  lastCheckedTime = millis();
}

void setMotorsDirection(boolean forward) {
  if (forward) {
    digitalWrite(LEFT_MOTOR_EN1_PIN, HIGH);
    digitalWrite(LEFT_MOTOR_EN2_PIN, LOW);
    digitalWrite(RIGHT_MOTOR_EN1_PIN, HIGH);
    digitalWrite(RIGHT_MOTOR_EN2_PIN, LOW);
  } else {
    digitalWrite(LEFT_MOTOR_EN1_PIN, LOW);
    digitalWrite(LEFT_MOTOR_EN2_PIN, HIGH);
    digitalWrite(RIGHT_MOTOR_EN1_PIN, LOW);
    digitalWrite(RIGHT_MOTOR_EN2_PIN, HIGH);
  }
}

void stopMotors() {
  Serial.println("Stopping motors");
  analogWrite(LEFT_MOTOR_PWM_PIN, 0);
  analogWrite(RIGHT_MOTOR_PWM_PIN, 0);
  inMotion = false;
}

void toggleLight(char command) {
  Serial.println("Toggle light");
  if (command == '1') digitalWrite(FLASH_PIN, HIGH);
  else digitalWrite(FLASH_PIN, LOW);
}

Step 5: Raspberry Piプロジェクトと依存関係のインストール・設定

システムアーキテクチャ

携帯型リモート監視カメラロボット - Raspberry PiとArduinoで構築
  1. Androidアプリ: uv4lストリーミングをWebViewで表示。操作コマンドをMQTTサーバーへ送信
  2. MQTTサーバー(mosquitto): Dockerコンテナで稼働
  3. Pythonサーバー: Dockerコンテナ内で稼働。MQTTコマンド受信→シリアルでArduinoへ転送。ArduinoからのセンサーデータをMQTTへ転送
  4. Arduino: モーター/ライト制御、前後センサー監視

前提条件

  1. Raspbian完全インストール、カメラ物理接続・有効化、SSH有効化
  2. ポートフォワーディング設定(外部アクセス時): 9090(uv4l)、1883(mosquitto)
  3. gitインストール
  4. プロジェクトクローン: git clone https://github.com/danionescu0/robot-camera-platform.git(フォルダ位置固定:/home/pi/robot-camera-platform)
  5. Piのシリアルコンソール無効化

uv4lストリーミングインストール

chmod +x uv4l/install.sh
chmod +x uv4l/start.sh
sh ./uv4l/install.sh

設定: uv4l/start.shでパスワード、ポート、フレームレート、解像度、回転等を調整

DockerとDocker Composeインストール

Raspberry Pi公式ブログ参照

設定ファイル編集

uv4lテスト

sh ./uv4l/start.sh          # 開始
# ブラウザで https://your_ip:9090/stream を確認
sudo pkill uv4l             # 停止

systemctlで自動起動設定

# systemctlフォルダ内のファイルを /etc/systemd/system/ にコピー
sudo systemctl enable robot-camera.service
sudo systemctl enable robot-camera-video.service
# 再起動後、ステータス確認
sudo systemctl status robot-camera.service
sudo systemctl status robot-camera-video.service

Step 6: Androidアプリの設定とビルド

  1. GitHubからクローン: git clone https://github.com/danionescu0/android-robot-camera
  2. 開発者オプション有効化、Android Studioインストール
  3. プロジェクトインポート
  4. ./app/src/main/values/passwords.xmlでMQTT/ストリーミング認証情報設定
  5. アプリを実機にインストール・実行

Step 7: 使用方法とデバッグ

携帯型リモート監視カメラロボット - Raspberry PiとArduinoで構築
携帯型リモート監視カメラロボット - Raspberry PiとArduinoで構築

アプリ操作

デバッグ手順

  1. Arduino層: FTDIアダプターで第2シリアル接続し、手動コマンド送信テスト。モーター逆回転なら配線入れ替え
  2. Raspberry Pi層: docker psでコンテナ確認、netstat -nltpでポート9090/1883確認、ls -l /dev/ttyS0でシリアルポート確認、picocomで直接シリアルテスト、シリアルコンソール無効化確認、外部からMQTT/ストリーミングアクセス確認
  3. Android層: デバッグモード有効化、passwords.xml確認、外部アクセス確認、アプリ右上の「Connected」確認、Androidデバッガーでエラー確認

Step 8: その他のユースケースと拡張

物体追跡ロボット: 特定色・サイズの物体を追従

拡張アイデア: 顔認識追従、巡回・異常検知報告、3Gモデム搭載で屋外危険区域探査など。プラットフォームの汎用性が最大の利点です。

コード

回路図

製造プロセス

  1. 現代カメラの進化と設計:フィルムからデジタルへ
  2. カメラレンズの理解:設計、歴史、未来の革新
  3. MrRobot: Ubuntu Mobile で操作する Rapiro ロボット – 音声、タッチ、シェイクインタラクション
  4. Roomberry:Raspberry Pi Zero WでRoombaを監視ロボット化
  5. Bluetooth対応 Arduino制御 モータライズド カメラ スライダー 〜滑らかなシネマティック撮影を実現〜
  6. NeoPixelリングとArduinoで作るインタラクティブジャイロスコープLEDディスプレイ
  7. Arduinoと1Sheeldで作る万能Androidリモコン──IR制御で家電を一括操作
  8. DIY Arduino USBゲームコントローラー - 高性能ゲームパッドを自作
  9. Pixie: Arduino Pro Miniで作るNeoPixel腕時計 - アナログとデジタル融合のDIY光る時計
  10. Arduino Dueでマスターする音声認識と音声合成
  11. Arduinoで作るワイヤレスPowerPointポインター - シームレスなプレゼンテーション制御