💡

mblockの拡張機能を作ってみた

2022/02/18に公開

これは何?

mblockを触っていると、

拡張機能というのが使えるのを最近知りました。

拡張機能

makeblock社の製品や、arduinoなどのマイコンなどに接続する拡張キットを扱えるようにする追加のライブラリのようで、実は誰でもそのライブラリが作成できるようなので、今回作ってみたという話です。

Arduinoから、以前作った8x8LEDを動かすライブラリを作ってみます。

mblockとは?

scratchを拡張したビジュアルプログラミング環境で、
ビジュアルにプログラミングができて、mbotなどのmakeblock社製のマシンを操作することができます。
makeblock社が開発しています。サイトはこちら

動作画面

ユーザ登録

mblockの拡張センターに拡張機能を作成というボタンがあるので、そこをクリックすると、mBlockのExtension Builderというサイトに飛ぶので、ユーザ登録をします。

オンラインヘルプは

http://www.mblock.cc/doc/en/developer-documentation/developer-documentation.html

登録後、ログインすると↓こんな画面(のハズ)

作るもの

作るのは、デバイスそのもの(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?でかけます

アップロードするとうまく動きました!!

脚注
  1. デフォルトのテンプレートだと不要なものを削除する ↩︎

  2. この設定はオンラインヘルプのsampleにありました ↩︎

Discussion