micro:bit(マイクロビット)と拡張基盤とUnityで遊んでみる

  • 8
    いいね
  • 0
    コメント

micro:bitとは

以前記事で紹介したchibi:bitと特に仕様は変わらず
BBC(英国放送協会)が主体となって作っている教育向けマイコンボードです。
仕様は25個のLED、2個のボタンスイッチのほか、加速度センサーと磁力センサー、BLE機能を搭載したマイコンボードです。
今回micro:bitは日本の技適通った事でスイッチサイエンスで発売になった訳です
スイッチサイエンス
chibi:bitとの違い
・本家
・安く手に入る 大体2千円ぐらい
・サポートしている拡張基盤が多い

開発環境は以前と変わらずブラウザ型のエディターになります
ブロックエディターとコードエディターが選べます
どちらでも自由に開発できます
micro:bit日本語開発環境

今回目指すもの

micro:bitをWiiUっぽいコントローラーとしてUnityと連携してみたいと思います
以前はchibi:bitからシリアル通信を送るだけでしたが、今回受ける所までやってみたいと思います

開発環境

・Windows10
・Unity2017.1.0

用意する物

micro:bit
SparkFun gamer:bit(拡張基盤)

セットアップ

こちらを参考
http://qiita.com/Sase/items/cbae0084d1147b9e9c64

micro:bit側の実装

micro:bit日本語開発環境を開きます
ブロックエディターを選ぶ
SparkFun gamer:bit(拡張基盤)のパッケージを追加します
やり方
https://learn.sparkfun.com/tutorials/microarcade-kit-experiment-guide/installing-the-gamerbit-package-for-microsoft-makecode

初期化
bandicam 2017-08-08 16-21-36-004.jpg

入力処理
一部をUpDate関数の中で組んでます
上を押した時 マイフレームLED処理をすると重くなるので、押した瞬間だけLED処理が走るようにしています
bandicam 2017-08-08 22-20-19-454.jpg

シリアル通信送信処理
bandicam 2017-08-08 22-26-24-638.jpg

シリアル通信受信処理
ITEMってゆう文字列が受信されたらITEM_GET_STATEを変えてLEDのアニメーションが実行されるようになっています
LEDのアニメーション処理をシリアル通信受信処理の中で組まずUpDate関数に書いている理由は
なぜかその中で組むと余計に数回呼ばれたので組んでいないです 多分バグかも
bandicam 2017-08-08 16-26-10-068.jpg

余談ですが、以前の記事のブロックエディターでキャスト(int->string)が出来なかったのですが、micro:bitのエディターではブロック側でもキャストできました。
ちなみにこんな感じ

bandicam 2017-08-08 16-42-39-776.jpg

ここまで実装完了
hexファイルをダウンロードしてきて、micro:bitをusb接続してストレージとしてPC上に出てきたら、先ほど
ダウンロードしてきたhexファイルをコピペして焼き付ける。

完成形のhexファイルgithubに上げました
https://github.com/SatoSeiichi/micro-bit_GameController

ちなみにhexファイルにしてもプロジェクトとしてブラウザエディターで開けます

シリアル通信の動作確認

こちらを参考
http://qiita.com/Sase/items/cbae0084d1147b9e9c64

Unity側の実装

最初にシリアル通信の受信部分のスクリプトの実装します。
こちらをお借りしました。文字列が切れる事がなくなりました
https://gist.github.com/asus4/86d48b80c295db826e37eef99d5438b2

次にオブジェクトにシリアル通信の値を反映するスクリプトの実装します
動かしたいオブジェクトにObjRotation.csをアタッチする

ObjRotation.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using AppKit;
using System.Text;

public class ObjContllol : MonoBehaviour {
    ArduinoSerial serial;
    Vector3 rotation;
    public string portNum;
    public Transform rotationObj;
    public string massage;

    enum MOVE_STATE
    {
        UP,
        DOWN,
        LEFT,
        RIGHT,
    }

    void Start()
    {
        serial = ArduinoSerial.Instance;
        bool success = serial.Open(portNum, ArduinoSerial.Baudrate.B_115200);
        if (!success)
        {
            return;
        }
        serial.OnDataReceived += SerialCallBack;
    }
    void OnDisable()
    {
        serial.Close();
        serial.OnDataReceived -= SerialCallBack;
    }
    // Update is called once per frame
    void Update () {
    }

    void SerialCallBack(string m)
    {
        objMove (m);
        objRotation(m);
        massage = m;
    }

    void objRotation(string message)
    {
        string[] a;

        a = message.Split("="[0]);
        if(a.Length != 2) return;  
        int v = int.Parse( a[1]);
        switch(a[0])
        {
        case "pitch":
            rotation = new Vector2(v, rotation.y);
            break;
        case "roll":
            rotation = new Vector2( rotation.x, v);
            break;
        }
        Quaternion AddRot = Quaternion.identity;
        AddRot.eulerAngles = new Vector3( -rotation.x, 0, -rotation.y );

        transform.rotation = AddRot;
    }

    void objMove(string message)
    {
        string[] a;

        a = message.Split("="[0]);
        if(a.Length != 2) return;  
        int v = int.Parse( a[1]);
        string m = a [0];
        if (m == "button") {

            string mc = a [1];

            //a_button
            if (mc [0] == '1') {
                print ("a_button");
            }
            //b_button
            if (mc [1] == '1') {
                print ("b_button");
            }
//          //y_button
            if (mc [2] == '1') {
                print ("y_button");
                rotationObj.GetComponent<Renderer> ().material.color = Color.blue;
            }
            //x_button
            if (mc [3] == '1') {
                print ("x_button");
                rotationObj.GetComponent<Renderer> ().material.color = Color.red;
            }
            //up
            if (mc [4] == '1') {
                print ("up");
                transform.SetPositionAndRotation (transform.position + (Vector3.up * 0.05f), transform.rotation);
                rotationObj.GetComponent<Renderer> ().material.color = Color.green;
            }
            //dawn
            if (mc [5] == '1') {
                print ("dawn");
                transform.SetPositionAndRotation (transform.position + (Vector3.down * 0.05f), transform.rotation);
                rotationObj.GetComponent<Renderer> ().material.color = Color.magenta;
            }
            //left
            if (mc [6] == '1') {
                print ("left");
                transform.SetPositionAndRotation (transform.position + (Vector3.left * 0.05f), transform.rotation);
                rotationObj.GetComponent<Renderer> ().material.color = Color.yellow;
            }
            //right
            if (mc [7] == '1') {
                print ("right");
                transform.SetPositionAndRotation (transform.position + (Vector3.right * 0.05f), transform.rotation);
                rotationObj.GetComponent<Renderer> ().material.color = Color.cyan;
            }

        }
    }

    void OnTriggerEnter(Collider co)
    {
        Destroy (co.gameObject);
        serial.Write ("ITEM");
        Debug.LogError("item_get");
    }
}

以上です。

完成Unityプロジェクトをgithubに上げました
https://github.com/SatoSeiichi/micro-bit_unity

結論
 Unityでシリアル通信をするならこちらのコードを参考にしよう
 https://gist.github.com/asus4/86d48b80c295db826e37eef99d5438b2

デモ動画

シリアル通信処理変更前

#microbit#unity で遊んでみる
うーん やっぱ2017にしてもシリアル通信はダメやなー 思い切ってBLE通信をやってみるかな pic.twitter.com/4njbtq3NSk

— SASE (@SaseKubrick) 2017年8月8日

シリアル通信処理変更後

やったー! シリアル通信処理を変更したらましになった! #microbit #unity pic.twitter.com/ZWXVpGwxTl

— SASE (@SaseKubrick) 2017年8月8日