teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

追記1

2020/10/21 12:36

投稿

nac_tnk
nac_tnk

スコア512

answer CHANGED
@@ -10,4 +10,91 @@
10
10
  今後の事を考えれば、ポーリングでリモコン受信させた方が良さそうには思いますけど…
11
11
  いずれにしても、現在のサーボ処理のスケッチは割り込み処理の形(カウントして計測する)に変える事になると思います。
12
12
 
13
- ※VarSpeedServoライブラリが裏でタイマ1を使い、タイマ割り込みで動作している、という事も頭に入れておいてください。
13
+ ※VarSpeedServoライブラリが裏でタイマ1を使い、タイマ割り込みで動作している、という事も頭に入れておいてください。
14
+
15
+
16
+ <追記1>
17
+ 外部割り込みでリモコン取得も、開始信号から信号最期、或いはエラーまで専有するやり方と、毎回時間を計測して、直ぐに終了するやり方があると思うけど、
18
+ 前者なら、現在のスケッチからの変更は少ないです。けれども、他の動作に支障が出やすいです。
19
+ 後者なら、書き直しになりますけど、こちらの方がベーシックなやり方だと思いますし、他のスケッチと共存し易いです。
20
+
21
+ で、後者の方を教えます。
22
+
23
+ まず、リモコン通信のフォーマットを確認して下さい。
24
+ ChaNさんの所が参考になります。http://elm-chan.org/docs/ir_format.html
25
+
26
+ そこに書いてあるようにNECフォーマットの場合は562μsが基準となり、信号の長さで0と1が決まります。
27
+ 受信側からけば、HIGHの長さが基本ですから、HIGHの長さだけ測っておけばいいです。
28
+ ※送信信号が有る時は、受信側はLOWです。何もないときはHIGHです。その図からは反転します。
29
+  (といっても、受信側の回路にもよりますけど)
30
+
31
+ 考え方は、HIGHになった時に、測定開始時刻を記録、LOWになった時に、HIGHの時間を算出。
32
+ その時間が、ちゃんとフォーマットの通りに来ていれば記録を続けるけれども、一度でも範囲外なら、そこまでのデータは捨てます。
33
+ で、32bit分送られて来たら、どのSWかの判定です。
34
+
35
+ 実際のRAWデータで、どの位の時間なのかを確認した方が良いです。案外いい加減なものですから、範囲を外している場合があります。
36
+
37
+ ↓が外部割り込み関数のサンプルです。
38
+ ※つらつらと書いただけで、検証はしていません。内容を読み取ってください。
39
+
40
+ ```Arduino
41
+ volatile byte ir_num=0;//割り込みとloop関数両方で参照する変数は外部変数で、volatileを付ける。
42
+
43
+ void recv() {//外部割り込み関数
44
+ static byte state=0;//0:測定前、1~:受信中
45
+ static uint32_t up=0,length=0,result=0;
46
+
47
+ if(digitalRead(pin))up=micros();
48
+ else {
49
+ length=micros()-up;
50
+ if(length>4000 &&length>5000)state=1;//開始条件8T=4496
51
+ else if(state) {
52
+ if(length>460 && length<760)state++;//T=562
53
+ else if(length>1400 && length<1900) {//3T=1686
54
+ result|=(0x80000000UL>>(state-1));
55
+ state++;
56
+ } else {//範囲外ならやり直し
57
+ state=0;
58
+ result=0;
59
+ }
60
+ if(state==33) {//データが揃ったら
61
+ switch (result) {
62
+ case 0xFF0CF30D:
63
+ ir_num=1;
64
+ break;
65
+ case 0xFF18E718:
66
+ ir_num=2;
67
+ break;
68
+ case 0xFF5EA15E:
69
+ ir_num=3;
70
+ break;
71
+ default:
72
+ ir_num=4;
73
+
74
+ }
75
+ state=0;
76
+ result=0;
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ ```
83
+
84
+ で、この結果(ir_num)を受けて、サーボを操作するわけですけど、リモコン信号が来た場合に、
85
+ ・即時に停止、或いは次の動作へ移行。(停止の場合はその場に停止か、HOME位置へ戻すか?)
86
+ ・サイクルを実行してから次の動作平行
87
+ があると思います。
88
+ (現在はサイクルな訳ですけど。その場合、ちゃんと受信しているのか判りにくくなります。
89
+ 今回のトグル動作とかも、長いサイクルの場合は判り難く、2回押す事も考えられます)
90
+
91
+ もう一点、現在、myservo○.write(○,○,true);(終わるまで待機)を使っていますけど、
92
+ 1台のサーボなら兎も角、複数だと、1台ずつしか動かせません。
93
+ 本当にそれで良いのでしょうか?
94
+
95
+ (つまり、現在のスケッチが、狙い通りの動きなのか、書き方が判らないからそうなっているのかが判断付きません)
96
+
97
+ 処理的には複雑にはなりますけど、2台を別のタイミングでそれぞれ同時に操作する事は可能です。
98
+
99
+ そのあたりをちょっと聞いてから追記します。
100
+ ※「sw1で停止」のみの対応なら簡単です。