質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.22%

unityのSystem.IO.PortsクラスのBytesToReadが正常に動かない

受付中

回答 0

投稿

  • 評価
  • クリップ 1
  • VIEW 2,792

daaaisuke

score 32

前提・実現したいこと

arduinoで読み取ったセンサの情報をunityに送りたい
BytesToReadという受信したデータのbyte数を返すプロパティを使って分岐をしようとしている

発生している問題・エラーメッセージ

BytesToReadの値が0になってしまう
ardunioからシリアルポートに値を送れていることは確認済み
しかしunityでBytesToReadを使用すると受信データは0byteになってる。

該当のソースコード

unity

using UnityEngine;//unityのデフォルトの機能を使うためのクラス
using System.Collections;//C#の機能を使うためのクラス?
using System.IO.Ports;//下2つはシリアル通信を行うためのクラス
using System.Threading;//マルチスレッドを可能にするためのクラス

public class SerialHandler : MonoBehaviour
{
    public delegate void SerialDataReceivedEventHandler(string message);//デリゲートの宣言
    public event SerialDataReceivedEventHandler OnDataReceived;//ondatereceivedっていうイベントを作っていると思われる。

    public string portName = "/dev/cu.usbmodem1411";//arduino側と同じシリアルポートを入れる
    public int baudRate = 9600;//arduino側と同じボーレートを入れる

    private SerialPort serialPort_;//serial portクラスのインスタンス生成
    private Thread thread_;//スレッドクラスのインスタンス生成
    private bool isRunning_ = false;//シリアルポートが開いているかどうか

    private string message_;//
    private bool isNewMessageReceived_ = false;//シリアルポートから値が送られてきているかどうか

    private Object lock_object_ = new Object();


    void Awake()//SerialHandlerインスタンス生成後すぐに実行される関数
    {
        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_.Open();//シリアルポートを開いて
        serialPort_.ReadTimeout = 1;

        isRunning_ = true;//開いた証としてtrueに変更

        thread_ = new Thread(Read);//新しいスレッドを作成してread関数を実行させる
        thread_.Start();//thread開始
    }

    private void Close()
    {
        isRunning_ = false;//シリアルポートを閉じた証としてfalseに変更

        if (thread_ != null && thread_.IsAlive) {//threadが存在しているなら
            thread_.Join();//元のスレッドの統合
        }

        if (serialPort_ != null && serialPort_.IsOpen) {//シリアルポートにインスタンスが格納されていて、シリアルポートが開いていれば
            serialPort_.Close();//シリアルポートを閉じる
            serialPort_.Dispose();//よくわからない
        }
    }

    private void Read()
    {
        while (isRunning_ && serialPort_ != null && serialPort_.IsOpen) {//シリアルポートが開いているかつシリアルポートインスタンスが存在する
            // System.Threading.Thread.Sleep(100);
            Debug.LogFormat("bytes to read:{0}", serialPort_.BytesToRead);
            if (serialPort_.BytesToRead > 0) {//受信したデータがあったら
                lock (lock_object_) {
                    message_ = serialPort_.ReadLine();//一行ずつデータを読み込む
                    Debug.Log("message_="+message_);
                    isNewMessageReceived_ = true;//メッセージを受け取った証として変更
                }
            }
        }
    }

    public void Write(string message)
    {
        serialPort_.Write(message);//メッセージをシリアルポートで送る
    }
}

arduino

#include "CurieIMU.h"//Genuino101の加速度センサを使用するためのライブラリをインクルード

namespace {
const int AVERAGE_NUM = 10;//値をある程度均一化するための数字
const int adjustX = 5;//センサの値を調整するための定数、水平面に置いた時のズレの値
const int adjustY = -2;
const int adjustZ = -1;
}

void setup()
{
  Serial.begin(9600);//シリアル通信スタート
  // IMUセッティング----------------------------------------
  CurieIMU.begin();//加速度センサ起動
  CurieIMU.setAccelerometerRange(2);//加速度センサのレンジ(測定範囲)の設定
}

void loop()
{
  delay(16);//fps60程度に調整
  readAccelerometer();
  setLed();

}


//function----------------------------------------------
void readAccelerometer()
{
  int axRaw = 0, ayRaw = 0, azRaw = 0; //加速度センサの値を受け取るための変数を用意
  CurieIMU.readAccelerometer(axRaw, ayRaw, azRaw);//加速度センサの値を読み取り格納
  int x = 0, y = 0, z = 0;//加速度センサの値を均した値を格納する変数を用意
  //値の平均化================================
  for (int i = 0; i < AVERAGE_NUM; ++i) {//AVERAGE_NUMで指定した数だけ加速度を測定して平均化する
    x += axRaw;
    y += ayRaw;
    z += azRaw;
  }
  x /= AVERAGE_NUM;
  y /= AVERAGE_NUM;
  z /= AVERAGE_NUM;

  //=========================================
  int angleX = map(axRaw, -16384, 16384, -90, 90); //センサで受け取った値を角度に変換
  int angleY = map(ayRaw, -16384, 16384, -90, 90);
  int angleZ = map(azRaw, -16384, 16384, -90, 90);

  angleX += adjustX;//角度を手動で調整
  angleY += adjustY;
  angleZ += adjustZ;

  Serial.print(angleX);
  Serial.print("\t");
  Serial.print(angleY);
  Serial.println("");
}

void setLed()
{
  if ( Serial.available() ) {
    char mode = Serial.read();
    switch (mode) {
      case '0' : digitalWrite(13, LOW);  break;
      case '1' : digitalWrite(13, HIGH); break;
    }
  }
}

試したこと

たまにbytestoreadの値が0以外になることがある。
シリアルポートのbpsは合わせてある。
unityのfpsに合わせてarduinoのfpsも約60に設定。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.22%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる