そのボード、僕が積んでおきます。

たくさんの電子工作基板が積みっぱなしになってるので、頑張って工作しようとしていますが、どんどん溜まっていっております。

ScratchからBezelieを動かしちゃう

このエントリーは、QiitaのRobot/ロボット Advent Calendar 2016の12月20日分のエントリーです。


 さて、一昨日の豊田さんのエントリー昨日の高橋くんのエントリーを受けて、何を書こうか非常に迷ったのだけど、今年はやはりこのネタで締めくくるべきだろうと思い、「Scratchからロボットを動かす」ことにしました。

 今年のアクティビティだけでも見ても、西田さんと太田さんの作った同人誌でもScratchでロボットを動かすことについて書き、月刊I/OV-Sidoの連載でもScratchからくまちゃんのロボットを操り、様々なイベントにScratchとロボットで遊びに行きました。今年の締めくくりはやっぱり「Scratchとロボット」であり、せっかくのバトンだし、豊田さんのエントリーを引き継いで、ScratchからBezelieを動かすことにします。
f:id:hine:20161220015430j:plain

Scratchと通信する

 Scratch(1.4)には、遠隔センサー接続(Remote Sensor Connection)という仕組みがあります。これは、ソケット通信でセンサー情報などをやる取りする仕組みで、(隠されてはいる機能ですが)Scratchのメッシュという通信の基礎ともなっているものです。

 Scratchの遠隔センサー接続のプロトコルはRemote Sensor Protocolというそのままの名前なのですが、仕様を見ると非常にシンプルでわかりやすい仕組みとなっています。
Remote Sensors Protocol - Scratch Wiki

 ただ、以前僕が探したときは、Python向けの気に入った実装がなかったため、とりあえず僕が個人でPython向けのライブラリを実装してしまいました。


Python3.x向け実装
github.com


Python2.7向け実装(上記の別ブランチ)
github.com


 今回もこちらを使います。先日の豊田さんのエントリーがPython2.7向けて書かれていたようなので、2.7版を利用します。


 今回は、このブランチから必要なファイルをコピーして持って来てしまいましたが、正しくは、上記の2.7向けブランチを

$ git clone -b 2.7 https://github.com/hine/pyscratch.git

して、その上でそのディレクトリで、

pip install ./

すれば、pyscratchライブラリはインストールされます。使い方はREADME.mdを御覧ください。

Bezelieを動かす

 今回のコード一式はこちらです。
github.com


 今回Bezelieは、一昨日の豊田さんのエントリーをそのまま利用できるよう、RaspberryPiとPCA9685を利用して接続します。ちょうど手元に、RaspberryPi3と中国製の基板があったので、そのまま利用しました。

 Bezelieを動かすコードはbezelie.pyとファイル名は豊田さんのエントリーそのままですが、今回Classにさせていただきました。コードはほとんどそのままコピペです。

import bezelie
bez = bezelie.Control()
bez.setTrim(head=0, back=0, stage=0)
bez.moveCenter()

などとして動かすことができます。

Scratchとつなぐ

 今回は、レポジトリの中に、pyscratchレポジトリからscratch.pyをコピーして持ってきてしまいました。

 こちらの使い方は若干クセが有り、

import scratch
def broadcast_handler(message):
    pass
def sensor_update_handler(**sensor_data):
    pass
rsc = RemoteSensorConnection(broadcast_handler, sensor_update_handler)
rsc.connect()

のように、メッセージなどを受け取った時のハンドラなどを用意して、それを引数として渡してあげます。


 実際にこちらのプログラムを動かす前に、接続されるScratch側で作業が必要となります。

 Scratchを立ち上げ、左上のブロック種類から「調べる」を選択し、下のブロック一覧の一番下の「○○センサーの値」のブロックを右クリック、「遠隔センサー接続を有効にする」を選びます。
f:id:hine:20161220012009p:plain
こうすることで、Scratchの遠隔センサー接続が利用できるようになります。


 今回、プログラムを動かすのはRaspberryPi上です。RaspberryPiにもScratchが搭載されていますので、HDMIのモニタなどにつなぎ、デスクトップでScratchを起動させて、上記の作業を行ってください。

 一方で、僕のようにRaspberryPiをディスプレイに繋がずに利用している人も多いかと思います。その場合は、同一ネットワーク内の他のマシンで動かしている(例えば手元のMacWindowsで動かしている)Scratchに接続させることもできます。その場合は、接続したい先のIPアドレスを調べて、

rsc.connect(host='192.168.11.1')

などと、IPアドレスを指定してください。

いよいよScratchからBezelieを動かす

 上記の2つのライブラリを用いて今回作ったのがscratch2bezelie.pyです。

実行は

python scratch2bezelie.py

もしくは

python scratch2bezelie.py '192.168.11.1'

などと、接続先のIPアドレスを指定してください。

問題がなければ

Connected to Scratch on 192.168.11.1

などのように表示されますので、その後は、Scratch側の作業となります。


今回は2つの方法でBezelieを動かせるようにしました。


 一つは、「broadcast」を用いた方法です。制御ブロックの「○○を送る」ブロックを用いてメッセージを送る方法です。ここで、メッセージに「bezelie:move:head:10」を指定すると、頭の角度位置10の位置に頭が移動します。同様に「bezelie:move:back:10」で身体が、「bezelie:move:stage:10」でステージが動きます。
f:id:hine:20161220014122p:plain
この方法は、数値が値になるとは限らないもの、例えば「何かを話せ」みたいなコマンドを用意したい場合には「bezelie:talk:何か」などというコマンドを作ることなどに応用できます。


 もう一つの方法は、グローバル変数の変更イベント「sensor_update」を受け取る方法です。この方法は、変数ブロックで新し変数としてすべてのスプライト用(グローバル変数)で「bezelie:head」「bezelie:back」「bezelie:stage」を作成し、変数変更ブロックなどで値を変化させる方法です。
f:id:hine:20161220014536p:plain
こちらは、数値の変化しかない情報の受け渡しに便利な方法です。例えば、LEDの光の強弱、音声のボリュームなどにも応用できそうです。


ここまでくれば、あとはScratchで遊ぶだけです。

Scratchでできること

 ご存知、Scratchはビジュアル言語です。今回のエントリーを読んで理解できるようなPythonでプログラムを書ける人にとっては、Pythonを使ったほうがいろいろな事ができます。しかし、Scratchは子ども向けの多くのプログラミング教室などで使われており、「Scratchならわかる」という子も少なくありません。ScratchからBezelieがコントロールできるようになることで、子どもたちが比較的低価格なロボットをプログラミングする手法を手に入れることができるのです。


ぜひ、子どもたちと一緒にBezelieで遊んでみてください。