micro: Maqueen の解析

micro: Maqueen は micro:bit を載せて走らせることのできるロボットプラットフォームである。DFROBOT社製で、 SWITCH SCIENCE から3,000円強で購入することができる。ちなみに、組み立て方その他はこのページに掲載されている。

中に入っているもの
組み立てたもの

プログラミングには、Scratch 3.0 をベースにした MIND+ というものを使うらしいが、githubにある拡張モジュールを使って、Microsoft MakeCode でプログラミングすることもできる。

とはいえ、MicroPython でも使えないことはなかろうと、いろいろと調べてみた。結果的には(全ての機能ではないものの)使えることがわかり、さっそく micro:witch に取り込んでみた。(いずれ公開予定)

この記事では、micro: Maqueen の各種デバイスをどのように制御するかについて調べたことをまとめる。元ネタは先ほどの拡張モジュールのソースファイル(maqueen.ts)である。


GPIO関係

ありがたいことに Maqueen のボード上には、デバイスの横にP8 のようにシルク印刷されている。まさに、左前の赤いLEDがP8と書かれているのだが、これは micro:bit のpin8に接続されていることを意味するので、プログラムから適切にアクセス(Pythonなら pin8.write_digital(1) のように)すれば、LEDが光る。

裏面にはライントレース用のフォトリフレクタがあるが、左側はP13と書かれており、 pin13 に接続されていることがわかるので、Python ならば pin13.read_digital() で値を取得できる。

項目ピン番号入出力備考
左前LED8出力1でオン
右前LED12出力1でオン
左フォトリフレクタ13入力反射があれば1
右フォトリフレクタ14入力反射があれば1

DCモータ

左右のDCモータはi2cバスを使って接続されている。デバイスのアドレスは 0x10 である。モータを扱うには3バイトのデータを書き込む必要がある。

最初のバイトは左右のモーターの区別で、M1なら0x00、M2なら0x02を指定する。(左右のどちらがM1, M2だったか忘れた。後で記載する)

2番めのバイトは回転方向で、前転なら0x00、後転なら0x01を指定する。(左右のモータは逆向きに付けられているが、同じ値の指定で前進・後退する)

3番めのバイトは回転スピードで、0から255の値を指定する。

バイト位置意味備考
0モータ指定M1=0x00, M2=0x02
1回転方向前転=0x00, 後転=0x01
2回転スピード0から255までの整数値

モータを使って戸惑ったのは、モータを回転させている途中で回転方向を切り替えても反応しないということだった。何らかの理由で回転の指示がキャンセルされてしまう。いったん回転スピードを0にして止めてから100msほど待てば、逆回転させることができた。

サーボ

ボードにサーボを取り付けることができるらしく、これもi2cバスで接続されているらしい。(まだ使ったことがない)資料によると、2バイトのデータを書き込むことでサーボを制御できるようだ。(動作未確認なので注意)

バイト位置意味備考
0サーボ指定S1=0x14, S2=0x15
1角度0から180までの整数値

フルカラーLED

ボード上にはフルカラーLEDが4つある。ただ、先の資料には記載がなく、使い方はよくわからない。NeoPixel として使えるのかも。余裕があれば調べる予定。

Hyper Keyboard pi のタッチパネル補正

ラズパイにキーボードと液晶を一体化させる Hyper Keyboard pi を手に入れた。ちょっと時間があったので作ってみたら、いくつか注意点があったので備忘として残しておく。

いろいろ書いているけど、Hyper Keyboard pi は素晴らしいです。ラズパイの使い勝手が高まります。個人的にはマストバイと思っています。

説明書は最後まで読んで取り組むべし

基本的に説明書を読んで作っていけばいいのだけど、ところどころ先に読んでおけばよかったなあということがあった。例えば、「カプトンテープって何だ?家にはないぞ。買わないと」のようなものだったり、「2枚の基板を組み上げる前に予備ハンダしとかないと後で辛いぞ」みたいなものだったり。これに限らず場当たり的に作るのが問題なのだけれど。

底板をつける前に MicroSD カードを刺す

底板を付けた後だと、ピンセットで差し込まなきゃならないことになる。

起動してもディスプレイが表示されない

HyperPixel4 で表示させるには当然のことながらドライバのインストールが必要。つまり、それまでは外部ディスプレイがないとダメ。事前に用意しよう。

ディスプレイの上下がさかさま

説明書にも書いてあるが、単にドライバインストールしただけではディスプレイの上下が反転してしまう。(正確には180度回転する)そのため、github に書かれた手順を行う必要がある。具体的には大したことなくて、「180 Degree Rotation」の通りにすれば良い。

タッチした場所にカーソルがこない

これにはまいった。画面をタッチするととんでもないところにカーソルが行ってしまう。xinput-calibrator とかインストールして設定してみても効果なし。いろいろググった末に、この issue にたどりついた。

要するに、 github でクローンしたソースファイルの一部を書き換える必要がある。具体的には、 src/hyperpixel4.dts を修正して、

         touchscreen-size-x = <800>;
         touchscreen-size-y = <480>;

         touchscreen-size-x = <480>;
         touchscreen-size-y = <800>;

にしてから、make & copy する必要がある。これでタッチの問題は解決する。

ヒートシンクは早めに設置

ラズパイの熱暴走の予防にヒートシンクをつけるなら底面の配線の前にした方がいい。すっかり忘れてラズパイを外そうとしたら、液晶から外せないくらい配線をきっちりしたせいで、ピンセットで取り付けるハメになった。ラズパイへの配線には余裕を持たそう。

PharoからCで書いたプログラムを呼び出す(その2)

これはSmalltalk Advent Calendar 2018の記事です。

前回の記事でPharoからCのプログラムを呼び出す方法について説明しました。今回もその続きで、UFFIというメカニズムを使った外部インターフェイスについて説明します。

さて、数値のような単純なデータを渡すのは簡単ですが、配列のようなデータを受け渡すには少し注意が必要です。例えば次のようなC関数を考えます。

double fsum(double *list, int n)
{
double result = 0;
for (int i = 0; i < n; i ++) {
result += list[i];
}
return result;
}

double型の要素をn個持つ配列を引数で得て、その和を求めるような場合、Pharo 側では少し工夫しなければなりません。

まず、Cの関数を呼び出すメソッドを定義します。

fsum: anArray size: anInteger
^ self ffiCall: #(double fsum #(FFIExternalArray anArray , int anInteger)) module: UFFITestLibrary

配列のパラメータを指定する部分以外は前回の記事と変わりありません。double型の要素を持つ配列を受け渡す場合には、FFIExternalArray という型を明示的に指定します。また、このメソッドが使われる時には、anArray に FFIExternalArray クラスのインスタンスが指定される必要があります。

fsum: anArray
| size arr |
size := anArray size.
^ [ arr := FFIExternalArray externalNewType: 'double' size: size.
1 to: size do: [ :i | arr at: i put: (anArray at: i) ].
self fsum: arr size: size ]
ensure: [ arr free ]

#externalNewType:size: というメッセージを使って FFIExternalArray のインスタンスを作成します。そのオブジェクトに受け渡したい要素を一つずつ設定してから、先程のメソッドを使います。使い終わったところで、作成した FFIExternalArray のインスタンスを開放します。

Cの関数の中で配列の要素に変更を加えるような場合も似たような形となります。配列の各要素を定数倍する関数を考えてみます。

void fmultiplyBy(double *list, int n, double x)
{
for (int i = 0; i < n; i ++) {
list[i] *= x;
}
}

この関数を呼び出す Pharo のメソッドは以下のようになります。

fmultiply: anArray size: anInteger by: x
^ self ffiCall: #(double fmultiplyBy #(FFIExternalArray anArray , int anInteger , double x)) module: UFFITestLibrary

上のメソッドを使うために FFIExternalArray のインスタンスを作って渡すメソッドを用意します。

fmultiply: anArray by: x
| size arr |
size := anArray size.
[ arr := FFIExternalArray externalNewType: 'double' size: size.
1 to: size do: [ :i | arr at: i put: (anArray at: i) ].
self fmultiply: arr size: size by: x.
1 to: size do: [ :i | anArray at: i put: (arr at: i) ] ]
ensure: [ arr free ]

要するに FFIExternalArray インスタンスから要素を一つずつ取り出して元の配列を変更するわけです。

以上が配列などのデータを受け渡す場合の方法となります。

残念ながら大きな配列のやり取りの場合だと、要素の出し入れに余計なコストがかかるぶん効率は良くありません。特に今回のような例では、以下のようなコードの方がずっと早いです。

a := #(1 2 3 4) asFloatArray.
a *= 2.
a.

こちらは FloatArrayPlugin という VM プラグインを用いており、C言語の関数側で配列の処理を行っています。

PharoからCで書いたプログラムを呼び出す

これはSmalltalk Advent Calendar 2018の記事です。

ごく稀にPharoから外部のプログラムを呼び出して使いたいことがあります。以前は外部プログラムを呼び出す仕組みが毎年のように変わっていたため、ちょっとご無沙汰していると置いてけぼりを食らうことが多々ありました。

最近では UFFI という仕組みで落ち着いた感がありますが、Pharo のことなのでまた変わってしまうのでしょう。

この記事では UFFI を使って Pharo から C で書いたプログラムを呼び出す方法を簡単に説明します。

Cプログラムの準備

まずは、C言語のプログラムを用意しておきましょう。普段 Linux を使っているので、Linux (64bit) を例に説明します。おそらく、mingw を使えば Windows でも同じようにいけるはずです。

int doublenumber(int n)
{
return n * 2;
}

上記のようなプログラムを用意します。ファイル名は uffitest.c とします。内容は整数を2倍する doublenumber 関数を定義しているだけです。

このプログラムをコンパイルして共有オブジェクトを作ります。

gcc -fPIC -shared -o uffitest.so uffitest.c

カレントディレクトリに uffitest.so というファイルができます。

UFFITestLibrary クラスの作成

Pharo を起動します。ここでは Linux 版のPharo6.1 のイメージを 64bit VM で起動したものとします。UFFILibrary クラスを継承した UFFITestLibrary クラスを作成します。

FFILibrary subclass: #UFFITestLibrary
instanceVariableNames: ''
classVariableNames: ''
package: 'UFFITest'

このクラスで外部のプログラムとの結びつきを定義します。そのためにメソッドを追加します。このメソッドはインスタンスメソッドとして登録します。

unixModuleName
^ 'uffitest.so'

このメソッドで先程作った uffitest.so ファイルのありかを示します。イメージと同じ場所にあるならパス指定は不要なようです。

他のOSで使う場合には別のメソッド名を用います。Mac OS Xならば macModuleName とし、Windows ならば win32ModuleName を使います。Windows は 32bit VM しか公開されていないので、先程の共有ライブラリも32btにする必要がありそうです。

外部プログラムを呼び出すメソッドの追加

doublenumber 関数を呼び出すメソッドを追加します。どんなクラスに書いてもいいのですが、ここではテストのため UFFITest クラスを作成してメソッドを登録します。

Object subclass: #UFFITest
instanceVariableNames: ''
classVariableNames: ''
package: 'UFFITest'

何の変哲もない Object クラスを継承したクラスです。このクラスのインスタンス側に doubleNumber: というメソッドを登録します。このメソッドは引数を1つ取り、その2倍の値を返します。

doubleNumber: anInteger
^ self ffiCall: #( int doublenumber (int anInteger)) module: UFFITestLibrary

このメソッドは #ffiCall:module: というメッセージを送るだけのものです。第一引数には C言語の関数プロトタイプ宣言のような形式で、呼び出す関数を指定します。また、第二引数には共有オブジェクトを定義したクラス名を指定します。

試してみる

以上で準備は完了しました。実際に使ってみましょう。Playground を開いて以下のように入力します。

UFFITest new doubleNumber: 10. 

Go を押せば結果(20)が得られます。

エラー?

External module not found というエラーメッセージが出ることがあります。これは、適切な共有オブジェクトファイルが見つからなかった時に現れます。Pharo のイメージファイルと同じディレクトリにファイルがあるか、32bit VMなのに64bitのオブジェクトファイルになっていないか、UFFITestLibrary クラスのメソッドが間違っていないかなど、確認してください。

おわりに

どうだったでしょうか?簡単にC言語の関数を呼び出せることがわかったと思います。C-API を持っているライブラリを活用する助けになれば幸いです。


micro:witch アルファ版公開

スクラッチ風のブロックプログラミング環境で micro:bit のプログラムを作成できるmicro:witch を公開しました。

https://github.com/EiichiroIto/microwitch

ドキュメントもなく、日本語化もされておらず、(ほぼ)何のテストもしていません。そのつもりでお使いください。

[2018/7/6追記]

現在は日本語化済みです。地球儀マークで「日本語」「にほんご」のいずれかを選べば日本語表示となります。

また、micro:witch 上での micro:bit のエミュレーションも不完全です。LEDとボタン程度しかまともに動作しません。

Windows 10での動作を確認しましたが、他にも動作の確認(動作しない確認でも)を行っていただけたなら twitter の投稿に返信くださると助かります。

アカウント: https://twitter.com/razdan3

[2018/6/29追記]

Windows で簡単に動かせるように必要なファイルをすべてパッケージしたので、github からダウンロードしたらすぐ利用できます。

Windows 用の簡単なインストール方法だけ載せておきます。

  1. Scratch のサイトから WinMacScratch1.4.zip をダウンロードしてください。
  2. 適当なフォルダに展開してください。
  3. 展開したフォルダにある、Scratch.image ファイルを削除してください。
  4. 上の github.com サイトで公開している、 microwitch.image, microwitch.changes, Microwitch.dll の3つのファイルをダウンロードし、先ほどのフォルダにコピーしてください。

以上です。

micro:bit が外部ドライブとして見えている状態なら、Microbit メニューからプログラムを送信できるはずです。

なお、「緑旗が押されたら」のHATブロック以降しかプログラム送信・実行しませんのでご注意ください。

 

micro:bit で遊んでみた

冬休みの自由課題として micro:bit で遊んでみた。

http://microbit.org/ja/

モジュールは秋月電子で購入した。

http://akizukidenshi.com/catalog/g/gM-12513/

最初の起動

PCと micro:bit とを USB-Micro USB のケーブルで接続すると、自動的に起動してメッセージ(Hello.)が表示される。

その後、左ボタン(A)と右ボタン(B)を押すように促される。さらに SHAKE と表示されるので micro:bit を振る。

次にCHASEの表示の後で点滅する赤いLEDが現れる。micro:bit を傾けると点灯するLEDが動くので、適当に傾けて点滅するLEDに重ねる。2回ほど行うと「GREAT NOW GET CODING!」表示されたあと、LEDのアニメーションが延々と続く。

JavaScript ブロックエディタ

自分でプログラムを作って micro:bit に転送することができる。micro:bit のサイトには何種類かの方法が提示されている。

http://microbit.org/ja/code/

一番手っ取り早いのはJavaScriptブロックエディタで、いわゆる Scratch 風のブロックプログラミングができる。

ブラウザに Scratch 2.0 風の配置の編集画面が表示される。中央のパレットから右側のブロックエリアにドラッグ&ドロップでブロックを配置していく。「最初だけ」や「ずっと」の中にブロックを配置していけば Arduino のようなプログラムを作れる。上部にある JavaScript ボタンを押せば JavaScript のコードに変換して表示される。

秀逸なのは、ブロックを編集するたびに左側に表示されている micro:bit でプログラムの動作がシミュレート表示されることだ。音関係のブロックを取り出すと、どのようにスピーカーに配線するかも図示される。

プログラムを micro:bit に転送するには「ダウンロード」ボタンを押せばよい。拡張子が hex のファイルがダウンロードされるので、それを micro:bit に転送する。micro:bit はPCに接続すると外付けメディアとして認識されるが、ダウンロードした hex ファイルをそのメディアにコピーすることでプログラムが転送される。

オフライン版

JavaScript ブロックエディタはオンラインでしか利用できないが、Docker を用いてサーバー環境を構築すればオフラインでも利用できる(らしい。試していない)。

https://hub.docker.com/r/kadok0520/pxt-microbit/

Python エディター

micro:bit のサイトには Python のコードを入力できるエディタもある。

画面に Python コードを入力するだけ。Download ボタンを押して hex ファイルをダウンロードするのは JavaScript ブロックエディタと同様である。

micro:bitで利用できるのは MicroPython で、どんな機能が使えるかは以下のサイトで確認できる。

http://microbit.org/ja/guide/python/

いわゆるLチカは、こんな風に書ける。

from microbit import *

while True:
    pin0.write_digital(1)
    sleep(500)
    pin0.write_digital(0)
    sleep(500)

mu エディタ(MicroPython)

上の2つはいずれもブラウザ上のアプリとして micro:bit のプログラミングを行うものだったが、PCにインストールするタイプのものもある。mu エディタはPC上で MicroPython のプログラムを作ることができる。

https://codewith.mu/

Windows, OS/X, Linux 版が提供されている。Linux版をダウンロードすると、 mu-0.9.13.linux.bin のようなバージョン付きのファイルが得られるので、適当な名前に変更するかシンボリックリンクを作成する。また、実行形式のフラグを設定する必要がある。

Python エディターに似た画面が表示され、Python コードを入力できる。 Flash ボタンを使うと直接 micro:bit にプログラムを転送することができる。ただし、(おそらく) dialout のグループにユーザーを登録する必要がある。

mbed(C++)

arm Mbed cloud 上でも micro:bit のプログラムを作成できる。そのためには、アカウントを作成してサイトにログインしておき、以下のページを開く。

https://os.mbed.com/platforms/Microbit/

画面中程の右サイドバーにある「Add to your mbed compiler」ボタンをクリックすると、mbed のアカウントに micro:bit 用のコンパイラが追加される。同じページにある「microbit-hello-world」などのサンプルをインポートすれば、適当なサンプルを試すことができる。

その他

スマホやタブレットのアプリからも micro:bit のプログラムを作れるらしい。個人的には JavaScript ブロックエディタが使いやすいように思える。ゼミでは arduino を使っているが、価格の違いを差っ引いても来年度は micro:bit を使いたい衝動に駆られた。

Building a memory game with Blocの手習い(Chapter 3)

これはSmalltalk Advent Calendar 2017の記事です。

前回に引き続いて、Bloc のチュートリアルである Building a memory game with Bloc のChapter 3(Building card graphical elements) の内容をやっていく。

元ネタは
https://github.com/pharo-graphics/Bloc
の中にある、
http://files.pharo.org/books-pdfs/booklet-Bloc/2017-11-09-memorygame.pdf
である。

続きを読む →