LEGO Mindstome EV3のEV3 インタラクティブサーボモーターLをRaspberry Pi 4から制御する
概要
ネットワークを介し倒立振子を制御する実験を行うため、計算アーキテクチャを含むハードウェア構成の検討を実施した。
当初、インテリジェントブロック EV3とwifiを介し、接続されたエッジ計算デバイスからパラメータ読み取り/書き込みを実行する構成を検討。
EV3は計算資源が貧弱かつ通信速度も極めて低速であるため、200ミリ秒から500ミリ秒程度の制御周期しか実現できず、倒立振子の制御手段としては不適と判断し使用を断念。
次にRaspberry Pi Build HATを介して SPIKE™ Lアンギュラーモーターを制御する構成を検討した。
Build HATは公式ドキュメントを参照する事で、Python 3スクリプトから簡便にSpikeモータ制御並びにセンサ読み取りを実行できる。
他方で公式ドキュメントの実装例で確認できる様に、継続的にモータを回転させ続けるためにtime.sleepを用いる必要がある。
Spike Lアンギュラーモーターはモータ内部に実装されたマイコンを介してモータを制御する構造となっており、例えばモータにデューティー比を与える事で、回転状態を維持しつつ連続的に回転速度を制御するような運用は困難であり、用途との見合いで使用を断念した。
最後に、Raspberry Pi 4からWave Share Motor Driver HATを介してンタラクティブサーボモーターL(※以後「Lモータ」)を制御する方法を検討した。
Wave ShareはMotor Driver HAT向けのライブラリをを公開しており、加えてPython実装例を提供している。
加えて、Pythonモジュールpigpio、gpiozeroを利用し、Lモータのロータリーエンコーダから回転角度を読み取る事が可能である。
目的
Raspberry PI 4からEV3 Lモータを制御する。
インタラクティブサーボモーターLの詳細
インタラクティブサーボモーターLの概要
LEGO Mindstome EV3基本セットに2個同梱されているモータである。
Lモータの筐体にはロータリーエンコーダが内蔵されており、Raspberry Piのピンと結線することでPythonスクリプトから簡易に回転角度が取得できる。
また、Lモータは出力端子の仕様が解析されており、コネクタを介してLモータと接続できる配線を作成する事で、容易にRaspberry Piと接続する事ができる。
インタラクティブサーボモーターLのインターフェース
pin配置 | 機能 |
---|---|
1. モータ1 | Motor Driver HATのMA1またはMB1に接続 |
2. モータ2 | Motor Driver HATのMA2またはMB2に接続 |
3. GND | Raspberry PiのGNDに接続 |
4. +3.3VDC | Raspberry Piの3.3Vに接続 |
5. エンコーダA | Raspberry PiのGPIO_GEN[N]に接続 |
5. エンコーダB | Raspberry PiのGPIO_GEN[N]に接続 |
Pythonスクリプトの実装例
以下にgithubにアップロードしたスクリプトから、本投稿に関連する箇所を抜き出し解説する。
モータ制御
PCA9685モジュールをインストール
https://github.com/adafruit/Adafruit_Python_PCA9685
sudo pip install adafruit-pca9685
PCA9685モジュールをimportする
from modules.PCA9685 import PCA9685
PWMインスタンスを初期化
pwm = PCA9685(0x40, debug=False)
pwm.setPWMFreq(50)
motor_driver = MotorDriver()
pwm.setPWMFreq(50000000.0)
モータとのインターフェースはクラスへ切り出し
本実装例では回転方向を文字列として配列に定義した
direction = [
'forward',
'backward',
]
クラスに定義したメソッドを介してデューティ比を印加
motor_driver.MotorRun(pwm, 0, direction[direction_a], ua)
motor_driver.MotorRun(pwm, 1, direction[direction_d], ua)
MotorRunメソッド内で文字列forward/backwardを0/1に読み替え
ロータリーエンコーダ読み取り
gpio Zeroをimport
from gpiozero import RotaryEncoder
from gpiozero.pins.pigpio import PiGPIOFactory
エンコーダを初期化
factory = PiGPIOFactory()
rotary_encoder_a = RotaryEncoder(
PIN_ROTAR_A1, PIN_ROTAR_A2, wrap=True, max_steps=180, pin_factory=factory
)
rotary_encoder_a.steps = 0
rotary_encoder_a.when_rotated_clockwise = rotated_clockwise_a
rotary_encoder_a.when_rotated_counter_clockwise = rotated_counter_clockwise_a
エンコーダから相対角度を読み取り
rt_a_counter = rotary_encoder_a.steps
検証
オシロスコープで出力波形を確認
※キャプチャは事後投稿
最後に
インテリジェントブロック EV3の計算アーキテクチャは陳腐化しており、加えてev3devではPython 3.x系を利用する事は困難である。
過去事例としてev3devからROSを利用する試みもあったが引用記事の通り、様々な障害があり中断されている。
他方でEV3Lモータは内部にロータリーエンコーダを内蔵しており、市販のモータ、ロータリーエンコーダを組み合わせて同等の仕様を実現する手間を考えると、プロトタイピング等に際して簡単に高機能なモータを利用できるメリットがある。
以上の利点を考慮し倒立振子のハードウェア構成として、Raspberry Piならびに安価な市販のHATとLモータを組み合わせを選択した。