Arduino用の信号平滑化ライブラリはありますか?


14

ワイヤレス2.4 GHzリンクを介して制御されるモバイルロボットで作業しています。受信機は、メインコントローラーとしてオンボードで機能するArduino Unoに接続されています。レシーバーから来る最も重要な(およびメインの)入力チャンネルは、非常にノイズの多い信号を生成します。これにより、アクチュエーターの出力は、不要であるにもかかわらず、多くの小さな変化につながります。

ここに画像の説明を入力してください
                    30秒間隔でのArduinoの入力のプロット。

効率的なスムージングを実行できるライブラリを探しています。Arduino(Uno)で使用できる信号平滑化ライブラリはありますか?


この種のライブラリを見つけることができるかどうかはわかりませんが、Arduinoにはこれらのライブラリに多くのCPUパワーが必要になる可能性があると思います。可能であれば、電子的なソリューション(ローパスフィルター)を使用したいです。
jfpoilpret 14

これについてはjfpoilpretを使用しています。電子ソリューションが必要だと思います。安定化コンデンサ(単純なローパスフィルター)を試します。ADCチャネルを使用していると想定しているため、このチャネルからグランドにキャップを付ける必要があります。100pf前後の値から始めて、そこから調整します。
ジョンb 14年

回答:


8

Microsmoothは、私が現在開発している軽量の信号平滑化ライブラリです。

それはまだ作業中であり、目的はメモリの観点から軽量で高速にすることです。ライブラリには、平滑化のための複数のフィルターが用意されています。

  • 単純移動平均
  • 指数移動平均
  • 累積移動平均
  • Savitzky Golayフィルター
  • Ramer Douglas Peckerアルゴリズム
  • カルモゴロフズルベンコフィルター

ライブラリを使用するには、ダウンロードしてソースディレクトリに追加します。また、ソースファイルに次の行を追加します。

#include "microsmooth.h"

こんにちは、ライブラリの使用に問題があります。ライブラリをインポートするために「ライブラリをインポート...」を使用しませんか?ソースを.inoフォルダーにコピーしようとしましたが、automicrosmooth.hが見つからない、シリアルが定義されていない、「;」が見つからないというエラーが表示されます。このライブラリはまだ機能していますか?おかげで
waspinator

@waspinatorそれについてすみません。エラーを修正しました。フィードバックをお寄せいただきありがとうございます!
-asheeshr

7

ノイズの多い信号には、単一サンプルのノイズスパイクが多く見られます。

中央値フィルターは、線形フィルターよりも単一サンプルのノイズスパイクを取り除くのに適しています。(応答時間とそのような単一サンプルノイズスパイクの外れ値を無視する能力の点で、ローパスフィルター、移動平均、加重移動平均などよりも優れています)。

実際、Arduinoには多くのシグナルスムージングライブラリがあり、その多くにはメディアンフィルターが含まれています。

arduino.ccの信号平滑化ライブラリ:

githubのシグナルスムージングライブラリ:

このようなものはロボットで動作しますか?(3の中央値は、CPUパワーをほとんど必要としないため、高速です):

/*
median_filter.ino
2014-03-25: started by David Cary
*/

int median_of_3( int a, int b, int c ){
    int the_max = max( max( a, b ), c );
    int the_min = min( min( a, b ), c );
    // unnecessarily clever code
    int the_median = the_max ^ the_min ^ a ^ b ^ c;
    return( the_median );
}

int newest = 0;
int recent = 0;
int oldest = 0;

void setup()
{
    Serial.begin(9600);
    // read first value, initialize with it.
    oldest = random(200);
    recent = oldest;
    newest = recent;
    Serial.println("median filter example: ");
}

void loop()
{
    // drop oldest value and shift in latest value
    oldest = recent;
    recent = newest;
    newest = random(200);

    Serial.print("new value: ");
    Serial.print(newest, DEC);

    int median = median_of_3( oldest, recent, newest );

    Serial.print("smoothed value: ");
    Serial.print(median, DEC);
    Serial.println("");

    delay(5000);
}

4

ローパスフィルターを試しましたか?私は例見つけ、ここでもう一つ、ここを

これらのライブラリには両方とも、選択したアナログセンサーから読み取られるデータのリストがあり、平均化されています。新しいセンサー値はすべてリストに追加され、次のように最後のセンサー値がスローされます。

List: 3 4 3 3 4 3 5 3 2 3 4 3 
new reading added. old one thrown out
      /--                     /--
List: 5 3 4 3 3 4 3 5 3 2 3 4
list averaged

単純なFIRフィルターがすべてのタップ値を1に設定して行うこととほぼ同じことです。タップ値をいじると、信号はさらに改善されますが、より高い数学が必要になります。
ジッピー14

注:2番目のリンクは累積移動平均を計算しますが、これはアクチュエータ制御、特に頻繁な開始と停止を伴う可能性のあるものの実用的な選択ではありません。平滑化された信号は、常に実際の信号のピーク値にかなりのマージンで追従します。
アヒーシュ14

2

ローパスフィルターを使用して、これをデジタルでフィルター処理できます。

int valueFilt = (1-0.99)*value + 0.99*valueFilt;

0.99を変更して、カットオフ周波数を変更します(1.0に近いほど周波数が低くなります)。その値の実際の式はexp(-2 * pi * f / fs)です。ここで、fは必要なカットオフ周波数、fsはデータがサンプリングされる周波数です。

別のタイプの「デジタルフィルター」は、イベントフィルターです。外れ値のあるデータでうまく機能します。例えば9,9,8,10,9,25,9。イベントフィルターは、最も頻繁な値を返します。統計的にこれがモードです。

平均、モードなどの統計平均は、Arduino Average Libraryを使用して計算できます。

Arduinoライブラリページから引用した例:

#include <Average.h>
#define CNT 600
int d[CNT];

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  int i;

  for(i=0; i<CNT; i++)
  {
    d[i] = random(500);
  }  

  Serial.print("Mean: ");
  Serial.print(mean(d,CNT),DEC);
  Serial.print(" Mode: ");
  Serial.print(mode(d,CNT),DEC);
  Serial.print(" Max: ");
  Serial.print(maximum(d,CNT),DEC);
  Serial.print(" Min: ");
  Serial.print(minimum(d,CNT),DEC);
  Serial.print(" Standard deviation: ");
  Serial.print(stddev(d,CNT),4);
  Serial.println("");
  Serial.println("");

  delay(5000);
}

1
これは非常に遅いことに注意してください。フロートとバックに多くの暗黙的なキャストを行うためです。
コナーウルフ14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.