「Arduino」カテゴリーアーカイブ

unity->Arduino->Unity開発メモ2019

UnitySerianHandloerのUnity2018で使えたやつ

 

SerialHandler.cs

using UnityEngine;
using System.Collections;
using System.IO.Ports;
using System.Threading;

public class SerialHandler : MonoBehaviour
{
    public delegate void SerialDataReceivedEventHandler(string message);
    public event SerialDataReceivedEventHandler OnDataReceived = delegate { };

    //ポート名
    //例
    //Linuxでは/dev/ttyUSB0
    //windowsではCOM1
    //Macでは/dev/tty.usbmodem1421など
    public string portName = "/dev/cu.usbmodem2101";//mac
    public int baudRate = 9600;

    private SerialPort serialPort_;
    private Thread thread_;
    private bool isRunning_ = false;

    private string message_;
    private bool isNewMessageReceived_ = false;

    void Awake()
    {
        Open();
    }

    void Update()
    {
        if (isNewMessageReceived_)
        {
            OnDataReceived(message_);
        }
        isNewMessageReceived_ = false;
    }

    void OnDestroy()
    {
        Close();
    }

    private void Open()
    {
        serialPort_ = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
        //または
        //serialPort_ = new SerialPort(portName, baudRate);
        serialPort_.ReadTimeout = 20;//Add this 2019
        serialPort_.Open();
        serialPort_.NewLine = "\n";//Add this 2019

        isRunning_ = true;

        thread_ = new Thread(Read);
        thread_.Start();
    }

    private void Close()
    {
        //isNewMessageReceived_ = false;
        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;
            }
            catch (System.Exception e)
            {
            //    Debug.LogWarning(e.Message);
            }
        }
    }

    public void Write(string message)
    {
        try
        {
            serialPort_.Write(message);
        }
        catch (System.Exception e)
        {
            Debug.LogWarning(e.Message);
        }
    }
}

 

Unityボタン側スクリプト

Btn.cs

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

public class Btn : MonoBehaviour
{
    //先ほど作成したクラス
    public SerialHandler serialHandler;


  void Start()
    {
        //信号を受信したときに、そのメッセージの処理を行う
        serialHandler.OnDataReceived += OnDataReceived;
    }

    void Updata()
    {
        //文字列を送信
       // serialHandler.Write("hogehoge");
    }

    //受信した信号(message)に対する処理
    void OnDataReceived(string message)
    {
        var data = message.Split(
                new string[] { "\t" }, System.StringSplitOptions.None);
        if (data.Length < 2) return;

        try
        {
         
        }
        catch (System.Exception e)
        {
            Debug.LogWarning(e.Message);
        }
    }



    /////ここから追加します
    /// 
    /// 
    /// 
    ///
    public void sendOn()
    {
        //Arduinoに文字列onを送る
        serialHandler.Write("4");
    }

    public void sendOff()
    {
        //
        serialHandler.Write("5");
    }
    public void ledOn()
    {
        //
        serialHandler.Write("6");
    }

    public void ledOff()
    {
        //
        serialHandler.Write("7");
    }

}

 

Arduino側コード

#include <Servo.h>
const int LED_PIN = 13;
int SERVO_SOCKET = 9;
Servo servo;
String InByte_strings;
int InByte;

void setup() {
 Serial.begin(9600);
 pinMode( LED_PIN, OUTPUT );
servo.attach( SERVO_SOCKET );
}

void loop() {
  
  if(Serial.available()>0){
    InByte_strings=Serial.readStringUntil(';');
    InByte=InByte_strings.toInt();
    Serial.println(InByte);

     switch (InByte){
    case 4:
      servo.write( 90 );
      break;
    case 5:
      servo.write( 180 );
      break;
      case 6:
      digitalWrite(LED_PIN,HIGH);
      break;
      case 7:
      digitalWrite(LED_PIN,LOW);
      break;
  }
}
}

 

 

某アクチュエーターコントロールスクリプト

シリアル通信時にCR,LFが入るとおかしくなる現象がおき,それの対策版です

Arduinoのシリアルモニタは改行無しで使用していれば特に問題はおきませんが,うっかり改行つきでテストしてた時に起こる問題を回避しています

寝不足だと改行モードが変わったことに気づかないのよ,,,

 

#include <Servo.h>

unsigned long mytime = 0;
unsigned long hittime;
unsigned long duration;
boolean sensorBool = false;//センサ計測制御用
boolean sensorWorking = false;//
boolean servoUp = false;//servo上下のBool
boolean serialFilter = true;//servo上下のBool
int input_value;//A1入力値
Servo myservo;//サーボ設定
int kaisu = 0;  // 角度のカウンタ max10で使うのは8がいい
int power;//サーボ動作速度
unsigned long startTime;//タイマー用
int servoTime;
int myvar;

void stageReset() {
  myservo.write(0);//最大斜度にする(リセット)
  delay(5000);//最大斜度になるのを待つ
  
  //約4度傾けて水平にする
  servoUp = true;
  power = 200;
  startTime = millis();
  servoTime = 3000;

  kaisu = 4;//4度にセット
}


void setup() {
  Serial.begin(9600);
  myservo.attach(9, 1000, 2000);
  mytime = millis();
  stageReset();//ステージ水平にする
  sensorWorking = false;
}

void mysend() {
  Serial.println(duration);//シリアルに計測時間送る
}


void loop() {
  //回転間隔計測
  input_value = analogRead(1);
  if (sensorBool) {
    if (input_value < 130) {//3.3V is under 130 is read sw ON Long cable version
      sensorBool = false;
      hittime = millis();
      duration = hittime - mytime;
      mysend();
      mytime = hittime;
    }
  } else if (!sensorBool) {
    if (input_value > 300) {
      sensorBool = true;
    }
  }

  //サーボ動作
  if (servoUp) {
    sensorWorking = true;
    if (millis() > startTime + servoTime) {
      servoUp = false;
      serialFilter = true;
      sensorWorking = false;
    }
    myservo.writeMicroseconds(map(power, 0, 255, 1500, 2000));
    Serial.flush();
  } else if (!servoUp) {
    myservo.writeMicroseconds(map(0, 0, 255, 1500, 2000));
   Serial.flush();
  }
}

void serialEvent() {
 // Serial.println("SERIALIN");

 //if(var == 0x0D){
 // return;
 //}else if(var == 0x0A){
 // return;
// }

 
  if (Serial.available()>0) { 
    byte var = Serial.read();

 if(var == 0x0D){
  return;
 }else if(var == 0x0A){
  return;
}else{

    
 if(serialFilter){
    serialFilter = false;
    //byte var = Serial.read();
    myvar = var - 0x30;//16進数でくるので16進数のゼロひく
   //int myvar = int(var);
   // switch (var) {
    //  case 1://stage UP
    servoUp = true;
    
   if(myvar  == 9){
      stageReset();
    return;
    }else if(myvar > 8){
      myvar = 8;
    }else if (myvar < 0){
      myvar = 0;
    }
    
   
if(kaisu > -1 && kaisu < 9 && !sensorWorking){  //ex2 var0

       // int sabun = myvar - kaisu;
       //   Serial.println(myvar);
  //Serial.println(sabun);
   //     servoUp = true;
   int sabun = myvar - kaisu;
   //Serial.println(sabun);
        if(sabun > 0 && !sensorWorking){
         // Serial.println("UP");
        power = 255;
        }else if (sabun < 0 && !sensorWorking){
         // Serial.println("down");
          power = -230;//down
        }

        startTime = millis();
        servoTime = 350 * abs(sabun);
        //if(kaisu > -1 && kaisu < 9){
          if(myvar < 0){
            kaisu = 0;
          }else if (myvar > 8){
            kaisu = 8;
          }else{
          kaisu = myvar;
          }
         
        //}
        //kaisu--;
      }
    //    break;
     // case 2://stage Down
      //else if(kaisu < 9){
       // power = -180;
       // servoUp = true;
       // servoTime = 700;
       // startTime = millis();
       // kaisu++;
      //}
       // break;
    }//end of serial filter
  }// end delte CRLF
  }
  
}
  

 

サーボ制御その2

サーボのプログラムを更新しました

サーボ(といくかアクチュエイター)の負荷を下げるために稼働時間を短く(速く動かす)しています

 

#include <Servo.h>

unsigned long mytime = 0;
unsigned long hittime;
unsigned long duration;
boolean sensorBool = false;//センサ計測制御用
boolean servoUp = false;//servo上下のBool
boolean serialFilter = true;//servo上下のBool
int input_value;//A1入力値
Servo myservo;//サーボ設定
int kaisu = 0;  // 角度のカウンタ max10で使うのは8がいい
int power;//サーボ動作速度
unsigned long startTime;//タイマー用
int servoTime;

void stageReset() {
  myservo.write(0);//最大斜度にする(リセット)
  delay(5000);//最大斜度になるのを待つ
  
  //約4度傾けて水平にする
  servoUp = true;
  power = 180;
  startTime = millis();
  servoTime = 3200;

  kaisu = 4;//4度にセット
}


void setup() {
  Serial.begin(9600);
  myservo.attach(9, 1000, 2000);
  mytime = millis();
  stageReset();//ステージ水平にする
}

void mysend() {
  Serial.println(duration);//シリアルに計測時間送る
}


void loop() {
  //回転間隔計測
  input_value = analogRead(1);
  if (sensorBool) {
    if (input_value < 130) {//3.3V is under 130 is read sw ON Long cable version
      sensorBool = false;
      hittime = millis();
      duration = hittime - mytime;
      mysend();
      mytime = hittime;
    }
  } else if (!sensorBool) {
    if (input_value > 300) {
      sensorBool = true;
    }
  }

  //サーボ動作
  if (servoUp) {
    if (millis() > startTime + servoTime) {
      servoUp = false;
      serialFilter = true;
    }
    myservo.writeMicroseconds(map(power, 0, 255, 1500, 2000));
  } else if (!servoUp) {
    
    myservo.writeMicroseconds(map(0, 0, 255, 1500, 2000));
    Serial.flush();
  }
}

void serialEvent() {
  if (Serial.available()) {
      if(serialFilter){
    serialFilter = false;
    byte var = Serial.read();
    int myvar = var - 0x30;//16進数でくるので16進数のゼロひく
   //int myvar = int(var);
   // switch (var) {
    //  case 1://stage UP
    if(myvar > 8){
      myvar = 8;
    }else if (myvar < 0){
      myvar = 0;
    }
      if(kaisu > -1 && kaisu < 9){  //ex2 var0
        int sabun = myvar - kaisu;
//Serial.println(sabun);
        servoUp = true;
        if(sabun > 0){
        power = 240;///up
        }else if (sabun < 0){
          power = -220;//down
        }
        startTime = millis();
        servoTime = 350 * abs(sabun);
       // if(kaisu > -1 && kaisu < 9){
          if(myvar < 0){
            kaisu = 0;
          }else if (myvar >8){
            kaisu = 8;
          }else{
          kaisu = myvar;
          }
        //  Serial.println(kaisu);
        //}
        //kaisu--;
      }
    //    break;
     // case 2://stage Down
      //else if(kaisu < 9){
       // power = -180;
       // servoUp = true;
       // servoTime = 700;
       // startTime = millis();
       // kaisu++;
      //}
       // break;
    }
  }
  }

 

なお,これに対応するUnity側のスクリプトは

using UnityEngine;
using System.Collections;
using System;//use for time
using UnityEngine.UI;//use for UI
using System.Threading;

public class serialSender2 : MonoBehaviour {
	public SerialHandler serialHandler;
	float myangle;
	int kakudoDummy;
	//Thread mythread;//use thread
	public Text myuitext;

	void Start () {
		Invoke("startLoop", 10f);//10秒後にコルーチン開始
	}

	void Update () {

	}
		
public void startLoop(){
	StartCoroutine(angleSend());
}


IEnumerator angleSend() {
while (true) {
			myangle  = this.transform.localEulerAngles.x;
			if (myangle < 360f && myangle > 180f) {
				myangle = 360f - myangle;
			}else{
				myangle = (myangle * -1f) ;
			}
			myangle = Mathf.Round(myangle) + 4;//まるめた角度
			if (myangle > 8) {
				myangle = 8;
			} else if (myangle < 0) {
				myangle = 0;
			}
			string _myangle  = myangle.ToString();
			serialHandler.Write (_myangle);//send Angle
			//ui display

			myuitext.text = myangle.ToString ();
//			Debug.Log(_myangle);
		yield return new WaitForSeconds(5f);
	}
}
		

}

です

角度を5秒ごとにサンプリングし,0〜8の数値(角度の近似値)に変化させシリアルで送信しています

サーボ制御とか

Arduino側のプログラム(スケッチ)

 

#include <Servo.h>

unsigned long mytime = 0;
unsigned long hittime;
unsigned long duration;
boolean sensorBool = false;//センサ計測制御用
boolean servoUp = false;//servo上下のBool
int input_value;//A1入力値
Servo myservo;//サーボ設定
int kaisu = 0;  // 角度のカウンタ max10で使うのは8がいい
int power;//サーボ動作速度
unsigned long startTime;//タイマー用
int servoTime;

void stageReset() {
  myservo.write(0);//最大斜度にする(リセット)
  delay(5000);//最大斜度になるのを待つ
  
  //約4度傾けて水平にする
  servoUp = true;
  power = 180;
  startTime = millis();
  servoTime = 3200;

  kaisu = 4;//4度にセット
}


void setup() {
  Serial.begin(9600);
  myservo.attach(9, 1000, 2000);
  mytime = millis();
  stageReset();//ステージ水平にする
}

void mysend() {
  Serial.println(duration);//シリアルに計測時間送る
}


void loop() {
  //回転間隔計測
  input_value = analogRead(1);
  if (sensorBool) {
    if (input_value < 70) {//3.3V is under 70 is read sw ON
      sensorBool = false;
      hittime = millis();
      duration = hittime - mytime;
      mysend();
      mytime = hittime;
    }
  } else if (!sensorBool) {
    if (input_value > 300) {
      sensorBool = true;
    }
  }

  //サーボ動作
  if (servoUp) {
    if (millis() > startTime + servoTime) {
      servoUp = false;
    }
    myservo.writeMicroseconds(map(power, 0, 255, 1500, 2000));
  } else if (!servoUp) {
    myservo.writeMicroseconds(map(0, 0, 255, 1500, 2000));
  }
}

void serialEvent() {
  
  if (Serial.available() > 0) {
    byte var = Serial.read();
    var = var - 0x30;//16進数でくるので16進数のゼロひく

    switch (var) {
      case 1://stage UP
      if(kaisu > -1){
        servoUp = true;
        power = 180;
        startTime = millis();
        servoTime = 700;
        kaisu--;
      }
        break;
      case 2://stage Down
      if(kaisu < 8){
        power = -180;
        servoUp = true;
        servoTime = 700;
        startTime = millis();
        kaisu++;
      }
        break;
    }
  }


}

 

 

UnityからArduinoにシリアルで送信

文字列として数字を送ります

Unity側(要SerialHandler)

using UnityEngine;
using System.Collections;
using System;//use for time
using UnityEngine.UI;//use for UI


public class serialSend : MonoBehaviour {
	public SerialHandler serialHandler;
	// Use this for initialization
	void Start () {
		serialHandler.OnDataReceived += OnDataReceived;
	}
	
	// Update is called once per frame
	void Update () {
	
	}

	public void sendBtn(){
		serialHandler.Write ("2");
	}



	void OnDataReceived(string message){

	}


}

Canvasでボタンを作成し,public void sendBtn()をアサインしてください

Arduino側

int i = 0;  // 文字数のカウンタ

void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}
void loop() {

  if (Serial.available()) {

    byte var = Serial.read();
    var = var - 0x30;
    switch (var) {
      case 1:
        //hoge(var);
        Serial.println('1');
        digitalWrite(13, HIGH);
        delay(1000);              // wait for a second
        digitalWrite(13, LOW);
        break;
      case 2:
        //hoge(var);
        Serial.println('2');
       digitalWrite(13, HIGH);
        delay(2000);              // wait for 2 second
        digitalWrite(13, LOW);

        
        break;
      case 3:
        Serial.println('3');
        break;
    }
  }
}

文字列の扱いをcharでやると面倒なので(今回は数字だけなので)byteでやってみる

byteの数字は0が0x30らしいので,1(0x31)を送ってそれをひくと1になるらしい,,,

参考

シリアルモニタからArduinoへ数値を送る方法 – Qiita

シリアルモニタから数値を送り、Arduinoに数値に応じた処理をさせたいときがあります。しかし、以下のコードを書き込んでもちっとも反応してくれません。 sample1.ino void setup() { Serial.begin(9600); } void loop() { byte var = Serial.read(); switch (var) { case 1: //hoge(var); Serial.pr…” name=”description

LINK: qiita.com/hikoalpha/items/633c677f5cd12d536dcc

 

 

VRに使ったスクリプト(Unity側)

(関連記事)

  • VRについての記事はこちら
  • SerialHandlerについての記事はこちら

上記リンク先の記事SerialHandlerを使ったUnityの制御です.

 

using UnityEngine;
using System.Collections;
using System;//use for time
using UnityEngine.UI;//use for UI


//アセットSuperSplinesのメニューを追加
	[AddComponentMenu("SuperSplines/Animation/Regular Animator")]


	public class mySpline2 : MonoBehaviour{
		public Spline spline;
		public WrapMode wrapMode = WrapMode.Clamp;//SuperSplineの初期モード実際はLOOPで使用
		public float speed = 0f;//初期速度ゼロでないと起動したら動いてしまう
		public float offSet = 0f;//オフセット値/スタート位置を変えたい場合など.

		public float passedTime = 0f;//何に使ったかな?
	float myspeed = 0f;//何に使ったかな?

		public Text myText; //UIで使う用
		public SerialHandler serialHandler;//serialHandlerスクリプトがアサインされたゲームオブジェクトをアサインする用.

		//for arduino
		public bool spBool = false;//停止用

		//時間計算用,試行錯誤してるので要らない変数あるかも
		private int starttime;
		private int now;
		private int duration;
		private float truespeed;
		private float myPos = 0f;
		private float mytime = 0f;
		float lerpspeed =0f;
	float firstSpeed = 0f;

	float mymillsec= 0f;
	string kmspeed;



	void Start(){

			myText.text = "0km/h";//GUI表示用に0km/hいれる
		starttime = DateTime.Now.Hour * 60 *60 * 1000 + DateTime.Now.Minute * 60 * 1000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;//起動した時間をstarttimeにミリセカンドで入れる.ペダル停止検知用
		//信号を受信したときに、そのメッセージの処理を行う
		serialHandler.OnDataReceived += OnDataReceived;
		}



		void Update( ) {
			mytime += Time.deltaTime * speed;//いまの時間とスピードかけてspline動かす指標にする
		if (spBool) {//ペダル動いてるとき
		myPos += Mathf.LerpUnclamped (speed ,firstSpeed, mytime);//スプライン上の位置myPosを時間でslerpする
		}
		if (Input.GetKeyDown ("s")) {//停止用
			myPos += Mathf.LerpUnclamped (0f, 0f, mytime);
				spBool = false;
			myspeed = 0f;
		}

			if (Input.GetKeyDown ("r")) {//リセット用
				myPos = 0;
				spBool = true;
				myspeed = 0f;
			speed = 0f;
			}
// 下3行がsplineを動かすやつ
			float clampedParam = WrapValue (myPos + offSet, 0f, 1f, wrapMode);
			transform.position = spline.GetPositionOnSpline (clampedParam);
			transform.rotation = spline.GetOrientationOnSpline (clampedParam);

////
		}



	void OnDataReceived(string message){//arduinoから文字列を受信したら
		
		firstSpeed = speed;初期速度をさっきの速度に入れ替え(2回目以降用)
		mymillsec = float.Parse (message);//車輪が1回転した間隔を受信してるので,それをフロート値に変換
			myspeed = (3600000f / mymillsec) * 0.000628f;//速度km/hを計算
		if (myspeed < 0.9) {//速度が1km未満ならゼロに
			myspeed = 0f;
		}

			kmspeed = myspeed.ToString ("N2");//小数点2桁でカット
		speed = myspeed * 0.00005f;//乗数で速度感変わります
		//}
	
		myText.text = kmspeed + "km/h";//速度をUIに表示
		//以下使ってない(タブでデータ区切り用)
		var data = message.Split(
			new string[]{"\t"}, System.StringSplitOptions.None);
		if (data.Length < 2) return;

		try {
		} catch (System.Exception e) {
			Debug.LogWarning(e.Message);
		}

	}



	public void stopper(){ //使っていません.ペダルの回転間隔を調べて回っていないのならゼロにしようと思いましたが,惰性で進むことを優先してこちらはカット(ただしBoolだけ使ってる)
		now = DateTime.Now.Hour * 60 *60 * 1000 + DateTime.Now.Minute * 60 * 1000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
		duration = now - starttime;

		if (duration > 3000) {
			spBool = false;
			kmspeed = "0";
			myText.text = kmspeed + "km/h";
		} else {
			spBool = true;
		}
		//Debug.Log (spBool);
		starttime = DateTime.Now.Hour * 60 *60 * 1000 + DateTime.Now.Minute * 60 * 1000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
	}



	public void testBtn(){//センサを使っていないときに,GUIのボタンでテスト出来るよう

		int myrand = UnityEngine.Random.Range (150, 1800);
		string randStr = myrand.ToString ();
		OnDataReceived (randStr);


	}



//splineのモード設定用みたい
		private float WrapValue( float v, float start, float end, WrapMode wMode )
		{
			switch( wMode )
			{
			case WrapMode.Clamp:
			case WrapMode.ClampForever:
				return Mathf.Clamp( v, start, end );
			case WrapMode.Default:
			case WrapMode.Loop:
				return Mathf.Repeat( v, end - start ) + start;
			case WrapMode.PingPong:
				return Mathf.PingPong( v, end - start ) + start;
			default:
				return v;
			}
		}

	}

です.

VRアプリ開発メモ

実質2日間でOculusRift(DK2)対応のコンテンツを作っていました.

このレベルなら文系の私でもモデリング含めて2日(徹夜なし)で作れるので,卒研とかはこんなレベルじゃダメですよ〜

(ていうか,そもそも組み立てただけで研究でもなんでもない,,,)

そもそもOculusって何かってっつーと,PSVRのようなものです.

 

Oculus Riftはコケられない、だから値段も高くなる|WIRED.jp

製品版「Oculus Rift」の予約受付がはじまり、その価格の高さに驚いた人も多いだろう。しかしソニーやHTCといった手ごわいライヴァル企業と競わなければならないOculusにとって、いちばんの問題はその価格ではないようだ。

LINK: wired.jp/2016/01/11/oculus-rift-price/

 

このOculus社がDK1を出したのはずいぶん前です.当時は衝撃でしたね.私はジェットコースターで酔ってOculusは触らないことにしました.

でもこのあたりの衝撃が現在のVRブームを作ったとも言えます.

さて,このVRコンテンツ,作るのは超簡単です.

どのくらい簡単かというと,ドライバなどインストールしてれば,見るだけなら3分くらいで作れます.

研究室に前の住人が残しておいたエアロバイクがあったので,ちょいと分解.データが取れそうでした.

そこで,,,,

Arduinoでちょいちょいといじって,

bike1

こんなものができました.

八事の空を空中散歩♪

オーキャンで高校生が絶叫していました〜(それを見てる方が楽しい)

bike2

センサのデータ変換にはAruinoを使っています.

 

今回書いたプログラムは全部で200行以下です.

そのうち,エアロバイクのセンサをArduinoからシリアルで送るプログラム

unsigned long mytime = 0;
unsigned long hittime;
unsigned long duration;
boolean sensorBool = true;
int input_value;

void setup(){
Serial.begin(9600);
mytime = millis();
}


void loop(){
 input_value = analogRead(3);
if(sensorBool == true){
if(input_value < 200){
 sensorBool = false;
hittime = millis();
duration = hittime - mytime;
mytime = hittime;
send();
}
}else if(!sensorBool){
  if(input_value > 500){
    sensorBool = true;
  }
}
  
}

void send(){
Serial.println(duration);

}

これをUnityに送って,コースのスプラインを走るだけです.

うん,簡単ですね.

Unity側のプログラムは別記します

なお,数値変化をやさしくするために,

Mathf.LerpUnclamped

を使っています.

Mathf.Lerpでもいいのですが,これは0から1でしか動作しません.

Splineは0(始点)から1(終点)で動くので,1を入れると1周します.Mathf.Lerpですと,1周しかしません.

Mathf.LerpUnclampedにすると,1を越えても数値補完してくれるので2周3周したいお客さんがいるときにも対応できます.

もちろん,適宜データのリセットは大事ですが,,

ArduinoのデータをUnityに送る

Uniduino(Arduinoでなく)ではシリアル通信のデータ=Serial.println(hogehoge);したもの=が見えない.

サイクルコンピュータのようなものを作ろうとしたのですが,UnityのFPSを越える間隔のデータはUnityでは処理しきれないため,Arduino側でデータを処理し,Unityのupdateより遅い速度でUnityへ送る必要がある.

そこで,シリアル通信を送るサンプルを探していたのですが,以下リンクより見つけることができました.

 

UnityとArduinoをシリアル通信 – Qiita

はじめに (読み飛ばしてください 笑) ちょっとした趣味でデータグローブを作ってUnityで遊べたらなと思いました。 ハードウェアの部分はArduinoで制御すればいいんですがUnityとArduino間の通信とどうしたもんじゃと。 調べたらUniduinoという大変素晴らしいAssetがあるみたいですが、使うのに$30するようです。 ふえぇ…学生には高いよぉ… ということでいろんなネットの情報を参考にUniduinoを使わずにUnityとArduin…” name=”description

LINK: qiita.com/yjiro0403/items/54e9518b5624c0030531

 

このプログラムのうち,SerialHandlerをそのまま使わせていただき,別の呼び出すスクリプトだけを変更します.

以下は,シリアルデータを読み出すスクリプトです.別途,SerialHandlerが必要です.

using UnityEngine;
using System.Collections;


	public class mySpline2 : MonoBehaviour{

	public SerialHandler serialHandler;


		void Start(){
		serialHandler.OnDataReceived += OnDataReceived;
		}



		void Update(){

		}



	void OnDataReceived(string message){
		Debug.Log(message);

		var data = message.Split(
			new string[]{"\t"}, System.StringSplitOptions.None);
		if (data.Length < 2) return;

		try {
		} catch (System.Exception e) {
			Debug.LogWarning(e.Message);
		}


	}
	}

 

7行目でInspectorにボックスが出ますので,serialHandlerがアサインされたオブジェクトを入れてください.

11行目は必須です.これがないとエラーがでます.

23行目にあるようにmessageでString形式でデータが戻ってきます.

最終的にはこれをintParseして数値として使用する予定です.

Uniduinoが動かないとき

UnityでArduinoと通信できる魔法のプラグインUniduino(おそらく開発停止)をインポートして動かないとき,

PlayerSettings.NET 2.0 subset.NET 2.0に変更する.これ大事.Uniduinoは以下リンクより.

 

Uniduino

LINK: www.uniduino.com/

 

 

なお,UnityでArduinoを扱えるシステムの最新版は,

 

ARDUnity Home Page

Innovative IoT base Physical Computing DIY Solution ‘ARDUnity’ Official Web Site

LINK: www.ardunity.com/

 

があり,しかも基本的なDOUT.INやAINなどは無料で使用可能です.