LoginSignup
1

More than 1 year has passed since last update.

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を呼ぼうとしてリブート。。。

以上

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1