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

シリアル通信時に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
  }
  
}
  

 

RigidBody.Velocityを使わない加速減速

マウスの横移動だけで加速減速します.マウスを戻しても逆走はしません.brakeの係数を変えることで減速率が変わりますが,単なる引き算なのであまりきれいではありません.

可能であれば加速に使用しているべき乗

Mathf.Pow(計算したい数値, 乗数);

のような関数を使うか,二次元関数や三角関数を使って減算してみるのもいいかもしれませんね.

 

スクリプト

using UnityEngine;
using System.Collections;

public class mousei : MonoBehaviour {

	public GameObject boatObj;
	public float sensitivity = 0.1f;
	public float brake = 0.05f;
	float firstPos;


	// Use this for initialization
	void Start () {
		firstPos = 0f;
	
	}
	
	// Update is called once per frame
	void Update () {

		float mouse_move_x = Input.GetAxis("Mouse X") * sensitivity;

		if (mouse_move_x > 0.1) {
			Mathf.Pow(mouse_move_x, 2);
			boatObj.transform.position += new Vector3 (mouse_move_x, 0f, 0f);
			firstPos += mouse_move_x;
		} else {
			if(firstPos > 0){
				firstPos -= brake;
			boatObj.transform.position += new Vector3 (firstPos, 0f, 0f);
			}
		}


	}
		


}

 

実行動画

特定のオブジェクトをON/OFFする

まずはスクリプトのみですが

 

using UnityEngine;
using System.Collections;

public class detachchild : MonoBehaviour {

	public GameObject RootObject;

	public GameObject RootObject2;
	// Use this for initialization
	void Awake(){


	}


	void Start () {


	}
	
	// Update is called once per frame
	void Update () {
	
	}



	public void hanasu(){
		RootObject.SetActive (false);
		RootObject2.SetActive (true);
	}

	public void hanasu2(){
		RootObject.SetActive (true);
		RootObject2.SetActive (false);
	}
}

 

public void クラス名(){

}

をつけたスクリプトは,ボタンのonClickにアサインしてそのクラスを選ぶとボタンから実行できます

 

ゲームオブジェクト変数名.SetActive(false); で見えなくなり

ゲームオブジェクト変数名.SetActive(true); で見えるようになります

そのゲームオブジェクトにアタッチしているスクリプトも無効になりますので注意.

NavmeshAgent上の速度検出

 

Rigidbody.veocity.magnitude で速度は出ません

using UnityEngine;
using System.Collections;

public class enemyScript : MonoBehaviour {

	public NavMeshAgent eneCharaObj;
	public Animator enemyAnim;

	float enemySpeedFloat = 0f;

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
		enemySpeedFloat = eneCharaObj.velocity.sqrMagnitude;
		enemyAnim.SetFloat("enemySpeed", enemySpeedFloat);
		//Debug.Log (enemySpeedFloat);
	}
}

 

サーボ制御その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

 

 

特定のオブジェクトの角度を出す

X軸の場合

using UnityEngine;
using System.Collections;

public class getAngle : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
		float myangle  = this.transform.localEulerAngles.x;
		Debug.Log (myangle);
	}
}