1

一部のセンサーデータを平滑化するプログラムを作成しようとしています。

センサーは 0 ~ 100 のしきい値入力を提供します。通常は 2 単位程度の精度ですが、読み取りごとに不安定です。

1 秒間に何度も入力を取得し、このデータからそれほど急激ではない動的平均を作成したいと考えています。

最近の入力を平均化して、滑らかに変化する数値、より正確な数値 (測定値にリアルタイムで対応する) をインターフェイスに表示するにはどうすればよいでしょうか?

助けてくれてありがとう。

4

2 に答える 2

3

データに応じて、平均を計算して測定値を平準化できます。

  • 一定数の以前の結果を使用する

    int values[BUFLEN];
    value = // your new raw measured value
    
    index = index++ % BUFLEN;
    values[index] = value;
    
    avg = 0;
    for(int i=0; i<BUFLEN; i++) {
        avg = avg + values[i] / BUFLEN;  // evenly weighted
    }
    

    必要に応じて、不均一なウェイトを使用することもできます。また、同じ重みを使用している場合は、このループを最適化できます。

  • 変動平均の使用

    avg = (avg * 0.9) + (value * 0.1)  // slow response
    avg = (avg * 0.5) + (value * 0.5)  // fast response
    
    float q = // new ratio
    avg = (avg * (1.0 - q)) + (value * q)  // general solution
    

浮動平均 (数学的に) は、すべての要素の重み付き合計です。ここで、重みは q N-iです。ここNで、 は測定値の合計iで、 は要素の連続インデックスです。限られた数の要素だけでなく、すべての要素が平均に含まれます。

誤った測定の頻度、平均からの距離、(計算された) 測定が実際のプロセスに従うためにどのような反応を期待するかなどを確認できます。

また、離散値 (整数) がある場合は、丸めの使用に注意する必要があります。すべての計算を浮動小数点で行い、結果を最も近い整数に丸めることをお勧めします。ただし、次のラウンドのために、計算された平均を浮動小数点に格納します。

アップデート:

最新かつ正確であることについての質問を反映するには、次のようにします。

問題は、最新のデータが傾向を示しているのか、それとも読み間違いの結果なのか、わからないことです。例を示します。

SEQ1: 15 15 14 15 15 [10]  6  6  5  6  6 
SEQ2: 15 15 14 15 15 [10] 20 15 14 15 15

では、[10]各シーケンスの意味は次のとおりです。最初のシーケンスでは、深刻な動き、トレンドを表しています。2番目のものでは、それは単なる読み違いです。しかし、あなたが読んだばかりのとき[10]、あなたは次に何が起こるか分かりません. したがって、その読み取りの効果を遅らせる必要があります。そのため、最新ではありません。

同様に、計算値である平均値を使用しています。したがって、正確ではありません。

バランスのとれた状況です。値が最新であるほど、精度が低くなります (読み間違いが発生しやすくなります)。データが正確であるほど、遅延は大きくなります。データ系列に基づいて、賢明に選択する必要があります。

2 番目の (変動平均) アルゴリズムを使用して、3 つのシナリオを計算しました。の値は、 lazynormal、またはeagerqに設定されています。

SEQ1:     15    15    14    15    15    10     6     6     5     6     6 
// q=0.25, "lazy"
Avg       15.00 15.00 14.75 14.81 14.86 13.64 11.73 10.30  8.98  8.23  7.67
Rounded   15    15    15    15    15    14    12    10     9     8     7   

// q=0.5, "normal"
Avg       15.00 15.00 14.50 14.75 14.88 12.44  9.22  7.61  6.30  6.15  6.08
Rounded   15    15    15    15    15    12     9     7     6     6     6

// q=0.75, "eager"
Avg       15.00 15.00 14.25 14.81 14.95 11.23  7.31  6.33  5.33  5.83  5.96
Rounded   15    15    14    15    15    11     7     6     5     5     6

遅延6計算は5 回の繰り返し後もまだ到達していないことがわかります。おそらくあと 3 回必要です。

法線はほとんどエラーを起こしにくいものではありませんでしたが (14.5 は端数を切り上げただけです)、すぐに傾向を追うことができました。

熱心な人は熱心に対策をたどり、曲線にわずかな緩和を追加しました. 15-14-15 の誤読も検出できませんでした。

上記のシリーズの最高の価値は約でしょう0.4-0.45私は思います. 実際の測定データのサンプルを試して、どのパラメーター値の動作がどのようなものかを確認することは価値があります。

実際、私のお気に入りは浮動平均アルゴリズムです。実装が簡単で、適切にパラメータ化されていれば、良い結果が得られます。

于 2013-10-16T13:22:17.220 に答える
1

免責事項:これにより、非常にスムーズな結果が得られます。この間に値が大幅に上下しても、直線が表示されるだけです。これは、時間の経過に伴う平均の変化を示します。これが望ましくない場合、この回答はおそらくあなたが望んでいるものではありません。

k最後の入力値を平均するとしましょう。

最初に注意すべきことは次のとおりです。

Average at time i = (value[i] + value[i-1] + ... + value[i-k+1]) / k
                  = value[i]/k + value[i-1]/k + ... + value[i-k+1]/k

and

Average at time i-1 = value[i-1]/k + value[i-2]/k + ... + value[i-k+2]/k

thus, cancelling out common terms...

Average at time i = Average at time i-1 + value[i]/k - value[i-k+2]/k

そして、潜在的な丸めの問題を回避するためにk、これによる除算を行わないようにしてください - 平均が得られたときにそれを行ってください (これを行っても数学が無効になることはありません)。

それでは、アルゴリズムに進みます。

  • size の循環配列を持っていますk。この配列のすべての値を 0 に初期化します。
  • 取り込まれた要素の数を保持します (0 に初期化されます)。
  • このバッファーに挿入するたびに、次のように平均を更新し
    average = newValue - overriddenValue
    ますk
  • 表示目的で平均を取得する場合は、それをカウントで割ります。
于 2013-10-16T13:43:04.657 に答える