mblockの拡張機能を作ってみた
これは何?
mblockを触っていると、
拡張機能というのが使えるのを最近知りました。
makeblock社の製品や、arduinoなどのマイコンなどに接続する拡張キットを扱えるようにする追加のライブラリのようで、実は誰でもそのライブラリが作成できるようなので、今回作ってみたという話です。
Arduinoから、以前作った8x8LEDを動かすライブラリを作ってみます。
mblockとは?
scratchを拡張したビジュアルプログラミング環境で、
ビジュアルにプログラミングができて、mbotなどのmakeblock社製のマシンを操作することができます。
makeblock社が開発しています。サイトはこちら
ユーザ登録
mblockの拡張センターに拡張機能を作成というボタンがあるので、そこをクリックすると、mBlockのExtension Builderというサイトに飛ぶので、ユーザ登録をします。
オンラインヘルプは
登録後、ログインすると↓こんな画面(のハズ)
作るもの
作るのは、デバイスそのもの(Arduinoとか)ではなく、Arduinoにくっつけて制御するものなので、「My extension」というのになります。
1588BSというmatrix LEDです。↓下記をmblockから動かし(光らせ)ます。
パネル設定
8ドット×8ドットのマトリクスLEDなので、パネルを設定します。
便宜上「mono_eye」という名前をつけました。
↑だいたいこんな感じで設定しました。
なんとなく操作はわかるので省略
拡張設定
拡張機能を追加します、とりあえずDefault Arduino templateを選んで、名前を聞かれるので、8x8eyeとして作成。
対応デバイスの設定
この拡張が対応するデバイスを選択します。
今回はArduino UNOなのでそちらを選択します[1]
また対応するmblockのプラットフォームを選択します
mblock内のブロックの設定
Basic configurationのcontentの部分に「eye @」と入力、「@」を入れた時点で、ドロップダウン選択になるので、「LED Panel」を選択します。
変数が認識されると値が選べるので、さきほど作成した、mono_eyeを選択します
選択後は↓こんな感じ
同様に何秒間光らせるかという意味合いで、@でnumberを選択します。
saveを忘れずに。
拡張機能の適用方法とデータの入り方
ここで疑問にぶつかりました。
mblock上で、LEDパネルデータがどのように格納されるのか資料が探せなかったので、手探りで調べることに。。。
確認用に「code」ブロックに変数のバインディング[2]を設定します。
↑ちょっと癖のあるインターフェースで、ダブルクリックすると別画面にとんでそこで記述できる。
※この記載のままだとArduinoにはアップロードできません(コンパイルエラーになる)がmblockでブロックの操作や、どんなC言語ができるのかは見れるっぽい。
拡張(mextファイル)をダウンロード
mblockにmextファイルをドラッグ&ドロップ。
mblockを再起動して、拡張を追加します
拡張でブロックを構成してみます
作成されるCのコードを見ると、0と1で構成された、64文字の文字列が入っていました。
0010000001000100001000100000001000000010001000100100010000100000
※単色の場合なので、色を増やしたりするどうなるかなどは調べてません。
8文字ずつ区切ると、
列 | 文字列 | HEX |
---|---|---|
Col 1 | 00100000 | 0x20H |
Col 2 | 01000100 | 0x44H |
Col 3 | 00100010 | 0x22H |
Col 4 | 00000010 | 0x02H |
Col 5 | 00000010 | 0x02H |
Col 6 | 00100010 | 0x22H |
Col 7 | 01000100 | 0x44H |
Col 8 | 00100000 | 0x20H |
物理的なLEDマトリックと組み合わせると
Col 1 | Col 2 | Col 3 | Col 4 | Col 5 | Col 6 | Col 7 | Col 8 | |
---|---|---|---|---|---|---|---|---|
Row 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Row 2 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
Row 3 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 |
Row 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Row 5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Row 6 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
Row 7 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 |
Row 8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
HEX | 0x20H | 0x44H | 0x22H | 0x02H | 0x02H | 0x22H | 0x44H | 0x20H |
Row 8がLSB
C言語的な設定
ここまでわかれば後はなんとかなりそうです。
declare
で定数や関数の定義、setup
で初期化、code
で実際のプログラムを作る(っぽい)。
以下のようにしました。
declare
//シフトレジスタのピン設定
const int PIN_SER = 8;
const int PIN_LATCH = 9;
const int PIN_CLK = 10;
byte column[8];
byte zero[8];
/**
* 8文字列(01010101など)を1バイトに
*/
byte getByte(String target){
Serial.println(target);
byte result = 0;
for(int i=0; i<8; i++){
if(target.substring(i, i + 1)=="1"){
result += 1 << (8 - i - 1);
}
}
Serial.println(result, HEX);
return result;
}
/**
* 64 string '1000000001000000000000000000000000000000000000000000000000000000'
* 8文字づつ区切ってByteに変換
*/
void setBytes(String target){
for(int i=0; i<8; i++){
column[i] = getByte(target.substring( 8 * i, 8 * i + 8));
}
return;
}
/**
* ライトオン
*/
void lightOn(){
for(int i = 0; i < 8; i++){
byte Row = 0;
if(column[i]>0){
//点灯する場合は対応するRowもHighにする(※カソード側のためLowで出力です、ここではHighとしてシフトレジスタの出力時に反転(A))
Row = 1 << (8 - i -1);
}
//16bitの出力を行う
//下位→上位の順(リトルエンディアン)
digitalWrite( PIN_LATCH, LOW );
shiftOut( PIN_SER, PIN_CLK, LSBFIRST, ~Row ); //(A) カソード(Col列側)
shiftOut( PIN_SER, PIN_CLK, LSBFIRST, column[i] );// アノード(Row行側)
digitalWrite( PIN_LATCH, HIGH );
}
}
/**
* ライトオフ
*/
void lightOff(){
for(int i = 0; i < 8; i++){
byte Row = 0;
if(zero[i]>0){
Row = 1 << (8 - i -1);
}
digitalWrite( PIN_LATCH, LOW );
shiftOut( PIN_SER, PIN_CLK, LSBFIRST, ~Row );
shiftOut( PIN_SER, PIN_CLK, LSBFIRST, zero[i] );
digitalWrite( PIN_LATCH, HIGH );
}
}
/**
* 待機時間までライトオン
*/
void lightOnWait(float seconds) {
long endTime = millis() + seconds * 1000;
while(millis() < endTime) lightOn();
}
setup
pinMode( PIN_SER, OUTPUT );
pinMode( PIN_LATCH, OUTPUT );
pinMode( PIN_CLK, OUTPUT );
code
// バイト配列生成
setBytes("/*{facePanel_1}*/");
// 待機時間まで光る
lightOnWait(/*{number_2}*/);
// 消灯
lightOff();
mextをダウンロード後ドラッグ&ドロップ
↓GUI?でかけます
アップロードするとうまく動きました!!
Discussion