回答編集履歴
1
平滑化の修正追記
answer
CHANGED
@@ -6,4 +6,50 @@
|
|
6
6
|
最初はありえないほど小さな値にしておくか、それとも一番最初に取得舌データを入れておいて、
|
7
7
|
新しいデータが得られる度にその最大値を保持する変数と新しいデータとを比べて、
|
8
8
|
新しいデータの方が大きい値なら最大値を新しいデータで書き換えれば、
|
9
|
-
いいんじゃない?
|
9
|
+
いいんじゃない?
|
10
|
+
|
11
|
+
---
|
12
|
+
平滑化(移動平均)処理の誤りについて
|
13
|
+
|
14
|
+
平均ってどうやるか、これは言うまでもなく、要素全部の和/要素の数を計算すればいいわけです。
|
15
|
+
ここで、1023が150個あるはずの平均の計算が1023*151/150の値になったとすれば、「要素全部の和」が正しく求められているかをチェックする、というのが流れでしょう。
|
16
|
+
その計算は、
|
17
|
+
` for(int i=0;i<n;i++) sensorValue+=f[i];`
|
18
|
+
でやっているわけですがしかし、このループに入る前にsensorValueには
|
19
|
+
`sensorValue = analogRead(sensorPin);`
|
20
|
+
という値が与えられています。これによって1023が151個分足される、ということになるわけです。ここを修正する必要があります。
|
21
|
+
|
22
|
+
---
|
23
|
+
analogRead()は「実行したまさにそのときの値」
|
24
|
+
|
25
|
+
多分大問題にはならないでしょうけど...analogRead()は、そのときそのときのADコンバータの値を返してきます。電圧が変化していたなら2度連続で読んで、おなじ値になる保証はありません。
|
26
|
+
```
|
27
|
+
sensorValue = analogRead(sensorPin);//ここと
|
28
|
+
for(int i=n-1;i>0;i--)f[i]=f[i-1];
|
29
|
+
f[0]=analogRead(1);//ここ
|
30
|
+
```
|
31
|
+
温度のデータならこの短時間で大きく変化はしないだろう、というのは言えますけれど、一般論としてはよろしい手法ではないです。
|
32
|
+
```
|
33
|
+
int tmpValue= analogRead(sensorPin); //取得は一回だけ
|
34
|
+
sensorValue=tmpValue;
|
35
|
+
for(int i=n-1;i>0;i--)f[i]=f[i-1];
|
36
|
+
f[0]=tmpValue;
|
37
|
+
for(int i=1;i<n;i++) sensorValue+=f[i];
|
38
|
+
|
39
|
+
```
|
40
|
+
などとして、取得は一度だけにしておいた方がよいでしょう。
|
41
|
+
millis()による時間取得で似たようなことをやって、微妙なバグを生んでしまう例をみたことがあります。random()を何度も呼んでしまって動きが目茶苦茶になって...という質問も(ここではありませんが)先日ありました。この辺はバグが顕著に出やすいですね。
|
42
|
+
|
43
|
+
---
|
44
|
+
計算の改善案
|
45
|
+
|
46
|
+
150個分のデータを貯めておいて平均の計算をするわけですが、総和を求める際には別に計算の順序はどうでも良くて、直近150個分のデータをとにかく足せばいいわけです。150個の配列は、先頭から順に新しいデータが並んでいる必要はありません。なので、一個ずつデータにお詰め合わせを願って先頭に最新のデータを置く、なんてやらずに、
|
47
|
+
`int i=0;`
|
48
|
+
をグローバル変数に追加して
|
49
|
+
```
|
50
|
+
sensorValue=0;
|
51
|
+
f[i]=analogRead(sensorPin);
|
52
|
+
i= (i+1) % n;//この計算によりiは0,1,..,149,0,1,...を繰り返すことになる
|
53
|
+
for(int j=0;j<n;j++) sensorValue+=f[j]; //変数はiのままでもいいんだけど、わざわざ紛らわしいことはしない
|
54
|
+
```
|
55
|
+
で十分かと思います。
|