質問編集履歴

2

回答が来なかったためコードを乗せた。言い回しを変えた

2016/09/29 11:32

投稿

daaaisuke
daaaisuke

スコア34

test CHANGED
@@ -1 +1 @@
1
- serialportが止まってしまう件について(Unity)
1
+ Unityの再生ボタンを押すとシリアル通信が止まってしまう
test CHANGED
@@ -1,8 +1,8 @@
1
1
  ###前提・実現したいこと
2
2
 
3
- Arduinoのセンサの値をUnityに送ってビジュアライズしたいと考えています。
3
+ Arduinoのセンサの値をUnityに送ってセンサの値をビジュアライズしたいと考えています。
4
-
4
+
5
- 通信規格はシリアルポートを使用しているのですが、その最中にどうしてもわからないことがありました。
5
+ シリアルポートを使用しているのですが、その最中にどうしてもわからないことがありました。
6
6
 
7
7
 
8
8
 
@@ -12,15 +12,375 @@
12
12
 
13
13
 
14
14
 
15
+ ###問題のコード
16
+
17
+ Unity側
18
+
19
+ ```C#
20
+
21
+ using UnityEngine;//unityのデフォルトの機能を使うためのクラス
22
+
23
+ using System.Collections;//C#のデフォルト機能を使うためのクラス
24
+
25
+ using System.IO.Ports;//シリアル通信を使用するためのクラス
26
+
27
+ using System.Threading;//スレッド機能を利用可能にするためのクラス
28
+
29
+
30
+
31
+ public class SerialHandler : MonoBehaviour
32
+
33
+ {
34
+
35
+ public delegate void SerialDataReceivedEventHandler(string message);//SerialDataReceivedEventHandlerというデリゲート(関数を入れる変数)の宣言
36
+
37
+ public event SerialDataReceivedEventHandler OnDataReceived;//OnDataReceivedという名前のデリゲートを生成
38
+
39
+
40
+
41
+ public string portName = "/dev/cu.usbmodem1411";//arduino側と同じシリアルポートを入れる
42
+
43
+ public int baudRate = 9600;//arduino側と同じボーレートを入れる
44
+
45
+
46
+
47
+ private SerialPort serialPort_;//serial portクラスのインスタンス生成
48
+
49
+ private Thread thread_;//スレッドクラスのインスタンス生成
50
+
51
+
52
+
53
+ private bool isRunning_ = false;//シリアルポートが開いているかどうか
54
+
55
+ private bool isNewMessageReceived_ = false;//シリアルポートから値が送られてきているかどうか
56
+
57
+
58
+
59
+ private byte message_b;//シリアル通信で送られてきたデータを格納する変数
60
+
61
+ private char message_c;//シリアル通信で送られてきたデータを格納する変数
62
+
63
+ private string text_="";//message_cを溜める場所
64
+
65
+
66
+
67
+ private Object lock_object_ = new Object();//?
68
+
69
+
70
+
71
+
72
+
73
+ void Awake()//このスクリプトのインスタンス生成後,つまり一番最初に実行される関数
74
+
75
+ {
76
+
77
+ Open();
78
+
79
+ serialPort_.ReadTimeout = 1;
80
+
81
+ }
82
+
83
+
84
+
85
+ void Update()
86
+
87
+ {
88
+
89
+ if (isNewMessageReceived_) {//値が送られてきたら
90
+
91
+ OnDataReceived(text_);
92
+
93
+ isNewMessageReceived_ = false;
94
+
95
+ text_="";
96
+
97
+ }
98
+
99
+ }
100
+
101
+
102
+
103
+ void OnDestroy()//ゲーム終了時に一度だけ呼び出される
104
+
105
+ {
106
+
107
+ Close();
108
+
109
+ }
110
+
111
+
112
+
113
+
114
+
115
+
116
+
117
+
118
+
119
+ private void Open()//シリアルポートを開いて、新しいスレッドを開く
120
+
121
+ {
122
+
123
+ serialPort_ = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);//シリアルポートインスタンス生成
124
+
125
+ serialPort_.Open();//シリアルポートを開く
126
+
127
+
128
+
129
+ isRunning_ = true;//開いた証としてtrueに変更
130
+
131
+
132
+
133
+ thread_ = new Thread(Read);//新しいスレッドを作成してread関数を実行させる
134
+
135
+ thread_.Start();//thread開始
136
+
137
+ }
138
+
139
+
140
+
141
+ private void Close()
142
+
143
+ {
144
+
145
+ isRunning_ = false;//シリアルポートを閉じた証としてfalseに変更
146
+
147
+
148
+
149
+ if (thread_ != null && thread_.IsAlive) {//threadが存在しているなら
150
+
151
+ thread_.Join();//元のスレッドの統合
152
+
153
+ }
154
+
155
+
156
+
157
+ if (serialPort_ != null && serialPort_.IsOpen) {//シリアルポートにインスタンスが格納されていて、シリアルポートが開いていれば
158
+
159
+ serialPort_.Close();//シリアルポートを閉じる
160
+
161
+ serialPort_.Dispose();//バッファの解放とか?
162
+
163
+ }
164
+
165
+ }
166
+
167
+
168
+
169
+ private void Read()
170
+
171
+ {
172
+
173
+ while (isRunning_ && serialPort_ != null && serialPort_.IsOpen) {//シリアルポートが開いているかつシリアルポートインスタンスが存在する
174
+
175
+ System.Threading.Thread.Sleep(100);
176
+
177
+ Debug.LogFormat("bytes to read:{0}", serialPort_.BytesToRead);
178
+
179
+ if (serialPort_.BytesToRead > 0) {//受信したデータがあったら
180
+
181
+ lock (lock_object_) {
182
+
183
+ Debug.Log("成功!!");
184
+
185
+ message_b = (byte)serialPort_.ReadByte();//一文字ずつデータを読み込む
186
+
187
+ message_c = (char)message_b;
188
+
189
+ text_ = text_ + message_c.ToString();
190
+
191
+ Debug.Log("message_b="+message_b);
192
+
193
+ Debug.Log("message_c="+message_c);
194
+
195
+ Debug.Log("text_="+text_);
196
+
197
+ if(message_b==10){
198
+
199
+ isNewMessageReceived_ = true;//メッセージを受け取った証として変更
200
+
201
+ }
202
+
203
+ }
204
+
205
+ }
206
+
207
+ }
208
+
209
+ }
210
+
211
+
212
+
213
+ public void Write(string message)
214
+
215
+ {
216
+
217
+ serialPort_.Write(message);//メッセージをシリアルポートで送る
218
+
219
+ }
220
+
221
+ }
222
+
223
+ ```
224
+
225
+ ```C++
226
+
227
+ #include "CurieIMU.h"//Genuino101の加速度センサを使用するためのライブラリをインクルード
228
+
229
+
230
+
231
+ namespace {
232
+
233
+ const int AVERAGE_NUM = 10;//値をある程度均一化するための数字
234
+
235
+ const int adjustX = 5;//センサの値を調整するための定数、水平面に置いた時のズレの値
236
+
237
+ const int adjustY = -2;
238
+
239
+ const int adjustZ = -1;
240
+
241
+ }
242
+
243
+
244
+
245
+ void setup()
246
+
247
+ {
248
+
249
+ Serial.begin(9600);//シリアル通信スタート
250
+
251
+ while (!Serial) {
252
+
253
+ ; // wait for serial port to connect. Needed for native USB port only
254
+
255
+ }
256
+
257
+ // IMUセッティング----------------------------------------
258
+
259
+ CurieIMU.begin();//加速度センサ起動
260
+
261
+ CurieIMU.setAccelerometerRange(2);//加速度センサのレンジ(測定範囲)の設定
262
+
263
+ }
264
+
265
+
266
+
267
+ void loop()
268
+
269
+ {
270
+
271
+ delay(16);//fps60程度に調整
272
+
273
+ readAccelerometer();
274
+
275
+ setLed();
276
+
277
+
278
+
279
+ }
280
+
281
+
282
+
283
+
284
+
285
+ //function----------------------------------------------
286
+
287
+ void readAccelerometer()
288
+
289
+ {
290
+
291
+ int axRaw = 0, ayRaw = 0, azRaw = 0; //加速度センサの値を受け取るための変数を用意
292
+
293
+ CurieIMU.readAccelerometer(axRaw, ayRaw, azRaw);//加速度センサの値を読み取り格納
294
+
295
+ int x = 0, y = 0, z = 0;//加速度センサの値を均した値を格納する変数を用意
296
+
297
+ //値の平均化================================
298
+
299
+ for (int i = 0; i < AVERAGE_NUM; ++i) {//AVERAGE_NUMで指定した数だけ加速度を測定して平均化する
300
+
301
+ x += axRaw;
302
+
303
+ y += ayRaw;
304
+
305
+ z += azRaw;
306
+
307
+ }
308
+
309
+ x /= AVERAGE_NUM;
310
+
311
+ y /= AVERAGE_NUM;
312
+
313
+ z /= AVERAGE_NUM;
314
+
315
+
316
+
317
+ //=========================================
318
+
319
+ int angleX = map(axRaw, -16384, 16384, -90, 90); //センサで受け取った値を角度に変換
320
+
321
+ int angleY = map(ayRaw, -16384, 16384, -90, 90);
322
+
323
+ int angleZ = map(azRaw, -16384, 16384, -90, 90);
324
+
325
+
326
+
327
+ angleX += adjustX;//角度を手動で調整
328
+
329
+ angleY += adjustY;
330
+
331
+ angleZ += adjustZ;
332
+
333
+
334
+
335
+ Serial.print(angleX);
336
+
337
+ Serial.print("\t");
338
+
339
+ Serial.print(angleY);
340
+
341
+ Serial.println("");
342
+
343
+ }
344
+
345
+
346
+
347
+ void setLed()
348
+
349
+ {
350
+
351
+ if ( Serial.available() ) {
352
+
353
+ char mode = Serial.read();
354
+
355
+ switch (mode) {
356
+
357
+ case '0' : digitalWrite(13, LOW); break;
358
+
359
+ case '1' : digitalWrite(13, HIGH); break;
360
+
361
+ }
362
+
363
+ }
364
+
365
+ }
366
+
367
+
368
+
369
+ ```
370
+
371
+
372
+
373
+
374
+
15
375
  ###試したこと
16
376
 
17
- ターミナルcat /dev/cu.usbmodem1411コマンドを入力して、Arduino側から値が送られてきているのを確認しながらUnityを再生。
377
+ ターミナルcatコマンド、Arduino側から値が送られてきているのを確認しながらUnityを再生。
18
-
378
+
19
- →ターミナルで値が送られてこなくなったのを確認
379
+ →ターミナルで値が送られてこなくなった?シリアルポートが止まった?のを確認
20
-
21
-
22
-
380
+
381
+
382
+
23
- UnityからArduinoへのデータ正常行われを確認済み
383
+ このことからarduinoからPCに値をることできているが、ソフトウェア側何らかの問題があり、再生と同時にシリアルポートが止まっていのではないか考えた。
24
384
 
25
385
 
26
386
 
@@ -28,4 +388,6 @@
28
388
 
29
389
  ###補足情報
30
390
 
391
+ たまにデータが最初の数バイトのみ送られてくる現象を確認。
392
+
31
- たまにデータが最初の数バイトのみ送られてくる現象を確認しかし、unity側でシリアルポートを開くタイミングとArduino側で値が送られてくるタイミングの兼ね合いによって起こるものと考えられる
393
+ しかし、unity側でシリアルポートを開くタイミングとArduino側で値が送られてくるタイミングの兼ね合いによって起こるもので、問題の根本は同じものであるのではないかと考えています

1

補足情報の追加

2016/09/29 11:32

投稿

daaaisuke
daaaisuke

スコア34

test CHANGED
File without changes
test CHANGED
@@ -20,8 +20,12 @@
20
20
 
21
21
 
22
22
 
23
+ UnityからArduinoへのデータ送信は正常に行われることを確認済み
23
24
 
24
25
 
26
+
27
+
28
+
25
- ###補足情報(言語/FW/ツール等のバージョンなど)
29
+ ###補足情報
26
30
 
27
31
  たまにデータが最初の数バイトのみ送られてくる現象を確認しかし、unity側でシリアルポートを開くタイミングとArduino側で値が送られてくるタイミングの兼ね合いによって起こるものだと考えられる。