工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示

部品と材料

Arduino Nano 33 BLE×1
エレクトレットマイクアンプ MAX9814×1
0.91インチ OLED I2Cディスプレイ 128×32ピクセル×1
コンデンサ 4.7nFRCローパスフィルタのカットオフ周波数による×1
コンデンサ 470μF×1
抵抗 2kΩRCローパスフィルタのカットオフ周波数による×1

アプリとオンラインサービス

Arduino IDE

このプロジェクトについて

はじめに

小さなOLEDディスプレイ上で、音楽や音に反応するバーグラフを表示します。左端が低周波、右端が高周波です。

構築

接続

Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示

低周波ノイズが気になる場合?

近くで動作している電気機器からのノイズです。すべての電子機器は固定周波数・電圧の交流(AC)で動作し、お住まいの国の商用電源周波数(50Hzまたは60Hz)がノイズ源になります。ファラデーケージで簡単に除去できます。回路を箱に入れ、箱をアースに接続し、回路もよくアースしてください。

Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示

Arduino Nano 33 BLEのピン配置

Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示

Arduino標準の analogRead() と Arduino Nano 33 BLE を使うと、約35,000サンプル/秒しか取得できません。FFTを使う場合、ナイキストの定理(サンプリング周波数の半分まで)により17.5kHz以上の周波数は扱えません。さらにクロック読み取りやビジーウェイトループでの比較処理があるため、安全を見て上限8kHzとしています。この周波数以上をカットするシンプルなRCローパスフィルタを使用できます。

Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示
Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示

R=180Ω、C=0.1μF でカットオフ周波数 fc=8842Hz

今回は2kΩ抵抗と4.7nFコンデンサで fc=17,000Hz としています

Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示

最大サンプリングレートの概算

通常の analogRead() はオーディオサンプリングには遅すぎるため、最大サンプリングレートを概算します。

Arduino Nano 33 BLE で Arduinoコアの analogRead() を使ってどれだけサンプリングできるか測定するスケッチ:

/* Rough calculation of maximum sample rate with AnalogRead */
#define ANALOG_PIN A0
#define SAMPLES 1000000.0
int newTime;
int analogValue;
void setup() {
  Serial.begin(9600);
  Serial.println("Sampling... please, wait. ");
}
void loop() {
  newTime = micros();
  for (int i = 0; i < (int)SAMPLES; i++) {
    analogValue = analogRead(ANALOG_PIN);
  }
  float elapsedTimePerSampleUs = (micros() - newTime) / SAMPLES;
  Serial.print("Time per sample (us): ");
  Serial.println(elapsedTimePerSampleUs);
  Serial.print("Max sampling freq(hz): ");
  Serial.println(pow(10,6) / elapsedTimePerSampleUs);
}
Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示

Arduino Nano 33 BLEで約35,000サンプル/秒。ナイキストの約2倍の要件により、スペクトラムビジュアライザーは17kHz以下に制限されます。この上限以上をカットするローパスフィルタを使用します。

クロック読み取りとビジーウェイトループでの比較があるため、安全マージンを取って8kHzを上限としています。

// サンプリング
for (int i = 0; i < SAMPLES; i++) {
  unsigned long newTime = micros();
  int value = analogRead(ANALOG_PIN);
  vReal[i] = value;
  vImag[i] = 0;
  while (micros() < (newTime + sampling_period_us)) {
    yield();
  }
}

ユーザーインターフェース

Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示

画面を11の周波数ゾーンに分割し、人間の聴覚に近い対数スケールで周波数をグループ化しています。

人間の可聴域は約20Hz〜20kHz(乳児は20kHz以上も聴取可能だが、成長とともに高周波感度は低下し、平均的な成人の上限は15〜17kHz程度)。

ゾーン3〜13(11ゾーン)を表示に使用。

Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示

各バーは、帯域内の最大値を点線で、平均値を塗りつぶし長方形で表示。値はヒューリスティックに決定した基準値を用いてデシベル(dB)で表示。

仕組み

オーディオサンプルを高速フーリエ変換(FFT)で周波数スペクトラムに変換。スペクトラムを14ゾーンに分割・グループ化し、11ゾーンをdBで表示。

マイクモジュールについて

Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示
Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示
Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示

エレクトレットマイクロフォン

エレクトレットは準永久的に帯電した誘電体。セラミック材料を加熱し、磁場中で冷却することで作られます。永久磁石の静電気版のようなものです。エレクトレットマイクでは、この材料の薄片をコンデンサの誘電体の一部として使用し、マイクの振動板が一方の極板になります。音圧で振動板が動くと容量が変化し、誘電体の固定電荷により極板間電圧も変化。このコンデンサを内蔵FETアンプの入力に接続。エレクトレットマイクは小型で高感度、広い周波数特性、低コストが特徴です。

MAX9814 マイクアンプ

MAX9814は自動利得制御(AGC)と低ノイズマイクバイアスを備えたマイクアンプで、ブレークアウト基板でいくつかの設定が可能。

感度

感度は、アナログ出力電圧またはデジタル出力値と入力音圧の比率で、マイクの主要スペックです。音響領域の単位を電気領域の単位にマッピングすることで、既知の入力に対する出力信号の大きさが決まります。

マイク感度の標準リファレンス入力は、1kHz正弦波、94dB SPL(音圧レベル)、または1Pa(圧力単位)。感度値が高いマイクは、固定音響入力に対してより高い出力レベルを示します。デシベル(dB)で表されるマイク感度は通常負の値なので、絶対値が小さいほど高感度。

アナログマイクの感度は通常 dBV(1.0V rms基準のデシベル)で指定されます。

リファレンスレベルと周波数特性

周波数特性は、周波数スペクトラム全体での出力レベルを示します。高域・低域の限界は、1kHzでの基準出力レベルから3dB下がった点で定義。1kHzの基準レベルは慣例的に0dBで正規化されます。

0.91インチ OLED I2Cディスプレイ 128×32ピクセル

対角約1インチの小型ディスプレイ。128×32個の白色OLEDピクセルで構成され、コントローラーチップで各ピクセルを個別にON/OFF制御。バックライト不要で消費電力が低い。

ここでは4ピンのI2C通信モデルを使用(RESETピンなし)。Arduino UnoのI2Cピンに接続:

OLED制御には adafruit_SSD1306.h と adafruit_GFX.h ライブラリが必要。インストール手順に従ってください。Adafruitライブラリを使用しています。Adafruitから何か購入して支援することもできます。

Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示
Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示
Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示

次のステップ

Arduino Nano 33 BLEはアナログ読み取りをさらに最適化可能。次期バージョンではnrf52840向けに最適化されたFFTとアナログ入力を使用予定。

コード

Arduino Nano 33 BLE用 サウンドスペクトラムビジュアライザー Arduino

Sound Spectrum Visualizer for Arduino Nano 33 BLE
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

/* Sound Spectrum Visualizer for Arduino Nano 33 BLE
   Arduino based sound visualizer
   @author Enrique Albertos
   Hardware requirements:
   - Arduino or Arduino-compatible boards.
   - ssd1306 oled I2C 128x32 display
   - Electret Microphone Amplifier with max9814
   - Optional: battery for portable use (else power through USB)
   Software requirements:
   - arduinoFFT https://github.com/kosme/arduinoFFT
   - Adafruit_GFX https://github.com/adafruit/Adafruit-GFX-Library
   - Adafruit_SSD1306 https://github.com/adafruit/Adafruit_SSD1306
   Connections:
   - Mic GAIN: * VCC to mic GAIN for 40dB
               * GND to mic GAIN for 50dB
               * floating mic GAIN for 60dB
   - Analog pin 0 to mic amp output
   - +3.3V, GND, SDA (or analog 4) and SCL (analog 5) to 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
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.
*/
#include "arduinoFFT.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SAMPLES 1024
#define SAMPLING_FREQ 24000
#define AMPLITUDE 100
#define FREQUENCY_BANDS 14
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define BARWIDTH 11
#define BARS 11
#define ANALOG_PIN A0
#define OLED_RESET -1

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
double vImag[SAMPLES];
double vReal[SAMPLES];
unsigned long sampling_period_us;
arduinoFFT fft = arduinoFFT(vReal, vImag, SAMPLES, SAMPLING_FREQ);
float reference = log10(50.0);
double coutoffFrequencies[FREQUENCY_BANDS];

void setup() {
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    for (;;);
  }
  display.clearDisplay();
  display.display();
  display.setRotation(0);
  display.invertDisplay(false);
  sampling_period_us = (1.0 / SAMPLING_FREQ) * pow(10.0, 6);
  double basePot = pow(SAMPLING_FREQ / 2.0, 1.0 / FREQUENCY_BANDS);
  coutoffFrequencies[0] = basePot;
  for (int i = 1; i < FREQUENCY_BANDS; i++) {
    coutoffFrequencies[i] = basePot * coutoffFrequencies[i - 1];
  }
  for (int i = 0; i < BARS - 1; i++) {
    for (int j = 0; j < SCREEN_HEIGHT; j += 4) {
      display.writePixel((i + 1) * BARWIDTH + 2, j, SSD1306_WHITE);
    }
  }
  display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SSD1306_WHITE);
}

int oldHeight[20];
int oldMax[20];
double maxInFreq;

void loop() {
  for (int i = 0; i < SAMPLES; i++) {
    unsigned long newTime = micros();
    int value = analogRead(ANALOG_PIN);
    vReal[i] = value;
    vImag[i] = 0;
    while (micros() < (newTime + sampling_period_us)) {
      yield();
    }
  }
  fft.DCRemoval();
  fft.Windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  fft.Compute(FFT_FORWARD);
  fft.ComplexToMagnitude();
  double median[20];
  double max[20];
  int index = 0;
  double hzPerSample = (1.0 * SAMPLING_FREQ) / SAMPLES;
  double hz = 0;
  double maxinband = 0;
  double sum = 0;
  int count = 0;
  for (int i = 2; i < (SAMPLES / 2); i++) {
    count++;
    sum += vReal[i];
    if (vReal[i] > max[index]) {
      max[index] = vReal[i];
    }
    if (hz > coutoffFrequencies[index]) {
      median[index] = sum / count;
      sum = 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]) - reference);
    }
    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);
      }
    }
    for (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

Arduino Nano 33 BLE サウンドスペクトラムビジュアライザー:リアルタイムオーディオ表示

製造プロセス

  1. Arduino UNOとOLEDディスプレイでクラシックPongゲームを自作:ステップバイステップチュートリアル
  2. K30 CO2センサで室内空気質をリアルタイム監視する
  3. 1SheeldとArduinoで盲ろう者のコミュニケーションを支援する
  4. スマート貯金箱を作ろう:Arduino Nanoでコインアクセプターを制御
  5. ArduinoでBluetooth経由でLEDを制御 – シンプルDIYガイド
  6. Arduino Nanoとジョイスティックで2軸ステッピングモーターを制御:Visuinoで簡単プログラミング
  7. Arduino Nano 33 BLE Senseで音声データ伝送を実現する方法
  8. Arduino Nanoで作る携帯型ガイガーカウンター
  9. Arduino UNOとEthernetシールドで太陽放射を測定する自作ピラノメーター
  10. Arduino Nanoで作る「食べさせロボット」:超音波センサーで食べ物検知し口を開閉
  11. Arduinoリアルタイム気象時計 - OLEDに時刻/日付/温度を表示