自作の可変両電源のAVRのプログラミングでは、移動平均をとるのと、ADCの変換中に他の処理をストップさせてノイズを減らすということをやったが、POTの読み取りごときでいちいち止めていられないので移動平均をとって改善するかどうか見ることにした。
「移動平均」というと何かかっこよさそうですが、前に読み取った値をいくつか覚えておいてその間の平均をとって今の値として採用するというだけ。
前作ったぴゅんぴゅんコントローラー2号で実験してみた。POT3個とアナログジョイスティック 1個(POTが縦横で2個)でアナログ素子は5個。Arduino 互換のHeaderのA0~A4につないだ。(タクトスイッチは使っていない。)
#include "mbed.h" class AverageAnalogIn { public: AverageAnalogIn(PinName _pin, int _bufferSize=16) : m_AnalogIn(_pin), bufferSize(_bufferSize), index(0) { buffer = new unsigned short[bufferSize]; } ~AverageAnalogIn() { delete buffer; } unsigned short read_u16() { buffer[index] = m_AnalogIn.read_u16(); index++; if (index == bufferSize) { index = 0; } unsigned int sum = 0; for (int i = 0; i < bufferSize; i++) { sum += buffer[i]; } return sum / bufferSize; } private: AnalogIn m_AnalogIn; int bufferSize; int index; unsigned short *buffer; }; AverageAnalogIn Pots[] = { AverageAnalogIn(A0, 4), AverageAnalogIn(A1, 8), AverageAnalogIn(A2, 16), AverageAnalogIn(A3, 32), AverageAnalogIn(A4, 64), }; #define POTS_SIZE (sizeof(Pots)/sizeof(Pots[0])) int main() { static uint16_t prevMeas[POTS_SIZE]; printf("\r\nAnalogIn example\r\n"); while(1) { unsigned int error = 0; for (int i = 0; i < POTS_SIZE; i++) { unsigned short meas = Pots[i].read_u16() >> 6; // 10bit width printf("%u,", meas); if (prevMeas[i] != meas) { prevMeas[i] = meas; error |= (1 << i); } } printf("%x\r\n", error); wait(0.01); // 10 ms } }
一応、C++らしくクラス化してみた。(ちゃんとテストしていないのでお気をつけて。)
<追記:2016.06.06>
早速ですが、デストラクタの「delete buffer」は「delete[] buffer」じゃないと作ったり壊したりしたらメモリー・リークする(^q^;
</追記>
オブジェクト指向というのは、STL(Windowsではないほう)、WindowsのMFC、DirectX、Java EEなどで使っていたのでどの流儀がいいのか記法レベルで迷う。組み込みだし、コストも気にしないといけないのでなかなか悩みどころが多い。
かと言って平文(?)でダラダラ書いてると、もう以前自分が何のつもりで書いてたのかわからなくなってきたので何か流儀を見つけないといけないなと思っています。
10bit精度で値のふらつきをみる。
AnalogInのread_u16は[0..0xFFFF]の値を返すので、ソースの通りunsigned 16bitで読み取った値を6bit右シフトして10bit精度に落としてCPLTでグラフ化してみた。
ch1(黒) | POT1 | 4個の平均 |
---|---|---|
ch2(青) | POT2 | 8個の平均 |
ch3(緑) | POT3 | 16個の平均 |
ch4(暗緑) | アナログジョイスティック | 32個の平均 |
ch5(赤) | アナログジョイスティック | 64個の平均 |
ch6(紫) | エラー値 |
グラフの一番下の棒グラフ状になっているところを見ると10bit精度では常に値が変動していそうだ。bitごとに1 or 0にしているので紫のグラフの背が高いところがエラーが多いというわけではない。
ch4(暗緑)は32個の平均をとって変動しているのに、64個の平均をとったch5(赤)はほぼ変動していない。
経験上このアナログジョイスティックは普通のPOTよりかなり精度が悪いのがわかっているので、64個も平均を取れば大体のPOTは大丈夫そうだ。
ただし、かなり反応が鈍くなる。
0 件のコメント:
コメントを投稿