1
Help us understand the problem. What are the problem?

posted at

updated at

MakeCode for M5Core2 を作った

前回、M5Atom上で、MakeCode for micro:bit で作ったプログラムを動かしました。
MakeCode for micro:bitで作ったプロジェクトをM5Atomで動かす

今度は、M5Core2上で動かしてみます。
具体的には、M5Core2のディスプレイ上に、Scratch3.0のネコを表示させ、M5Core2のタッチボタンのAとCボタンで左右に動かしたり、Bボタンでネコを回転させたりします。
それらの実装を、MakeCode for micro:bitでビジュアルプログラミングします。
やっていることは、MakeCodeで作ったものをJavaScriptでとりだして、ESP32で動くJavaScriptインタプリタQuickJSで動かしています。

細かいことは、ソースコードを見ていただくとして、ぜひ使ってみてください。
もろもろのソースコードを以下に置いています。

poruruba/M5Core2_MakeCode
 https://github.com/poruruba/M5Core2_MakeCode
poruruba/M5Core2_CustomBlock
 https://github.com/poruruba/M5Core2_CustomBlock

用意するもの

以下を用意します。

  • M5Core2 とUSB-Cケーブル
  • SDカード(FAT32でフォーマット済)
  • Visual Studio Code+PlatformIO

準備

まずは一式ダウンロードしてZIP展開。
https://github.com/poruruba/M5Core2_MakeCode

次に、M5Core2にSDカードを挿入しておきます。FAT32でフォーマットしておいて下さい。
Visual Studio Codeから、以下のフォルダを開きます。

 M5Core2_MakeCode-master\Arduino\M5Core2_MakeCode

そして、platformio.iniのポート番号を、実際のM5Core2が接続された仮想COMポートの番号に合わせる。

Arduino\M5Core2_MakeCode\platformio.ini
upload_port = COM8
monitor_port = COM8

WiFiアクセスポイントのSSIDとパスワードに変更。WiFiは、MakeCode for micro:bitで作ったJavascriptを登録するために使っています。

Arduino\M5Core2_MakeCode\src\main.cpp
const char *wifi_ssid = "【WiFiアクセスポイントのSSID】";
const char *wifi_password = "【WiFiアクセスポイントのパスワード】";

最後に、M5Core2に書き込みます。

これで、Scratch3.0のネコが表示されるかと思います。
以下の画像が、M5Core2に表示されます。

image.png

M5Core2のタッチボタンを押してみてください。ネコが、左側のボタンを押すと左に、右側のボタンを押すと右に動くかと思います。真ん中のボタンを押すと、ネコが回転します。ついでに、LEDをチカチカさせていますし、ネコをタッチするとバイブレーションが動くようにしました。

MakeCodeプロジェクトの作成

先ほど動かしたのは、以下のJavascriptです。

Arduino\M5Core2_MakeCode\rom\main.js
let led2 = 0
custom.setInterval(500, function () {
    custom.led_onoff(led2)
    led2 = (led2 + 1) % 2
})
custom.onButtonPressed(ExButton.C, function () {
    custom.player_step(10, 0)
})
custom.onButtonPressed(ExButton.B, function () {
    custom.player_rotate(ExRotate.RIGHT, 10)
})
custom.onButtonPressed(ExButton.A, function () {
    custom.player_step(-10, 0)
})
custom.onPlayerTouched(function () {
    custom.shock_play(100)
})

これは、あらかじめMakeCode for micro:bitで作成したものを、以下のようにして埋め込んでおいたものです。

Arduino\M5Core2_MakeCode\platformio.ini
board_build.embed_txtfiles =
    rom/main.js

次は、これをもう一度MakeCodeで作成してみます。

MakeCode for micro:bitをブラウザから開きます。

MakeCode for micro:bit
 https://makecode.microbit.org/

image.png

新しいプロジェクトを選択します。
適当な名前を付けます。例えば、test

image.png

プロジェクトが作成されました。

image.png

次に、M5Core2用のカスタムブロックを取り込むため、拡張機能を選択します。

image.png

検索のところに、以下を入力します。

 https://github.com/poruruba/M5Core2_CustomBlock

image.png

M5Core2カスタムブロックを選択します。
そうすると、Customというのが増えているのがわかります。

image.png

M5Core2で便利なブロックを作っておきました。

image.png

さきほどの拡張機能で取り込んできたファイル群の中にあります。
とはいっても、実は関数定義だけ。実体はArduino側に実装しています。

custom.ts
/**
 * このファイルを使って、独自の関数やブロックを定義してください。
 * 詳しくはこちらを参照してください:https://makecode.microbit.org/blocks/custom
 */

enum ExRotate{
    //% block="右回り"
    RIGHT,
    //% block="左回り"
    LEFT
}

enum ExDimension{
    //% block="X軸"
    X,
    //% block="Y軸"
    Y,
    //% block="Z軸"
    Z
}

enum ExDimension2d{
    //% block="X軸"
    X,
    //% block="Y軸"
    Y
}

enum ExRoll{
    //% block="ピッチ"
    PITCH,
    //% block="ロール"
    ROLL,
    //% block="ヨー"
    YAW
}

enum ExButton{
    //% block="A"
    A,
    //% block="B"
    B,
    //% block="C",
    C
}

/**
 * カスタムブロック
 */
//% weight=100 color=#0fbc11 icon="\uf0fe"
namespace custom {
    /**
     * タッチ
     */ 
    //% block block="このスプライトが押されたとき"
    export function onPlayerTouched(callback: () => void): void{
    }

    /**
     * ボタン押下
     */ 
    //% block block="%btn が押されたとき"
    export function onButtonPressed(btn: ExButton, callback: () => void): void{
    }

    /**
     * 繰り返し
     */ 
    //% block block="%msec msecごとに実行する"
    //% msec.defl=100
    export function setInterval(msec: number, callback: () => void): void{
    }

    /**
     * コスチューム
     */ 
    //% block block="コスチュームを %name にする"
    //% name.defl="costume1"
    export function costume_change(name: string): void{
    }

    /**
     * 背景
     */ 
    //% block block="背景を %name にする"
    //% name.defl="background1"
    export function background_change(name: string): void{
    }

    /**
     * 表示
     */ 
    //% block block="表示する"
    export function player_on(): void{
    }

    /**
     * 非表示
     */ 
    //% block block="隠す"
    export function player_off(): void{
    }

    /**
     * 歩く
     */ 
    //% block block="X座標を %x ずつ、Y座標を %y ずつ変える"
    export function player_step(x: number, y: number): void{
    }

    /**
     * 移動
     */ 
    //% block block="X座標を %x 、Y座標を %y にする"
    export function player_goto(x: number, y: number): void{
    }

    /**
     * 回転
     */ 
    //% block block="%direction に %degree 度回す"
    export function player_rotate(direction: ExRotate, degree: number): void{
    }

    /**
     * 角度
     */ 
    //% block block="%degree 度に向ける"
    export function player_angle(degree: number): void{
    }

    /**
     * 音再生
     */ 
    //% block block="%name の音を鳴らす"
    //% name.defl="cat"
    export function sound_play(name: string): void{
    }

    /**
     * バイブレーション
     */ 
    //% block block="%duration msec震わせる"
    export function shock_play(duration: number): void{
    }

    /**
     * 傾き
     */ 
    //% block block="%axis の傾き"
    export function direction(axis: ExDimension): number {
        return 0;
    }

    /**
     * 加速度
     */ 
    //% block block="%acc の加速度"
    export function acceleration(acc: ExDimension): number {
        return 0;
    }

    /**
     * 回転角
     */ 
    //% block block="%roll の回転角"
    export function rolling(roll: ExRoll): number {
        return 0;
    }

    /**
     * LED
     */ 
    //% block block="LED %onoff"
    export function led_onoff(onoff: number): void {
    }

    /**
     * コンソール
     */ 
    //% block block="%message をコンソール出力"
    export function console_log(message: string): void {
    }

    /**
     * 現在位置
     */ 
    //% block block="%dimension"
    export function player_position(dimension: ExDimension2d): number {
        return 0;
    }

    /**
     * 現在角度
     */ 
    //% block block="向き"
    export function player_direction(): number {
        return 0;
    }
}

カスタムブロックの仕様は以下が参考になります。
 https://makecode.com/defining-blocks

どんなカスタムブロックを作ったかというと、

  • ネコの現在角度
  • ネコの現在位置
  • ネコの移動
  • ネコの表示/非表示
  • ネコのコスチュームの変更
  • LEDのOnOff
  • M5Core2の回転角
  • M5Core2の加速度
  • M5Core2の傾き
  • バイブレーション
  • 音声再生(メモリ不足中)
  • 背景の変更
  • XXXmsecごとに実行
  • ボタンが押されたときに実行
  • ネコがタップされたときに実行
  • コンソール出力

それではさっそく作ってみましょう。

image.png

ちょっと画像ではわかりにくいかもしれませんが、Javascriptを選択すると以下のように変わります。

image.png

このコードは以下に置いておきました。

 scripts\cat_rolling.js

実は、ブロックをマウスで作らなくても、このJavascriptをコピペしても作れます。

scripts\cat_rolling.js
let x = 0
let y = 0
custom.setInterval(200, function () {
    x = custom.player_position(ExDimension2d.X) - custom.acceleration(ExDimension.X) / 2
    y = custom.player_position(ExDimension2d.Y) + custom.acceleration(ExDimension.Y) / 2
    if (x < 0) {
        x = 0
        custom.shock_play(100)
    }
    if (x >= 320) {
        x = 319
        custom.shock_play(100)
    }
    if (y < 0) {
        y = 0
        custom.shock_play(100)
    }
    if (y >= 240) {
        y = 239
        custom.shock_play(100)
    }
    custom.player_goto(x, y)
})

このデモは、M5Core2についているモーションセンサの値に従って、傾けている方向にネコを移動させるものです。もし画面の端にぶつかったら、M5Core2についているバイブレーションが動くようにしました。

M5Core2に転送する。

実はM5Core2にWebSocketサーバを立ち上げておいたので、ブラウザからプログラムをいつでもアップロードできます。
アップロードするプログラムは、先ほど表示を切り替えたJavascriptです。

アップロードするためのWebページを以下に作っておきました。

 html\upload\index.html

これをブラウザで開きます。もしくは以下からもアクセスできるようにしておきました。

 https://poruruba.github.io/M5Core2_MakeCode/html/upload/

(ですが、よく考えたらM5Core2側はwssではなくwsなので、Chromeがエラーをはじくようです。その場合は、諦めてファイルからindex.htmlを開くか、こちらを参考にしてください。)

image.png

ws_urlに、M5Core2のURLを入力します。以下のような感じです。

 ws://[M5Core2のIPアドレス]:81

そして、Connectボタンを押下すると、M5Core2のWebSocketサーバと接続できます。
Javascriptをペーストして、Sendボタンを押下すると、JavascriptがM5Core2に送られ、Javascriptを実行するため、自身を再起動します。
内部的にはSDカードに書き込んでいます。

再起動すると、先ほどと同じように背景とネコが表示されます。
今度は、M5Core2を持ち上げて、上下左右に傾けてみてください。傾けた方向にネコが動くかと思います。

image.png

やり残したこと

・Javascriptエンジンに、QuickJSを使いました。どうしても、Javascriptの再読み込みができずに、自身を再起動させました。
 → 解決しました。

・M5Core2のpsramInit()が動きませんでした。せっかく8MBもの広大なメモリがあるのに、使おうとすると、M5Core2がリブートしてしまいます。(どなたか助けてくれないでしょうか!!!)
メモリが増えれば、いろんなことができるのに。。。その影響で、サウンド再生が動けていないです。メモリが少ないため、再生しようとしたときにpsramInitを呼ぼうとしてリブート。。。

以上

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
1
Help us understand the problem. What are the problem?