回答編集履歴
1
平滑化の修正追記
test
CHANGED
@@ -15,3 +15,95 @@
|
|
15
15
|
新しいデータの方が大きい値なら最大値を新しいデータで書き換えれば、
|
16
16
|
|
17
17
|
いいんじゃない?
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
---
|
22
|
+
|
23
|
+
平滑化(移動平均)処理の誤りについて
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
平均ってどうやるか、これは言うまでもなく、要素全部の和/要素の数を計算すればいいわけです。
|
28
|
+
|
29
|
+
ここで、1023が150個あるはずの平均の計算が1023*151/150の値になったとすれば、「要素全部の和」が正しく求められているかをチェックする、というのが流れでしょう。
|
30
|
+
|
31
|
+
その計算は、
|
32
|
+
|
33
|
+
` for(int i=0;i<n;i++) sensorValue+=f[i];`
|
34
|
+
|
35
|
+
でやっているわけですがしかし、このループに入る前にsensorValueには
|
36
|
+
|
37
|
+
`sensorValue = analogRead(sensorPin);`
|
38
|
+
|
39
|
+
という値が与えられています。これによって1023が151個分足される、ということになるわけです。ここを修正する必要があります。
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
---
|
44
|
+
|
45
|
+
analogRead()は「実行したまさにそのときの値」
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
多分大問題にはならないでしょうけど...analogRead()は、そのときそのときのADコンバータの値を返してきます。電圧が変化していたなら2度連続で読んで、おなじ値になる保証はありません。
|
50
|
+
|
51
|
+
```
|
52
|
+
|
53
|
+
sensorValue = analogRead(sensorPin);//ここと
|
54
|
+
|
55
|
+
for(int i=n-1;i>0;i--)f[i]=f[i-1];
|
56
|
+
|
57
|
+
f[0]=analogRead(1);//ここ
|
58
|
+
|
59
|
+
```
|
60
|
+
|
61
|
+
温度のデータならこの短時間で大きく変化はしないだろう、というのは言えますけれど、一般論としてはよろしい手法ではないです。
|
62
|
+
|
63
|
+
```
|
64
|
+
|
65
|
+
int tmpValue= analogRead(sensorPin); //取得は一回だけ
|
66
|
+
|
67
|
+
sensorValue=tmpValue;
|
68
|
+
|
69
|
+
for(int i=n-1;i>0;i--)f[i]=f[i-1];
|
70
|
+
|
71
|
+
f[0]=tmpValue;
|
72
|
+
|
73
|
+
for(int i=1;i<n;i++) sensorValue+=f[i];
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
```
|
78
|
+
|
79
|
+
などとして、取得は一度だけにしておいた方がよいでしょう。
|
80
|
+
|
81
|
+
millis()による時間取得で似たようなことをやって、微妙なバグを生んでしまう例をみたことがあります。random()を何度も呼んでしまって動きが目茶苦茶になって...という質問も(ここではありませんが)先日ありました。この辺はバグが顕著に出やすいですね。
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
---
|
86
|
+
|
87
|
+
計算の改善案
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
150個分のデータを貯めておいて平均の計算をするわけですが、総和を求める際には別に計算の順序はどうでも良くて、直近150個分のデータをとにかく足せばいいわけです。150個の配列は、先頭から順に新しいデータが並んでいる必要はありません。なので、一個ずつデータにお詰め合わせを願って先頭に最新のデータを置く、なんてやらずに、
|
92
|
+
|
93
|
+
`int i=0;`
|
94
|
+
|
95
|
+
をグローバル変数に追加して
|
96
|
+
|
97
|
+
```
|
98
|
+
|
99
|
+
sensorValue=0;
|
100
|
+
|
101
|
+
f[i]=analogRead(sensorPin);
|
102
|
+
|
103
|
+
i= (i+1) % n;//この計算によりiは0,1,..,149,0,1,...を繰り返すことになる
|
104
|
+
|
105
|
+
for(int j=0;j<n;j++) sensorValue+=f[j]; //変数はiのままでもいいんだけど、わざわざ紛らわしいことはしない
|
106
|
+
|
107
|
+
```
|
108
|
+
|
109
|
+
で十分かと思います。
|