回答編集履歴

2

誤記修正

2021/12/23 23:43

投稿

thkana
thkana

スコア7703

test CHANGED
@@ -66,7 +66,7 @@
66
66
 
67
67
  0xff 0xff D0L D0H D1L D1H D2L D2H
68
68
 
69
- というのが一組のデータという規則にすれば、4以下(前回のD3H)、0xff, 0xffというデータ並びを見つければその次がD0Lという期待はまぁ正当でしょう(単純に0xff 0xffの並びだけを探してしまうと、D0Lが0xffになる可能性があるので誤検出が考えられます)。9600bpsで1byteの伝送に1msかかるとして、64Hz=15.6ms周期に8byte=8msのデータ量ですから収まります。
69
+ というのが一組のデータという規則にすれば、4以下(前回のD2H)、0xff, 0xffというデータ並びを見つければその次がD0Lという期待はまぁ正当でしょう(単純に0xff 0xffの並びだけを探してしまうと、D0Lが0xffになる可能性があるので誤検出が考えられます)。9600bpsで1byteの伝送に1msかかるとして、64Hz=15.6ms周期に8byte=8msのデータ量ですから収まります。
70
70
 
71
71
 
72
72
 

1

方法提案

2021/12/23 23:43

投稿

thkana
thkana

スコア7703

test CHANGED
@@ -19,3 +19,99 @@
19
19
  ```
20
20
 
21
21
  なぜ12バイト以上のデータの受信を確認したあとで6バイトの受信を行う仕組みになっているのですか?
22
+
23
+
24
+
25
+ ---
26
+
27
+ 自己解決にするとのことですがまぁとっかかりだけでも。
28
+
29
+
30
+
31
+ D0L D0H D1L D1H D2L D2H D0L D0H D1L D1H ...
32
+
33
+ とダラダラ並んでいるだけのデータ列では、取りこぼしがあって例えばD0Hが抜けたときに受信側が
34
+
35
+ (D0L D1L) (D1H D2L) (D2H D0L)
36
+
37
+ のようなペアで解釈してしまうとデータは滅茶苦茶になって自力では復帰できません。
38
+
39
+ あるいは、たまたま受信を開始したのが途中からで
40
+
41
+ D2L D2H D0L D0H D1L D1H ...
42
+
43
+ と受信していれば、受信側はD0のつもりでD2を(以下順次ズレて再起不能)得てしまうことになります。
44
+
45
+
46
+
47
+ 要は、通信データ列(だけ)を見てどれが1つ目、2つ目、3つ目のデータか認識できるように考えれば(送受信間の通信の約束=プロトコルを決めれば)いいわけです。
48
+
49
+
50
+
51
+ データ間隔が大きく空いているなら、
52
+
53
+ D0L D0H D1L D1H D2L D2H [間隔]
54
+
55
+ の間隔時間を測ることによってデータの区切りを知ることができますが、今回は64Hz=15ms周期とのことで、Processingのdraw()繰り返し実行のデフォルト周期(60Hz)との絡みもあって検出は難しいですね
56
+
57
+
58
+
59
+ となると、データ列に「位置を知るための特殊なデータ」を埋め込むことで位置を知るという方法が考えられるでしょう。テキストデータであれば、データ本体には登場しない改行コードであるとか','とかをデータ区切りに使うというのはよくあるパターンではありますが、今回はバイナリデータなのでちょっと考える必要があります。
60
+
61
+
62
+
63
+ Arduino UNO(ただArudinoとだけいう名前の機種はありません。原則としてArduinoのナニなのかを明示するようにしてください)のADCは10bitですから、高位側のデータは(特に加工していなければ)4以上にはなりません。つまり、4以上のデータが2つ続けば「それは特殊なデータだ」と知ることができるわけです。
64
+
65
+ 例えば、
66
+
67
+ 0xff 0xff D0L D0H D1L D1H D2L D2H
68
+
69
+ というのが一組のデータという規則にすれば、4以下(前回のD3H)、0xff, 0xffというデータ並びを見つければその次がD0Lという期待はまぁ正当でしょう(単純に0xff 0xffの並びだけを探してしまうと、D0Lが0xffになる可能性があるので誤検出が考えられます)。9600bpsで1byteの伝送に1msかかるとして、64Hz=15.6ms周期に8byte=8msのデータ量ですから収まります。
70
+
71
+
72
+
73
+ ```Processing
74
+
75
+ //D0Lの頭出しをするループ(動作チェック等はしていません)
76
+
77
+ byte head0,head1;
78
+
79
+ boolean found_FF=false;
80
+
81
+ head0=0;//仮データ
82
+
83
+ while(true){
84
+
85
+ if(port.available()){
86
+
87
+ head1=port.read();//2byte目受信
88
+
89
+ if(found_FF && head1=0xff){ //D2L,0xff,0xffのパターンを見つけた。次はD0L
90
+
91
+ break;
92
+
93
+ }
94
+
95
+ found_FF=(head0<4 && head1==0xff);//4以下-0xffのシーケンス発見
96
+
97
+ head0=head1;//今回の2byte目は次回シーケンスの1byte目
98
+
99
+ }
100
+
101
+ }
102
+
103
+ //頭出しができているので安心して取得
104
+
105
+ if(port.available()>=6){
106
+
107
+ for ( i = 0; i < 3; i++ ) {
108
+
109
+ data[i] = port.read() + port.read() * 256 ;
110
+
111
+ }
112
+
113
+ }
114
+
115
+ ```
116
+
117
+ のように処理すれば、何らかのズレが発生したときにも次回には修正されることになるかと思いますがいかが。(もちろん送信側にも0xff 0xffを送る処理を追加する必要があります)