Arduino Nano 33BLEを搭載したサウンドスペクトルビジュアライザー
コンポーネントと消耗品
> |
| × | 1 | |||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
アプリとオンラインサービス
> |
|
このプロジェクトについて
はじめに
小さなOLEDディスプレイで、棒グラフが音楽と音にどのように反応するかを確認してください。グラフの左端に向かって最も低い頻度、右に向かって最も高い頻度。
建設
<図>
接続
- システムに適した感度に応じてマイクゲインを接続します: VCC マイクに GAIN 40dB、低感度、 GND マイクに GAIN 50dBの場合、中程度の感度、またはマイクを浮かせてゲイン 60dB、高感度。
- アナログピン0を接続します A0 マイクアンプへ OUT
- 3.3V を接続します 、 GND 、 SDA (またはアナログ4 A4 )および SCL (アナログ5 A5 )からI2CSSD1306へ
- 電源バスのVCCとGNDの間に470uFのコンデンサを接続します
低周波ノイズが発生しますか?
ノイズは、動作している測定システムの近くの電気機器から発生します。すべての電子機器は固定周波数で動作し、50Hzまたは60Hzの周波数があなたの国の電力線周波数である交流(AC)の電圧です。ファラデーケージを使用すると、ノイズを簡単に除去できます。回路をボックスの中に入れ、ボックスをアースに接続します。回路をしっかりと接地してください。
<図>Arduino Nano 33BLEのピン配置
<図>arduinoコアAnalogReadとArduinoNano 33 BLEを使用すると、1秒あたり約35,000サンプルしか取得できないため、17.5 Khzを超える周波数ではFFTを使用できません。これは、ビジー待機ループでクロックを読み取り、いくつかの比較を行う必要があるためです。注意して、8kHzの上限を取ります。したがって、単純なRCローパスフィルターを使用して、その周波数を超える煩わしいソリューションを回避できます。
<図> <図>R =180ΩC=カットオフ周波数の場合は0.1uFfc =8842 [Hz]
ここでは、カットオフ周波数fc =17000 [Hz]
に2Kオームの抵抗と4.7nFのコンデンサを使用しています。 <図>
最大サンプルレートの大まかな計算
通常のArduinoanalogRead()関数を使用すると、オーディオをサンプリングするには遅すぎるので、最大サンプルレートを計算してみましょう。
arduinoコアAnalogReadとArduinoNano 33BLEを使用して取得できるサンプル数を見積もります。
この小さなプログラムを実行して見積もりを取りましょう。
/ *
* AnalogReadを使用した最大サンプルレートの大まかな計算
* /
#define ANALOG_PIN A0
#define SAMPLES 1000000.0
int newTime;
int analogValue;
void setup(){
Serial.begin(9600);
Serial.println( "Sampling。 ..お待ちください。 ");
}
void loop(){
//メインコードをここに配置して、繰り返し実行します:
newTime =micros ();
// 100万サンプル
for(int i =0; i <(int)SAMPLES; i ++){
analogValue =analogRead(ANALOG_PIN);
}
floatlapsedTimePerSampleUs =(micros()-newTime)/ SAMPLES;
Serial.print( "Time per sample(us):");
Serial.println(elapsedTimePerSampleUs);
Serial.print( "最大サンプリング周波数(hz):");
Serial.println(pow(10,6)/ elapsedTimePerSampleUs);
}
<図> arduinoコアのAnalogReadとArduinoNano 33 BLEを使用すると、1秒あたり約35,000サンプルしか取得できません。ナイキスト定理の結果である約2倍のレート要件により、スペクトルビジュアライザーは17kHz未満の周波数に制限されます。ローパスフィルターを使用して、その制限を超える周波数をスキップできます。
ビジーウェイトループでクロックを読み取り、いくつかの比較を行う必要があります。注意して、上限を8kHzにします。
//サンプルを取得
for(int i =0; i unsigned long newTime =micros();
int value =analogRead(ANALOG_PIN );
vReal [i] =value;
vImag [i] =0;
while(micros()<(newTime + sample_period_us)){
yield();
}
}
ユーザーインターフェイス <図>
画面は11の周波数ゾーンに分割されており、人間の耳がそれらを認識するのと同様の周波数をグループ化した対数目盛です。
人間は約20Hzから20kHzの周波数範囲の音を検出できます。 (人間の乳児は実際には20 kHzよりわずかに高い周波数を聞くことができますが、成熟するにつれてある程度の高周波感度が失われます。平均的な成人の上限は15〜17 kHzに近いことがよくあります。)
表現にはゾーン3から13(11ゾーン)を使用します。
<図>各バーは、間隔を空けた線でバンドの最大値を表し、塗りつぶされた長方形でバンドの平均値を表します。
値は、ヒューリスティックな方法で取得された事前に選択された参照とともにデシベルを使用して表示されます。
仕組みは?
オーディオサンプルは、高速フーリエ変換またはFFTを使用して周波数スペクトルに変換されます。
次に、スペクトルは14のゾーンに分割およびグループ化され、11のゾーンのみがdBで表されます。
マイクモジュールについて <図> <図> <図>
エレクトレットマイク
Electretは、準永久的に帯電した誘電体です。それは、セラミック材料を加熱し、それを磁場に置き、それを磁場の中に置いたまま冷却することによって作られます。これは、永久磁石の静電的等価物です。エレクトレットマイクでは、この材料のスライスがコンデンサの誘電体の一部として使用され、マイクのダイアフラムが1つのプレートを形成します。音圧がダイヤフラムを動かします。プレートの動きは音圧に応じて静電容量を変化させます。誘電体の内蔵固定電荷を考えると、コンデンサの両端の電圧も変化します。エレクトレットコンデンサは、内蔵のFETアンプの入力に接続されています。エレクトレットマイクは小型で、優れた感度、広い周波数応答、そして一般的に非常に低コストです。
MAX9814マイクアンプ
MAX9814は、自動利得制御(AGC)と低ノイズのマイクバイアスを備えたマイクアンプであり、ブレークアウトで構成できるいくつかのオプションがあります。
MAX9814モジュールには3つのアンプ設定(40dB、50dB、60dB)があります。デフォルトは60dBですが、ゲインピンをVCCまたはグランドにジャンパすることで40dBまたは50dBに設定できます。
内部低ノイズマイクバイアス1.25V、2Vpp。アンプからの出力は、1.25VDCバイアスで最大約2Vppであるため、最大3.3V入力のアナログ/デジタルコンバーターで簡単に使用できます。
攻撃/解放の比率も、デフォルトの1:4000から1:2000または1:500に変更できます。
ライン入力に直接接続するには、DC成分をブロックするためのブロックコンデンサ/カップリングコンデンサが必要です。システムによって異なりますが、1uFを超える直列にブロッキングコンデンサを使用できます。疑わしい場合は、33uFから100uFまで試してください。結合回路により、DCコンポーネントをブロックしながら、AC信号をある部分から別の部分に流すことができます。オーディオ回路では、これはDCコンポーネントがオーディオ出力を歪ませるのを防ぐために行われます。カップリングコンデンサの有効性は、挿入損失、等価直列抵抗、直列共振周波数など、周波数に依存するさまざまなパラメータに依存します。
電源:2.7V〜5.5V
感度
感度 、入力圧力に対するアナログ出力電圧またはデジタル出力値の比率は、マイクの重要な仕様です。音響領域の単位を電気領域の単位にマッピングすると、既知の入力が与えられた場合のマイク出力信号の大きさが決まります。
マイクの感度は、特定の標準的な音響入力に対する出力での電気的応答です。マイクロフォンの感度測定用の標準の基準入力信号は、94 dBの音圧レベル(SPL)で1 kHzの正弦波、または1パスカル(Pa、圧力の測定値)です。感度値が高いマイクロフォンは、感度値が低いマイクロフォンよりも、固定音響入力に対して出力レベルが高くなります。デシベル(dB)単位のマイク感度は、通常、負の数です。したがって、感度が高いほど絶対値は小さくなります。
アナログマイクの場合、感度は通常dBVの単位で指定されます。つまり、1.0 Vrmsを基準にしたデシベルです。
参照レベルと周波数応答
マイクロフォンの周波数応答は、周波数スペクトル全体の出力レベルを表します。周波数の上限と下限は、マイクロフォンの応答が1kHzでの基準出力レベルより3dB低くなるポイントとして表されます。 1kHzでの基準レベルは通常0dBに正規化されています。
0.91インチOLEDI2Cディスプレイ128x32ピクセル
これは、対角約1インチの小さなディスプレイです。128x32の個別の白色OLEDピクセルで構成されており、各ピクセルはコントローラーチップによってオンまたはオフになります。バックライトは必要ありません。これにより、OLEDの実行に必要な電力が削減されます。
ここで使用しているモデルには4つのピンしかなく、I2C通信プロトコルを使用してArduinoと通信します。このモデルにはRESETピンがありません。 Arduino Uno I2Cピンに接続するだけです:
- Arduino Nano:SDA(A4); SCL(A5);
OLEDディスプレイを制御するには、adafruit_SSD1306.hおよびadafruit_GFX.hライブラリが必要です。次の手順に従って、これらのライブラリをインストールします。
Adafruitライブラリを使用しています。それらをサポートするためにAdafruitから何かを購入できることを忘れないでください。
<図> <図> <図>次のステップ
Arduino Nano 33 BLEは、アナログ読み取りをより適切に行うことができます。次のバージョンでは、nrf52840用に最適化されたFFTとアナログ入力を使用します。
コード
- Arduino Nano 33BLE用サウンドスペクトルビジュアライザー
Arduino Nano 33BLE用サウンドスペクトルビジュアライザー Arduino
Arduino Nano 33BLE用サウンドスペクトルビジュアライザーarduinoFFTを使用https://github.com/kosme/arduinoFFT
Adafruit_GFXを使用https://github.com/adafruit/Adafruit-GFX-Library
Adafruit_SSD1306を使用https://github.com/adafruit/Adafruit_SSD1306
/ * Arduino Nano 33BLE用サウンドスペクトルビジュアライザーArduinoベースのサウンドビジュアライザー@authorEnrique Albertosハードウェア要件:-ArduinoまたはArduino互換ボード。 --ssd1306 oled I2C 128x32ディスプレイ-max9814を備えたElectretマイクアンプ-オプション:ポータブル使用用バッテリー(USBを介したその他の電源)ソフトウェア要件:-arduinoFFT https://github.com/kosme/arduinoFFT-Adafruit_GFX https://github.com / adafruit / Adafruit-GFX-Library-Adafruit_SSD1306 https://github.com/adafruit/Adafruit_SSD1306接続:-マイクゲイン:* VCCからマイクゲイン40dB * GNDからマイクゲイン50dB *フローティングマイクゲイン60dB-アナログピン0からマイクアンプ出力-+ 3.3V、GND、SDA(またはアナログ4)およびSCL(アナログ5)からI2C SSD1306 @uses arduinoFFT https://github.com/kosme/arduinoFFT @uses Adafruit_GFX https:// github。 com / adafruit / Adafruit-GFX-Library @uses Adafruit_SSD1306 https://github.com/adafruit/Adafruit_SSD1306このプログラムは無料のソフトウェアです。このプログラムは、GNU General PublicLicenseによって公開されている条件の下で再配布および/または変更できます。 Free Software Foundation、ライセンスのバージョン3、または(オプションで)それ以降のバージョン。このプログラムは、役立つことを期待して配布されていますが、いかなる保証もありません。商品性または特定目的への適合性の黙示の保証もありません。詳細については、GNU General PublicLicenseを参照してください。* /#include "arduinoFFT.h" #include#include #define SAMPLES 1024 // 2の累乗#define SAMPLING_FREQ 24000 // 12 kHz Fmax =sampleF / 2 #define AMPLITUDE 100 // sensitive#define FREQUENCY_BANDS 14#define SCREEN_WIDTH 128 // OLEDディスプレイの幅(ピクセル単位)#defineSCREEN_HEIGHT 32 // OLEDディスプレイの高さ(ピクセル単位)#defineBARWIDTH 11#define BARS 11#define ANALOG_PIN A0 // I2Cに接続されたSSD1306ディスプレイの宣言(SDA、SCLピン)#define OLED_RESET -1 //リセットピン#(またはArduinoリセットピンを共有している場合は-1)Adafruit_SSD1306 display(SCREEN_WIDTH、SCREEN_HEIGHT、&Wire、OLED_RESET); double vImag [SAMPLES]; double vReal [SAMPLES]; unsigned longsingping_period_us; arduinoFFT fft =arduinoFFT(vReal、vImag、SAMPLES、SAMPLING_FREQ); //参照を調整してバックグラウンドノイズを除去するnoisefloatreference =log10(50.0); double coutoffFrequencies [ FREQUENCY_BANDS]; void setup(){// SSD1306_SWITCHCAPVCC =generate dis内部で3.3Vからの電圧を再生if(!display.begin(SSD1306_SWITCHCAPVCC、0x3C)){//アドレス0x3C for 128x32 for(;;); //続行せず、永久ループ} //ディスプレイの設定display.clearDisplay(); display.display(); display.setRotation(0); display.invertDisplay(false); sample_period_us =(1.0 / SAMPLING_FREQ)* pow(10.0、6); //カットオフ周波数を計算し、対数スケールを作成しますbase basePOt double basePot =pow(SAMPLING_FREQ / 2.0、1.0 / FREQUENCY_BANDS); coutoffFrequencies [0] =basePot; for(int i =1; i max [index]){max [index] =vReal [i]; } if(hz> coutoffFrequencies [index]){median [index] =sum / count;合計=0.0; count =0; index ++; max [index] =0; median [index] =0; } hz + =hzPerSample; } //周波数帯域ごとの中央値と最大値を計算するif(sum> 0.0){median [index] =sum / count; if(median [index]> maxinband){maxinband =median [index]; }} int bar =0; for(int i =FREQUENCY_BANDS-1; i> =3; i-){int newHeight =0; int newMax =0; //実際のデシベルを計算しますif(median [i]> 0 &&max [i]> 0){newHeight =20.0 *(log10(median [i])-reference); newMax =20.0 *(log10(max [i])-参照); } //最小レベルと最大レベルを調整するif(newHeight <0 || newMax <0){newHeight =1; newMax =1; } if(newHeight> =SCREEN_HEIGHT-2){newHeight =SCREEN_HEIGHT-3; } if(newMax> =SCREEN_HEIGHT-2){newMax =SCREEN_HEIGHT-3; } int barX =bar * BARWIDTH + 5; //古いレベルの中央値を削除if(oldHeight [i]> newHeight){display.fillRect(barX、newHeight + 1、7、oldHeight [i]、SSD1306_BLACK); } //古い最大レベルを削除if(oldMax [i]> newHeight){for(int j =oldMax [i]; j> newHeight; j- =2){display.drawFastHLine(barX、j、7、SSD1306_BLACK); }} //(int j =newMax; j> newHeight; j- =2){display.drawFastHLine(barX、j、7、SSD1306_WHITE);の新しい最大レベルをペイントします。 } //新しいレベルの中央値display.fillRect(barX、1、7、newHeight、SSD1306_WHITE);をペイントします。 oldMax [i] =newMax; oldHeight [i] =newHeight; bar ++; } display.drawFastHLine(0、SCREEN_HEIGHT-1、SCREEN_WIDTH、SSD1306_WHITE); display.display();}
回路図
soundspectrumvisualizer_qLzRsVPVlc.fzz 製造プロセス