Unityとchibi:bitの連携（シリアル通信）

#chibi:bitとは
chibi:bitは、BBC（英国放送協会）が主体となって作っている教育向けマイコンボードBBC micro:bitの互換機です。
仕様はmicro:bitと同じです。25個のLED、2個のボタンスイッチのほか、加速度センサーと磁力センサー、BLE機能を搭載したマイコンボードです。
micro:bitはBLE機能が日本の技適が通っていない為使用ができない　しかも　電源入れると自動的にBLEが起動するので、電源も入れられなので、日本で使う場合はchibi:bitをお勧めします。
[chibi:bit専用の開発環境](http://chibibit.io/ide/)を用意されています。
もちろん[micro:bitの開発環境](http://microbit.org/)で書いたプログラムも書き込み可能です。

chibi:bit購入　
[スイッチサイエンス](https://www.switch-science.com/catalog/2900/)

#Unityとchibi:bitの連携
今回はchibi:bitのセンサーの値をシリアル通信でUnityに値を送信してオブジェクト動かす所までやりたいと思います。

#開発環境
・Windows１０
・Unity5.5.0

#セットアップ
micro:bitの公式サイトのリファレンスを参考
https://www.microbit.co.uk/td/serial-library
１、[デバイスドライバーのインストール](https://developer.mbed.org/handbook/Windows-serial-configuration)
　　サイトの[Download latest driver](https://developer.mbed.org/media/downloads/drivers/mbedWinSerial_16466.exe)をクリック
２、ターミナルエミュレーターのインストール（PCの導通確認時に必要）
　[Tera Term](https://ttssh2.osdn.jp/index.html.en)のDownloadから.exeをダウンロード
　公式では4.88をインストールしてと書いてあるが、当方は最新の4.93でも動きました。

#chibi:bit側の実装
[chibi:bit専用の開発環境](http://chibibit.io/ide/)を開きます。
プログラムはブロックエディタを使わず直接JavaScriptを書くようにします。理由はブロックエディタだとキャストが使えなかったので
コードは簡単に書くと
```
//アップデート
basic.forever(() => {
    serial.writeLine("pitch=" + input.rotation(Rotation.Pitch))//ジャイロセンサーのピッチを送信
    serial.writeLine("roll=" + input.rotation(Rotation.Roll))//ジャイロセンサーのロールを送信
})
```
でhexファイルをダウンロードしてきて、chibi:bitをusb接続してストレージとしてPC上に出てきたら、先ほど
ダウンロードしてきたhexファイルをコピペして焼き付ける。

#シリアル通信の動作確認
セットアップでインストールした[Tera Term](https://ttssh2.osdn.jp/index.html.en)を起動する
１、ファイル→新しい接続を選択しTCP/IPとシリアルの項目があるので、シリアルを選択してokをクリック
ちなみにポート番号はあとでUnityの実装で使うのでメモしておく
![bandicam 2017-01-06 15-14-37-284.jpg](https://qiita-image-store.s3.amazonaws.com/0/158441/e840f964-ea32-e276-6c9e-638f75aeb419.jpeg)
２、設定→シリアルポート設定を選択し　ボー・レートを「115200」を選択しokをクリックすると
下記の画像にログが出ればシリアル通信の成功になります
![bandicam 2017-01-06 15-19-47-787.jpg](https://qiita-image-store.s3.amazonaws.com/0/158441/20fb6f51-5713-620e-0ba4-25ce6724cd83.jpeg)

#Unity側の実装
最初にシリアル通信の受信部分のスクリプトの実装します。
参考にしたもの
http://tips.hecomi.com/entry/2014/07/28/023525



```csharp:SerialHandler.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO.Ports;
using System.Threading;
using System.Runtime.InteropServices;

public class SerialHandler : MonoBehaviour {
	public delegate void SerialDataReceivedEventHandler(string message);
	public event SerialDataReceivedEventHandler OnDataReceived;
	
	public string portName = "COM8";
	public int baudRate    = 115200;
	
	private SerialPort serialPort_;
	private Thread thread_;
	private bool isRunning_ = false;
	
	public string message_;
	private bool isNewMessageReceived_ = false;
	
	
	void Awake()
	{
		Open();
		
	}
	
	void Update()
	{
	}
	
	void OnDestroy()
	{
		Close();
	}
	
	private void Open()
	{
		serialPort_ = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);

		serialPort_.Open();
		
		isRunning_ = true;
		
		thread_ = new Thread(Read);
		thread_.Start();
	}
	
	private void Close()
	{
		isRunning_ = false;
		
		if (thread_ != null && thread_.IsAlive) {
			thread_.Join();
		}
		
		if (serialPort_ != null && serialPort_.IsOpen) {
			serialPort_.Close();
			serialPort_.Dispose();
		}
	}
	
	private void Read()
	{
		while (isRunning_ && serialPort_ != null && serialPort_.IsOpen) {
			try {
				message_ = serialPort_.ReadLine();
				isNewMessageReceived_ = true;
				Debug.LogError(message_);
			} catch (System.Exception e) {
				Debug.LogWarning(e.Message);
			}
		}
	}
	
	public void Write(string message)
	{
		try {
			serialPort_.Write(message);
			Debug.LogError(message);
		} catch (System.Exception e) {
			Debug.LogWarning(e.Message);
		}
	}
}
````

ここで重要なのは
・public変数の string portNameをシリアル通信の動作確認でメモしといたものと置き換える
・public変数の int baudRateを115200に固定する

このスクリプト適当にシーンのオブジェクトにアタッチする

次にオブジェクトにシリアル通信の値を反映するスクリプトの実装します
ここではジャイロセンサーの値をオブジェクトの回転に反映しています

```csharp:ObjRotation.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ObjRotation : MonoBehaviour {
　　　　
	public SerialHandler _SerialHandler;　//SerialHandler.csの参照
	Vector3 rotation;
	
	// Update is called once per frame
	void Update () {
		objRotation(_SerialHandler.message_);
	}
	
	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;
	}
}
````
動かしたいオブジェクトにObjRotation.csをアタッチして、

Playするとエディタ上のオブジェクトとchibi:bitの動きが反映されたら成功です。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">unityとchibi:bitの連携 (シリアル通信) <a href="https://t.co/GbD6mfIUNx">pic.twitter.com/GbD6mfIUNx</a></p>&mdash; SASE (@SaseKubrick) <a href="https://twitter.com/SaseKubrick/status/818085317991243776?ref_src=twsrc%5Etfw">2017年1月8日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>