Raspberry PI 5でロボットカーを操作1:ハード設定と確認
RASPBERRY PI 5で簡単なロボットを動かすことを実施してみます。いずれこれで強化学習を実施してみたいと思います。
まず最初はなるべく安く実験するため、RASPBERRY PI以外は安価なものでやってみようと思います。
ラズベリーパイにOSをインストールする際に必要なもの
こちらを参考にしてみてください
必要なもの
- PC (Ubuntuをインストールできるもの)
できれば一定時間無線で稼働できるよう電池付きのWIFI通信できる軽量なもの推奨 - ラズベリーパイ 5 (4やそれ以前でも基本は大丈夫かと思います。)
- ジャンパーワイヤ (一応、M-M,M-F,F-Fすべてそろえたほうがいいかもしれません)
- 2輪駆動 三輪スマートカー車体キット

* モータドライバ
私はMX1508を使いましたがはんだづけが大変でした。

もしはんだずけなしで上記のジャンパーワイヤで済ませたい場合、ほんの少し値段はあがりますがTB6612FNGなどピンで固定できるようなもののほうが作業ははかどるかもしれません。

ただ、結構組み立て中に線が外れたり切れたりとあるのではんだずけは慣れていたほうがいいかもしれません。
あるといいもの
- はんだごてとはんだ
仕様部品によっては必須、安価なロボットだとちょっとしたことで配線が外れるのでもっておくことをお勧めします。私も2輪のモータについていた線が3度切れて結局付けなおしをしています。 - 電流、電圧計測器
思うように動かないときどこで問題が起きているか判断がしやすくなります。 - 小型バッテリー
ある程度の範囲でうごかすとき、電源コードを気にせずバッテリーがあったほうが自由に動かせます - WIFIスイッチ
これも同様ですがラズベリーパイはWIFIで接続すれば操作用のPCとの通信(SSH接続など)がやりやすくなります。 - フォトインタラプタ
モータのエンコーダーカウントをしてなるべく低速で走るように制御します。
GPIOと回路の接続
下記のように接続します。
テーブルの1列名の物理番号はUSBがあるほうから見て基盤端子の1列目:左、右、2列目:左、右で順に
カウントされます。例えば物理ピンが11は6列名の右、テーブルの2列目は記述ですがその中でGPIOとあるのはPYTHONの中でして電流を流すときに指定するピンの番号です。


詳細な仕様は英語ですが以下のラズベリーパイの公式ドキュメントに記載がありますので、ピンの場所を変えたい場合などはこれを参考にしてください。(流す電圧や電流には十分注意を!家事にはならないだろうけど最悪ラズパイは壊れる可能性あり)


さてそれぞれの接続が機能しているかをチェックします。
よくあるのはピンがしっかりはまってない(私は左のタイヤが後ろに回転するのに前に回転せず散々苦労して確認したら、単純にピンに差し込まれてなくピンとピンの間に挟まっていただけでした。)別のとこに接続している。
あと電子工作初心者のためにフォトインタラプタの設定方法を記載します。
以下ののようにタイヤのわきにつけた無数に窓ができた輪を挟むように差し込みます。こうしてその光の遮りからカウントしていくようです。


製作した全体像は以下のようです。USBのカメラもとりつけました。まだ配線をまとめたり、外付け電池をつけたり、場所の準備などができてないですがとりあえず動かせそうなとこまでできました。



それではタイヤ走行のテストと、フォトインタラプタによる車輪回転カウントのテストコードを走らせていきます(上記の写真のようにタイヤを空中の浮かせて回るかどうかだけテストしています)。モータの走行テストはgpiozeroのライブラリのPWMというものを利用します。PWMとは
「ONとOFFを超高速で切り替えて、平均の強さを作っている」仕組みです。ここでは50%(=半分の時間)だけONですがもちろん100%(=常にON),0%(=常にOFF)となります。基準は 電圧ですがこの場合はGPIOの 3.3Vにつないでいるのでそこのオン、オフ比率を制御することになります。そしてこのON/OFFを繰り返す周期を1秒で何回繰り返すかが周波数になります。ここでは60にしてます。
これはここではGPIO18→左モータ:IN1, GPIO17→左モータ:IN2を前提にします。
ON-OFFのセットでON比率50%を1セットとしてこの電圧ON-OFFを1秒に60回繰り返します。
下のコードで左タイヤ(もし回路の接続点がIN1,IN2でなくIN3,IN4であれば右タイヤ)
が前進を5秒、後進を5秒します。
まずインストール
# apt install python3-lgpio
# apt install python3-venv python3-pip
# python3 -m venv devicetest
# source devicetest/bin/activate --system-site-packages
(devicetest)$ pip install gpiozero
そして左のタイヤから動作確認
from gpiozero import PWMOutputDevice
from time import sleep
MOT_L_1 = PWMOutputDevice(pin=18, frequency=60) # 左IN3(例)
MOT_L_2 = PWMOutputDevice(pin=17, frequency=60) # 左IN4(例)
# 前進
MOT_L_1.value = 0.5
MOT_L_2.value = 0.0
sleep(5)
# 停止
MOT_L_1.value = 0.0
MOT_L_2.value = 0.0
#ちょっと待ってから
sleep(1)
# 後進
MOT_L_1.value = 0.0
MOT_L_2.value = 0.5
sleep(5)
# 停止
MOT_L_1.value = 0.0
MOT_L_2.value = 0.0
同様にもう片方もチェックしておきます
(devicetest) root@takeo-rp:/opt/devicetest# cat motor_drive_rfb.py
from gpiozero import PWMOutputDevice #RaspiのGPIOを使うためのライブラリ
from time import sleep
MOT_R_1 = PWMOutputDevice(pin=23, frequency=60) #GPIO23 右IN1
MOT_R_2 = PWMOutputDevice(pin=22, frequency=60) #GPIO22 右IN2
# 前進
MOT_R_1.value = 0 #duty50%でPWM出力
MOT_R_2.value = 0.5
sleep(5)
# 停止
MOT_R_1.value = 0 #PWM出力停止
MOT_R_2.value = 0
sleep(1)
# 後進
MOT_R_1.value = 0.5 #duty50%でPWM出力
MOT_R_2.value = 0
sleep(5)
# 停止
MOT_R_1.value = 0 #PWM出力停止
MOT_R_2.value = 0
次に、走行を安定させたりするためにいろいろあって
* いいロボットやセンサー、制御装置を買う
* きちんと製作する。
* 物理的なキャリブレーション
* ソフトでのキャリブレーションと補正
が必要だと思いますが、予算と自分の手先の不器用さと経験の浅さから今は目をつぶります。
また次に物理的なキャリブレーションをする予定ですが実際に走行を安定させるためにエンコードでモータ回転を補正するためのカウントをとります。
以下のようなコードを走らせ先ほどの回転コマンドを打つか、手で回すことでカウントがアップします。
from gpiozero import Button
def enc_callback_R(): #右側割り込み関数
global count_R #グローバル変数count_Rを使う
count_R += 1 #カウントアップ
print('R= ' + str(count_R)) #画面出力
def enc_callback_L(): #左側割り込み関数
global count_L #グローバル変数count_Lを使う
count_L += 1 #カウントアップ
print('L= ' + str(count_L)) #画面出力
# encoder settings
ENC_R = Button(10, pull_up=True) #GPIO10
ENC_L = Button(2, pull_up=True) #GPIO2
count_R = 0 #エッジカウント
count_L = 0 #エッジカウント
#ENC_Rの両エッジ検出
ENC_R.when_pressed = enc_callback_R
ENC_R.when_released = enc_callback_R
#ENC_Lの両エッジ検出
ENC_L.when_pressed = enc_callback_L
ENC_L.when_released = enc_callback_L
try:
while True:
pass
except KeyboardInterrupt:
print("stop")
実際上記のコマンドを実施して、手でタイヤを動かしました。タイヤを動かすと同時にカウントがアップしていきます。(手でゆっくりと回しても以下のようにアップしていきます。上記のコマンドで動かすとすごい勢いでカウントアップされます)
(devicetest)$ python encoder.py
R= 1
R= 2
R= 3
R= 4
R= 5
R= 6
R= 7
R= 8
R= 9
R= 10
R= 11
R= 12
R= 13
R= 14
R= 15
R= 16
R= 17
R= 18
R= 19
R= 20
R= 21
R= 22
R= 23
L= 1
L= 2
L= 3
L= 4
L= 5
L= 6
L= 7
L= 8
L= 9
L= 10
L= 11
L= 12
L= 13
L= 14
L= 15
L= 16
L= 17
L= 18
L= 19
L= 20
L= 21
最期にUSBで接続したカメラがどのデバイスに対応しているか確認しておきます。
もしユーティリティがインストールされていなければインストールします。
あとPYTHNからはOpenCVを使うためOpenCVももしインストールされてなければインストールしておきます。
# apt install v4l-utils
# apt install python3-opencv
その後、lsusbとこのユーティリティーコマンドを使って認識ができているか確認します。
# lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 0c45:6366 Microdia Webcam Vitade AF
Bus 003 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 004 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 005 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
# v4l2-ctl --list-devices
pispbe (platform:1000880000.pisp_be):
/dev/video20
/dev/video21
/dev/video22
/dev/video23
/dev/video24
/dev/video25
/dev/video26
/dev/video27
/dev/video28
/dev/video29
/dev/video30
/dev/video31
/dev/video32
/dev/video33
/dev/video34
/dev/video35
/dev/video36
/dev/video37
/dev/media1
/dev/media3
rpivid (platform:rpivid):
/dev/video19
/dev/media0
Innomaker-U20CAM-1080p-S1: Inno (usb-xhci-hcd.0-2):
/dev/video0
/dev/video1
/dev/media2
上のコマンドから、Bus 002 Device 002 でUSB WEBCAMが認識されており、さらに
/dev/video0 もしくは /dev/video1 のどちらかであると推定できます。
どちらなのか、確認コマンドを実行します。
(rosa) root@takeo-rp:/opt/rosa# v4l2-ctl -d /dev/video0 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture
[0]: 'MJPG' (Motion-JPEG, compressed)
Size: Discrete 640x480
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 1920x1080
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 1280x960
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 1280x720
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 1024x576
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 800x600
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 640x360
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 640x480
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.033s (30.000 fps)
[1]: 'YUYV' (YUYV 4:2:2)
Size: Discrete 640x480
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 1920x1080
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 1280x720
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 640x360
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 640x480
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.033s (30.000 fps)
(rosa) root@takeo-rp:/opt/rosa# v4l2-ctl -d /dev/video1 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture
以上ですが、次回は実際に走らせてみたいと思います。どうなることやら
(参考文献) 中村俊幸著: 趣味のロボット制作 ROS2入門編
Discussion