Raspberry Pi Zero 2WでBluetooth制御Carを作る

IT

1. はじめに

1.1 プロジェクトの概要

このプロジェクトでは、スマートフォンでコントロールできる小型の車(ロボット)を作ります。Raspberry Pi Zero 2W(ラズパイ)という小型コンピュータを使用し、スマートフォンからBluetoothで制御します。完成すると、前進、後退、左右の回転をスマートフォンから操作できるようになります。

1.2 必要な機材

  • Raspberry Pi Zero 2W
  • L298Nモータードライバー(モーターを制御する基板)
  • DCモーター 2個(タイヤ付き)
  • モバイルバッテリー(5V 2A以上)
  • ジャンパーワイヤー(オス-オス)数本
  • シャーシ(車体)
  • Android スマートフォン

1.3 プロジェクトの難易度と所要時間

  • 難易度:中級(電子工作初心者でも丁寧に進めれば完成可能)
  • 所要時間:2-3時間

 

2. ハードウェアのセットアップ

2.1 Raspberry Pi Zero 2Wの準備

  1. OSのインストール
    • Raspberry Pi ImagerでOSをインストール
    • 64ビットのデスクトップ版を選択
    • WiFiの設定も同時に行うと便利
  2. 初回起動
    • モニター、キーボード、マウスを接続
    • 電源を入れ、初期設定を完了

2.2 配線の手順

  1. L298Nモータードライバーの接続

    GPIOピンの接続:
    – GPIO 17 → IN1
    – GPIO 27 → IN2
    – GPIO 22 → IN3
    – GPIO 23 → IN4
    – GPIO 18 → ENA
    – GPIO 13 → ENB

  2. 電源の接続
    • モバイルバッテリーからRaspberry PiのUSB電源ポートへ接続
    • L298NモータードライバーのGNDとVCCの接続

2.3 モーターの接続

  1. 左モーター:L298NのOUT1とOUT2に接続
  2. 右モーター:L298NのOUT3とOUT4に接続
  3. 接続時の注意点:
    • 配線が確実に接続されているか確認
    • 極性は後で動作確認時に調整可能

 

3. ソフトウェアの準備

3.1 必要なパッケージのインストール

ターミナルを開き、以下のコマンドを順番に実行します:

sudo apt-get update
sudo apt-get install python3-bluetooth
sudo apt-get install --reinstall bluez bluez-tools

3.2 Bluetoothの設定

Bluetoothの設定ファイルを編集:

sudo nano /etc/bluetooth/main.conf

以下の設定を追加または変更:

DiscoverableTimeout = 0
Discoverable = true

Bluetoothサービスの再起動:

sudo systemctl restart bluetooth

スマホとペアリング

スマホとラズパイをBluetooth接続します。

3.3 制御用Pythonスクリプトの作成

以下のスクリプトを作成します:

sudo nano /home/hoge/Desktop/main.py

スクリプトの内容

以下のコードをエディタにコピーします:

import bluetooth
import subprocess
import time
import RPi.GPIO as GPIO

# GPIOピンの設定
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

# モーター制御ピンの定義
IN1 = 17  # GPIO 17 を IN1 に接続
IN2 = 27  # GPIO 27 を IN2 に接続
IN3 = 22  # GPIO 22 を IN3 に接続
IN4 = 23  # GPIO 23 を IN4 に接続
ENA = 18  # GPIO 18 を ENA に接続
ENB = 13  # GPIO 13 を ENB に接続

# GPIOピンのセットアップ
pins = [IN1, IN2, IN3, IN4, ENA, ENB]
for pin in pins:
   GPIO.setup(pin, GPIO.OUT)

# PWMの設定
pwm_a = GPIO.PWM(ENA, 1000)  # 1000Hzで初期化
pwm_b = GPIO.PWM(ENB, 1000)
pwm_a.start(100)  # デューティ比100%で開始
pwm_b.start(100)

def setup_bluetooth():
   """Bluetoothのセットアップを行う"""
   print("Bluetoothをセットアップ中...")
   subprocess.run(['sudo', 'hciconfig', 'hci0', 'reset'], check=True)
   time.sleep(2)
   subprocess.run(['sudo', 'hciconfig', 'hci0', 'piscan'], check=True)
   time.sleep(2)
   print("Bluetoothセットアップ完了")

def move_forward():
   """前進"""
   GPIO.output(IN1, GPIO.HIGH)
   GPIO.output(IN2, GPIO.LOW)
   GPIO.output(IN3, GPIO.HIGH)
   GPIO.output(IN4, GPIO.LOW)

def move_backward():
   """後退"""
   GPIO.output(IN1, GPIO.LOW)
   GPIO.output(IN2, GPIO.HIGH)
   GPIO.output(IN3, GPIO.LOW)
   GPIO.output(IN4, GPIO.HIGH)

def turn_right():
   """右回転"""
   GPIO.output(IN1, GPIO.LOW)
   GPIO.output(IN2, GPIO.HIGH)
   GPIO.output(IN3, GPIO.HIGH)
   GPIO.output(IN4, GPIO.LOW)

def turn_left():
   """左回転"""
   GPIO.output(IN1, GPIO.HIGH)
   GPIO.output(IN2, GPIO.LOW)
   GPIO.output(IN3, GPIO.LOW)
   GPIO.output(IN4, GPIO.HIGH)

def stop():
   """停止"""
   GPIO.output(IN1, GPIO.LOW)
   GPIO.output(IN2, GPIO.LOW)
   GPIO.output(IN3, GPIO.LOW)
   GPIO.output(IN4, GPIO.LOW)

def main():
   try:
       # Bluetoothのセットアップ
       setup_bluetooth()
       
       # サーバーソケットの作成
       print("\nサーバーソケットを作成中...")
       server_sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
       
       # ポートにバインド
       print("ポートにバインド中...")
       port = 1
       server_sock.bind(("", port))
       server_sock.listen(1)
       print(f"RFCOMMチャンネル {port} で待機中")
       
       # サービスの公開
       uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee"
       bluetooth.advertise_service(
           server_sock,
           "RaspiBtSrv",
           service_id=uuid,
           service_classes=[uuid, bluetooth.SERIAL_PORT_CLASS],
           profiles=[bluetooth.SERIAL_PORT_PROFILE]
       )
       
       print("\n接続待機中...")
       print("Androidデバイスから接続してください")
       client_sock, client_info = server_sock.accept()
       print(f"\n接続完了: {client_info}")
       
       # メインループ
       while True:
           try:
               # データ受信
               data = client_sock.recv(1024).decode('utf-8')
               if not data:
                   break
               print(f"受信データ: {data}")
               
               # 受信データに基づいて制御
               if 'forward' in data:
                   move_forward()
               elif 'backward' in data:
                   move_backward()
               elif 'right' in data:
                   turn_right()
               elif 'left' in data:
                   turn_left()
               elif 'stop' in data:
                   stop()
                   
           except bluetooth.BluetoothError as e:
               print(f"Bluetooth通信エラー: {e}")
               break
               
   except KeyboardInterrupt:
       print("\nプログラムが中断されました")
   except Exception as e:
       print(f"エラーが発生しました: {e}")
       import traceback
       traceback.print_exc()
   
   finally:
       print("\nクリーンアップ中...")
       # ソケットのクローズ
       if 'client_sock' in locals():
           client_sock.close()
       if 'server_sock' in locals():
           server_sock.close()
       # GPIOのクリーンアップ
       GPIO.cleanup()
       print("終了しました")

if __name__ == "__main__":
   main()

 

コードの説明

1. インポートと初期設定

– 必要なライブラリをインポート
– GPIOピンをBCMモードで設定
– モーター制御用のピン番号を定義

 

2. モーター制御関数

– `move_forward()`: 前進
– `move_backward()`: 後退
– `turn_right()`: 右回転
– `turn_left()`: 左回転
– `stop()`: 停止

 

3. Bluetooth通信

– RFCOMMソケットを使用
– ポート1で待ち受け
– シリアルポートプロファイルを使用

 

4. メインループ

– 接続待機
– データ受信と制御命令の実行
– エラー処理

 

5. クリーンアップ処理

– 接続の切断
– GPIOピンの解放

 

スクリプトの保存と実行

1. エディタでの保存

– `Ctrl + X`を押す
– 保存するか聞かれたら`Y`を押す
– Enterを押して確定

 

2. スクリプトの実行

sudo python3 /home/hoge/Desktop/main.py

このスクリプトは、Bluetoothで受信したコマンドに基づいてモーターを制御します。エラー処理も含まれており、予期せぬ問題が発生した場合でも安全に終了できるように設計されています。

 

 

4. デバイスの接続とテスト

4.1 初期接続の手順

  1. Bluetoothの設定を初期化:
sudo bluetoothctl

bluetoothctl内で:

power off
power on
discoverable on
pairable on
exit
  1. スクリプトの実行:
sudo python3 /home/juzo/Downloads/bt_test3.py
  1. Androidスマートフォンとの接続:
    • スマートフォンのBluetooth設定を開く
    • デバイスのスキャンを実行
    • “sansyou”を選択して接続

4.2 動作確認

  1. モーターの動作テスト
    • 前進/後進の確認
    • 左右の回転確認
    • 必要に応じてモーターの配線を調整
  2. 接続の安定性確認
    • 通信が途切れないか確認
    • レスポンスの遅延をチェック

4.3 トラブルシューティング

よくある問題と解決方法:

  1. 接続できない場合
    • Bluetoothサービスの再起動
    • ペアリングの再実行
  2. モーターが正しく動かない場合
    • 配線の確認
    • GPIOピン番号の確認
    • モーターの極性確認

 

5. トラブルシューティング

5.1 Bluetooth接続の問題

よくある症状と解決方法

  1. デバイスが見つからない場合
    # Bluetoothサービスの完全リセット
    sudo systemctl stop bluetooth
    sudo rm -rf /var/lib/bluetooth/*
    sudo systemctl start bluetooth

    その後、bluetoothctlで設定を行います:

    sudo bluetoothctl
    power off
    power on
    discoverable on
    pairable on
      • SDPサービスの問題の可能性があります
      • 以下のコマンドで状態を確認:接続は成功するが通信できない場合
      sdptool browse local
      • エラーが出る場合は、Bluetoothサービスの設定を修正:
      sudo nano /etc/systemd/system/bluetooth.target.wants/bluetooth.service

      ExecStartの行を以下のように修正:

      ExecStart=/usr/libexec/bluetooth/bluetoothd --compat

5.2 モーター制御の問題

  1. モーターが動かない
    • 電源電圧の確認
    • GPIOピンの接続確認
    • L298Nのジャンパー設定確認
  2. モーターの回転方向が逆
    • プログラム内のGPIO出力を反転
    • または物理的に配線を入れ替え
  3. 片方のモーターだけ動く
    • 接触不良の確認
    • モーター自体の故障チェック
    • L298Nのピン設定確認

5.3 Pythonスクリプトのデバッグ

  1. エラーメッセージの確認方法
    # コード
    except Exception as e:
    print(f"エラー詳細: {str(e)}") import traceback
    traceback.print_exc()
  2. ログの確認
    # Bluetoothのログを確認
    sudo journalctl -u bluetooth -n 50

     

    6. 発展的な内容

    6.1 機能の追加例

    1. スピード制御の実装
      def set_speed(speed): # PWMデューティ比の設定(0-100)
      pwm_value = int(speed) * 100 / 255
      pwm_a.ChangeDutyCycle(pwm_value)
      pwm_b.ChangeDutyCycle(pwm_value)
    2. 自動停止機能
      class BluetoothCar: 
      def __init__(self): self.setup_gpio() self.setup_bluetooth() 
      def setup_gpio(self): # GPIOの初期設定 
      def setup_bluetooth(self): # Bluetooth設定 
      def run(self): # メインループ
    3. バッテリー残量の監視
      # config.py 
      PIN_SETTINGS = { 'IN1': 17, 'IN2': 27, 'IN3': 22, 'IN4': 23, 'ENA': 18, 'ENB': 13 }
      def check_battery(): # GPIOで電圧を読み取り 
      voltage = read_voltage() 
      if voltage < threshold: 
      send_low_battery_alert()

6.2 コードの改良

  1. クラス化による整理
class BluetoothCar: def __init__(self): self.setup_gpio() self.setup_bluetooth() def setup_gpio(self): # GPIOの初期設定 def setup_bluetooth(self): # Bluetooth設定 def run(self): # メインループ
  1. 設定ファイルの外部化
# config.py PIN_SETTINGS = { 'IN1': 17, 'IN2': 27, 'IN3': 22, 'IN4': 23, 'ENA': 18, 'ENB': 13 }

6.3 ハードウェアの改良

  1. センサーの追加
    • 超音波センサーで障害物検知
    • 赤外線センサーでライントレース
    • 加速度センサーで傾き検知
  2. 電源管理の改善
    • 電圧レギュレータの追加
    • バッテリー保護回路の実装

7. 参考資料

7.1 技術資料

  1. Raspberry Pi公式ドキュメント
  2. Pythonライブラリ

7.2 コミュニティとサポート

  1. フォーラム
    • Raspberry Piフォーラム
    • Stack Overflow
    • Reddit r/raspberry_pi
  2. 日本語コミュニティ
    • Raspberry Pi日本語フォーラム
    • Qiita Raspberry Piタグ

7.3 プロジェクトの発展

  1. アイデア集
    • カメラ制御の追加
    • Webインターフェースの実装
    • AIによる自律走行
  2. セキュリティ考慮事項
    • Bluetooth通信の暗号化
    • アクセス制御の実装
    • エラー処理の強化

この内容は、基本的な機能を実装した後、さらに理解を深め、プロジェクトを発展させたい方向けの情報となっています。初学者の方は、まずは基本的な実装を確実に行い、その後徐々に機能を追加していくことをお勧めします。

コメント

タイトルとURLをコピーしました