直前の音の平均を得る

私は60秒ごとに音の入力を読んでいますが、ノンブロッキングコードを使ってその期間の音の平均を計算したいと思います。別のセンサーで何か他のことをする必要があるので、別の関数で計算する方法を変更するにはどうすればよいですか。

int calculateSoundValue(){
    int average = analogRead(0);
   //loop to calculate the average simple formula sum div nbr of calculated times
    return average;
}

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

}
void loop() {
 //I donùt wanna calculate the average inside a loop but instead inside a function 
  int value = calculateSoundValue();
  Serial.println(value);

  delay(600);
}

更新

これはあなたが意味することですか?

unsigned long previousMillis = 0;
const long interval = 6000;  
int totalSamples = 0; 
int count = 0

    int calculateSoundValue(){
        int sound = analogRead(0);
        totalSamples+= sound;
        count += 1;
        return totalSamples/count;
    }

void setup() {
 //set the digital pin as output:
  pinMode(ledPin, OUTPUT);
}

void loop() {

  unsigned long currentMillis = millis();
int totalSamples = 0; 
int count = 0
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

  }
      int value = calculateSoundValue();
      Serial.println(value);
}
0
@ user3378649:あなたはどのようなサウンドかわからないようです... analogRead()の信号の平均ではなく、上下の信号の変動ですその平均。あなたが得ることができる "音の平均"に最も近いのは、 RMS です= "https://en.wikipedia.org/wiki/Alternating_current" rel = "nofollow noreferrer"> AC の一部です。これをlow_pass(s​​quare(high_pass(s​​ignal)))として計算することができます。
追加された 著者 Sprogz,
平均がどのように計算されるか知っていますか?
追加された 著者 user67244,
あなたはどんな音であるか知っていますか?
追加された 著者 Majenko,
@RSMそれは古典的な XY問題です - 彼らは彼らが望むものとそれを達成する方法を知っていると思っていますが、その方法を実装する方法を試していますが、基本的な方法とその基本的な理解は完全に間違っています。したがって、実装しても実装することはできません。彼らは基本的に間違った質問をしています。
追加された 著者 Majenko,
@RSMそれは間違っているかもしれません;)それはOPに指示されていた...
追加された 著者 Majenko,
@RSMその後、平均はあなたが望むものではありません。あなたがしたいことは、継続的に耳を傾け、トリガーの閾値以上の音があるかどうかを瞬時に判断し、その事実を覚えておいてください - あなたが覚えているものそれに基づいて行動してください。
追加された 著者 Majenko,
平均的な音が何分になるかを教えてくれるファンシーなソフトウェアは必要ありません...答えはゼロです。
追加された 著者 Majenko,
@Majenko私はオーディオのものではありませんが、私は平均して時間の無駄であることに同意する、私は実装方法を考えていた。 OPは、ピーク検出器を使用することもできる。
追加された 著者 RSM,
@ user3378649あなたはミルis()関数を使用することができますノンブロッキングコードを作るために、ほとんどの遅延の例なしで瞬きを見てみましょう。遅れはあなたのコードをブロックするでしょう、私は、遅延が実行されているときにタイマ割り込みがまだ発生していることを知っています。また、60 * 1000mS = 1分。
追加された 著者 RSM,
@Majenkoその冷たい:)、それは私が明らかによりも思考をどのようにして、そしてOPはかなり忙しい受信トレイを持っています:)
追加された 著者 RSM,
@ user3378649あなたは、ノンブロッキングコードを利用したかったことを非常に明確にしていないので、それほど実用的ではなく、厳しいものではありませんでした。
追加された 著者 RSM,
sleep(600)が分からない、 delay()を意味しましたか?他のセンサーを使用するには、読み取り時に平均化するときにノンブロッキングコードを使用する必要があります。
追加された 著者 RSM,
@RSMあなたはUPDATEを確認できますか、あなたが提案したものを実装しようとしました。ダブルチェックし、私たちにあなたの提案を教えてください。
追加された 著者 Peter - Designer Drains,
@Majenko私は最後の1分間に運動があったかどうかを調べようとしています。サウンドセンサーを使用して
追加された 著者 Peter - Designer Drains,
@Avamander厳しい答え!いずれにせよ;あなたがarduinoに精通している場合には、ノンブロッキングの方法で平均を計算する方法を意味していたことを知っています。
追加された 著者 Peter - Designer Drains,
@RSMはい!それは私の質問の背後にあるポイントです。どのように私はそれを同時に非ブロッキングにすることができます、私は遅延をやっています
追加された 著者 Peter - Designer Drains,

3 答え

analogRead の平均実行時間を1分以上求めたいのですか?

これはどう?

unsigned long total;
unsigned int count;

unsigned long whenStarted;

const unsigned long INTERVAL = 60000; //one minute

void setup ()
{
  Serial.begin (115200);
  Serial.println (F("Starting ..."));
  whenStarted = millis ();
} //end of setup

void loop ()
{
 //one more sample
  total += analogRead (0);
  count++;

  if (millis() - whenStarted >= INTERVAL)//is a minute up?
    {
    Serial.print (F("Average = "));
    Serial.println (total/count);
    total = 0;
    count = 0;
    whenStarted = millis ();
    }
} //end of loop
1
追加された
...すでに指摘したように、測定値を平均しても何も役に立たない
追加された 著者 rossp,
ありがとう!私はtotal + = analogRead(0)を置くことができますか?カウント++;私が行ったようにを置き換えてください - あなたはそれが何を意味するのか分かりません。
追加された 著者 Nick Gammon,
ありがとう!私はtotal + = analogRead(0)を置くことができますか?カウント++;私のようにそれを交換してください
追加された 著者 Peter - Designer Drains,

The short answer is use millis() to keep track of time. You can also put all the time related stuff inside a class to have a nicely organized code. You can get more info about time management on the Arduino here. https://learn.adafruit.com/multi-tasking-the-arduino-part-1/ditch-the-delay

0
追加された
millis()ではなく、 micros()を意味します:ADCをオーディオ信号に関連するレートでサンプリングする場合は、 millis()十分に細かい解像度を提供しません。
追加された 著者 Sprogz,

あなたが実際に望むのは、音の強さを測定することです。これは あなたが読んだサンプルを単に平均化するよりもはるかに関わっています。私 数週間前にこれを正確に行うプログラムを書いています。 音の強さを測定し、その測定値を シリアルポート。それはあなたがかもしれないかなり短いプログラム(43行のコード)です あなたのニーズに適応することができるので、私は今GitHubの要点としてそれを共有しています: sound-meter.ino

これをリンク専用の回答にしないために、私は プログラムの内部の働き、そして音を測定する理論 Arduinoでの強さ。しかし、まずここに免責条項を入れておきます。 「実際の」騒音レベルメーターは、 いくつかの規格では、絶対レベルに較正する必要があります。 このプログラムは、どの周波数でも校正されていない読み取り値のみを提供します アナログハードウェアの応答です。

シグナルコンディショニング

Four measuring sound on an Arduino, you obviously need a microphone, but you also need some kind of interface circuit between the microphone and the Arduino. The purpose of the interface is to “condition the signal”, i.e. to make sure the Arduino gets a voltage in the proper range for it's analog-to-digital converter (ADC). It's typically an op-amp based circuit that provides some amplification and also adds a DC bias to avoid clipping the negative side of each oscillation. Ideally, the DC bias should be around Vcc/2, i.e. 2.5 V on an Arduino Uno.

この SparkFunマイクをご覧ください ブレークアウトの例 そのような回路を構築することができます(「回路図」をクリックしてください)。

ADCサンプリング

Once you have a properly conditioned analog signal, you have to sample it fast enough to catch all its spectral content. The Nyquist–Shannon sampling theorem tells us the sampling rate should be at least twice the highest frequency in the signal. For audio signals, sampling rates of the order of 8 kS/s (kilosamples per second) are typical of low quality, telephone-like applications, whereas high quality audio would run at 44.1 to 48 kS/s.

The ADC of the Arduino Uno, in its default configuration, takes 104 µs to convert one sample. If you just call analogRead() in a tight loop, this gives a sampling rate of about 9.6 kS/s, which is fine for this kind of application, unless we have to measure noise above 4.8 kHz. The problem with this approach is that analogRead() is a blocking function. Calling it in a tight loop means the program will spend most of its time just waiting for the ADC. If you do anything else in the loop, not only will the sampling rate be lowered, it will also become unsteady, which is generally not desirable.

In order to avoid blocking the CPU, we have to forgo analogRead(), and instead get our hands dirty with low-level configuration of the ADC. The ADC of the Arduino Uno offers a so-called “free running mode”, which is well suited for this kind of application. In this mode, the ADC starts a new conversion as soon as the previous one is done, ensuring a very consistent sampling rate of 9.6 kS/s. It can also trigger an interrupt after each conversion, in order for the interrupt service routine to retrieve and process the sample. See the datasheet of the ATmega328P for details on configuring the ADC.

DCバイアスの除去

デジタル化されたサンプルを入手したら、最初に削除する インターフェイス回路によって追加されたDCバイアス。バイアスが 安定していて(実験によって決定されるかもしれない)、これは 定数を減算する。それが知られていない場合は、 カットオフ付きのデジタルローパスフィルタでサンプルを実行する 関心のある範囲よりも低い周波数である。 aの出力を減算する ローパスフィルタは基本的にハイパスフィルタを構築しています。として 代替、数値導関数(連続 サンプル)を粗ハイパスフィルタとして使用することができる。しかし、これは ハイエンド方向の検出感度をバイアスする スペクトラム。検出したいノイズと バックグラウンドノイズの場合、これはアプリケーションで許容される可能性があります。

私が共有しているプログラムでは、私はDCバイアスが分かっていると仮定します。 dc_offset 定数をプログラムの先頭に追加します。

瞬時強度

DCバイアスを除去した状態での信号は、 マイクが選んだ音。ちょうどそれを平均化するのは魅力的かもしれない そのまま。しかし、これは肯定的な変動 信号の負の値がキャンセルされます。

この問題を解決するためのいくつかのオプションがあります。私たちはピークを迎えることができた 平均の代わりに検出するか、または絶対値をとることができます 平均化する前に。最も一般的な選択肢はおそらく サンプルの四角。実数の2乗は常に これは、平均化問題を回避する。しかし、広場にも より深い物理的意味:これは、音に比例します 強度、すなわち 音波によって運ばれるエネルギー。

ローパスフィルタ

The intensity computed above is a very fast varying quantity. If the signal is a simple tone of constant frequency and volume, the 瞬時強度 fluctuates between zero and some maximum at twice the tone frequency. In order to recover the “constant volume” property of the sound, we need to perform some sort of averaging or, in other words, we need a ローパスフィルタ.

There are many ways to implement a digital ローパスフィルタ. The most intuitive may be to group the samples into batches, and then compute the average of each batch. However, this is neither the best nor the most efficient to implement. When I need a quick and simple low pass filter, I generally use an exponential moving average. This is the discrete-time equivalent of an analog RC filter, and it can be implemented very efficiently by remembering the previous output and updating it as

output += input - output/N;

where, for efficiency reasons, N should be a power of two. The filter's time constant is N/fs, where fs is the sampling frequency. In the program I use N = 256, which makes the division virtually free. This gives a time constant of 26.6 ms. You can tune the time constant to your needs simply by changing N, but make sure it is still a power of two.

デシメーション

If you only want to trigger an event when the sound intensity exceeds a defined level, you may not need this. But if you have other processing to do with those measurements, it is probably not useful to process more than one intensity reading per time constant of the previous filter. That's why the program has a デシメーション step. This is simply the ISR periodically signaling the main program that an intensity reading is available. Notice that, since the sample count is an 8-bit variable, it automatically counts modulo 256. If you want to increase the デシメーション factor, you should make sample_count wider and mask out the bits you do not need.

0
追加された