カメラのパン・チルト(上下・左右方向に首を振る)をサーボモータ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


コメントを残す