カメラのパン・チルト(上下・左右方向に首を振る)をサーボモータ2個で制御します。さらに、この制御をスマホのアプリからジョイスティックのインターフェースでWiFi通信で遠隔制御する方法を解説します。カメラの基本的な使用方法は前回記載しましたので、そちらを参照してください。
環境
ハード
ラズパイ本体 | Raspberry Pi4 ModelB 4GB 技適対応品 |
カメラ | Raspberry Pi Camera Module V2 カメラモジュール |
パン・チルトキット | Pan Tilt HAT |
サーボ制御のボード | SparkFun Pi Servo HAT (PCA9685) |
バッテリ | Anker Power Core Fusion 5000 |
ソフト
OS | Raspbian Buster with desktop and recommended software (2020-02-13) |
Python | Python 3.7.3 |
カメラ パン・チルトの組み立て
パン・チルトのキット組み立ては、同梱の説明書を見れば10分程度組み立てられます。もし分かりにくければ、製造元のsparkfunのHPに記載がありますので、参考にしてください。
PCA9685でサーボを制御
PCA9685は高機能で、16個のサーボモータをI2Cで制御することができます。このICはNXP製で、データシートはここにあります。今回はSparkfun製のボードを使用しますが、Adafruitからも製造販売されています。
PCA9685のボードは、USB-Type Cのポートが付属しており、ここに電源を供給することで、Raspberry Pi本体にも電源供給することができるので、電源周りをコンパクトに纏められます。ただし、サーボモータ多く動かす場合は、消費電力が大きくなるので、接続する電源の供給電流をよく確認してください。もし、電流量が足りない場合は、ボードの電源ジャンパー配線を切断して、ボードとRaspberry Piに別電源を供給できるようになっています。詳細はここを見てください。
サーボ制御プログラムは、AdafruitのCircuitPythonライブラリを使用します。そのため、まずはCircuitPythonをインストールします。
$ pip3 install --upgrade setuptools $ pip3 install adafruit-blinka
次に、Adafruitのライブラリをインストールします。
$ pip3 install adafruit-circuitpython-pca9685 $ pip3 install adafruit-circuitpython-servokit
これで準備は完了です。試しに、サーボモータをボードに接続して動かしてみます。上下方向に動かすサーボモータをチャネル2に接続し、左右方向に動かすサーボモータをチャネル3に接続します。
プログラムは下記の通り、「kit.servo[チャネルNo.].angle = 角度(°)」とするだけなので簡単ですね。
import time from adafruit_servokit import ServoKit kit = ServoKit(channels=16) ######################### # Up & Down ######################### kit.servo[2].angle = 0 time.sleep(1) kit.servo[2].angle = 90 time.sleep(1) kit.servo[2].angle = 180 time.sleep(1) kit.servo[2].angle = 90 time.sleep(1) ######################### # Left & Right ######################### kit.servo[3].angle = 45 time.sleep(1) kit.servo[3].angle = 90 time.sleep(1) kit.servo[3].angle = 135 time.sleep(1) kit.servo[3].angle = 90 time.sleep(1)
Blynkで遠隔操作
ここまでで、サーボモータをプログラムで制御できる状態になりました。しかし、制御するたびにコードを書いてられないので、スマホで制御できるようにしましょう。使用するアプリは、Arduinoでも使用したBlynkです。ライブラリは、以下のコマンドでインストールしてください。
$ git clone https://github.com/vshymanskyy/blynk-library-python.git $ cd blynk-library-python $ sudo pip3 install .
BlynkアプリとスマホをWiFiで接続し、JOYSTICKを配置します。設定は、「MERGE」で、値の範囲を-100~+100にします。「WRITE INTERVAL」は100msにします。
Pythonプログラムは、下記のとおりです。BLYNK_AUTHは、ご自身の認証トークン(Auth Token)に書き換えてください。
Adafruitのサーボライブラリを読み込んで、角度制御に使用する変数を初期化しています。angleXとangleYは、Joystickで動かす角度です。ki.servo[*].angle=90で、サーボの初期角度を90°とし、カメラが真正面を向くようにセットします。
次に、Blynkライブラリの読み込みとタイマーライブラリを読み込みます。limit関数は、サーボモータが回りすぎないように、角度の上限と下限を決めています。Joystickの値は、v1_write_handlerで取得しています。Joystickが-30~+30の範囲のときは「不感帯」とし、その範囲を超えている場合は、angleX, angleYの値を+4または-4にします。
panTiltMoveは、今のサーボ角度から、angleX, angleYの角度で回転させたときに、角度の上下限を超えていない場合は回転し、角度の上下限を超える場合は回転させないように、limit関数で制限しています。
timer.set_intervalでは、0.1秒(100ms)ごとに、panTiltMoveを実行するようにしています。この100msというのは、Blynkで設定したインターバルの100msに合わせています。
BLYNK_AUTH = 'xxxxxxxxxxxxxxxxxxx' from adafruit_servokit import ServoKit kit = ServoKit(channels=16) angleX = 0 angleY = 0 kit.servo[3].angle = 90 kit.servo[2].angle = 90 import BlynkLib from BlynkTimer import BlynkTimer blynk = BlynkLib.Blynk(BLYNK_AUTH) timer = BlynkTimer() def limit(value, lower, upper): if value < lower: value = lower elif value > upper: value = upper return value @blynk.on("V1") # Joystick def v1_write_handler(value): global joystick_mode, angleX, angleY joystickX = int(value[0]) joystickY = int(value[1]) # PanTilt if joystickX > 30: angleX = 4 elif joystickX < -30: angleX = -4 else: angleX = 0 if joystickY > 30: angleY = 4 elif joystickY < -30: angleY = -4 else: angleY = 0 print("angle {} {} ".format(angleX,angleY)) def panTiltMove(): global angleX, angleY kit.servo[3].angle = limit(kit.servo[3].angle - angleX, 45, 135) kit.servo[2].angle = limit(kit.servo[2].angle - angleY, 45, 135) # Define Timers timer.set_interval(0.1, panTiltMove) # 100ms while True: blynk.run() timer.run()
最後に
これでカメラの向きを自由自在に操れます。しかし、操るだけでは、本当に向けたい向きにカメラが向いているかどうかわかりません。やはり、カメラに写っている映像をリアルタイムで確認して、カメラの向きを制御したいですよね。次回は、その方法について記事を書きたいと思います。
(参考にしたサイト)
https://intellectualcuriosity.hatenablog.com/entry/2020/03/16/053146
コメントを残す