気の向くままに辿るIT/ICT/IoT
IoT・電子工作

ArduinoとProcessingでグラフィックイコライザー風表示

ホーム前へ次へ
Arduinoって?

ArduinoとProcessingでグラフィックイコライザー風表示

ArduinoとProcessingでグラフィックイコライザー風表示

ArduinoとProcessingでグラフィックイコライザー風表示風リアルタイムグラフ表示
2018/03/18

 『Arduino側サウンドセンサの入力値をシリアル通信で送受信しつつ、Processingでグラフィックイコライザーっぽくリアルタイムグラフ表示』してみるページ。

 Lチカに始まり、ArduinoとProcessing連携第6弾。

 今回は、Arduinoのスケッチは、Arduinoフォーラムから辿り着いたMeasuring Sound Levelsを、ほぼ、そのまま使わせて頂き、これとオリジナルのProcessingスケッチを組み合わせてみました。

 イコライザと言っても今回は、音に合わせてリアルタイムで棒グラフの高さが変わるという表示のみで調整できるわけではありません。

 確認は、Icecastインターネットラジオ某局放送のJazzをArduino側の音センサで拾い、シリアル送信、Processing側でリアルタイム棒グラフ表示することで行ないました。

 グラフ1本じゃなんなのでダミー2本追加で3本にし、なんちゃって感を増幅してみましたが、ガラケーやスマホのアンテナみたいになってしまった...。

回路

ArduinoとProcessingでグラフィックイコライザー風表示風リアルタイムグラフ表示回路

 スケッチは後述するとして回路として必要になるハードウェアは、Arduinoボードとサウンド(音)センサ・モジュール、ブレッドボードを各1個とジャンパワイヤ4本だけ。(もちろん、USBケーブルとPC、Arduino IDEもしくは代替も要るけど。)

 今回、サウンドセンサには、37センサーキットに入っていた(感度が違う?)大・小のマイクが載ったポテンショメータ付きモジュール各1個、両方とも使ってみました。

 必要なソフトウェアは、Arduino IDEか代替とProcessing。

Arduino側のスケッチ

// Arduino側のスケッチ
 
/****************************************
Example Sound Level Sketch for the
Adafruit Microphone Amplifier
ほんの一部変更あり by webzoit
****************************************/
 
const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
unsigned int sample;
 
void setup()
{
 Serial.begin(9600);
}
 
 
void loop()
{
 unsigned long startMillis= millis(); // Start of sample window
 unsigned int peakToPeak = 0; // peak-to-peak level
 
 unsigned int signalMax = 0;
 unsigned int signalMin = 1024;
 
 // collect data for 50 mS
 while (millis() - startMillis < sampleWindow)
 {
  sample = analogRead(0);
  if (sample < 1024) // toss out spurious readings
  {
   if (sample > signalMax)
   {
    signalMax = sample; // save just the max levels
   }
   else if (sample < signalMin)
   {
    signalMin = sample; // save just the min levels
   }
  }
 }
 peakToPeak = signalMax - signalMin; // max - min = peak-peak amplitude
 double volts = (peakToPeak * 5.0) / 1024; // convert to volts
 
// 修正・追加
 int volval = volts * 100;
 
// Serial.println(volts);
 Serial.println(volval);
}

 Arduinoのスケッチは、シリアル送信値を整数にしたかったので100倍してint型変数に入れ、それを送信することにした以外は、先のリンク先Adafruitのものを、そのまま使わせて頂きました。

 が、Arduinoフォーラムのコメントを鵜呑みにしただけで、こんなに行数の少ないスケッチなのに中身を理解できていない...。

 というか、単位時間(ここでは50ms)あたりのアナログ値1024以内における振幅の上限下限ピークをサンプリング、その差を求め、一般的な出力5VのArduinoボードを想定し、電圧換算した値を送る...と書いてあることはわかってるつもり...

 が、精度は高そうな気がしなくもない、ただ、なんで単にアナログピンからの入力値を電圧変換したもの(当初自分で書いたラフスケッチ)だとダメなのかが、いまいちピンとこない...。

Processing側のスケッチ

// Processing側のスケッチ
 
import processing.serial.*;
 
Serial myPort; // シリアルポート
 
// グラフ色適用範囲値
const int MaxColorRange = 8;
const int MidColorRangeH = 8;
const int MidColorRangeL = 4;
// 入力値倍率(グラフ高さ嵩上げ用)
const int BaseMagnifications = 3;
const int DummyMagnifications_1 = 4;
const int DummyMagnifications_2 = 5;
 
int ival0, ival1, ival2;
 
void setup() {
 //画面設定
 size(300,300);
 
 // シリアルポートのリスト取得
 println(Serial.list());
 // ポート番号とスピードを指定してシリアルポートをオープン
 myPort = new Serial(this, Serial.list()[4], 9600);
 println(Serial.list()[4]);
 // 改行コード(\n)が受信されるまで、シリアルメッセージを受けつづける
 myPort.bufferUntil('\n');
 textFont(createFont("IPAGothic", 20));
}
 
int ival0, ival1, ival2;
void draw() {
 // シリアルバッファーを読込み
 String myString = myPort.readStringUntil('\n');
 // 空白文字など余計な情報を消去
 myString = trim(myString);
 println(myString);
 if(myPort.available() > 0 && myString != null) {
  ival0 = Integer.valueOf(myString);
  println(ival0);
 }
 // 読込み完了で次の情報を要求
 myPort.write("A");
 
 // グラフ描画
 // 背景色設定
 background(18,24,50);
 // 値によって色を変更
 if(ival0 > MaxColorRange){
  fill(10,255,255);
 } else if (ival0 > MidColorRangeL && ival0 < MidColorRangeH) {
  fill(255,10,255);
 } else {
  fill(255,255,255);
 }
 // グラフ高さ調整
 ival0 *= BaseMagnifications;
 ival1 = ival0 * DummyMagnifications_1;
 ival2 = ival0 * DummyMagnifications_2;
 // グラフ描画
 rect(200,280,-30,-ival0);
 rect(160,280,-30,-ival1);
 rect(120,280,-30,-ival2);
 // 再描画用遅延
 delay(50);
}

 Processing側のスケッチは、グラフ化の際のシリアル通信をそのままにグラフ表示を細工してみました。

 スケッチの大半はシリアル通信部分であり、今回のために書いたと言える部分は、

...くらいしかありません。

 説明用も兼ねて長ったらしい変数名を使っていたり、無駄な大きさのint型にしていたり、要るか要らないか微妙な変数もあったりしますが、気にしない。

 尚、音量の大小、スピーカーと音センサの距離はもちろん、入力値によって結果が変わるので実際の環境に合わせて調整が必要になるでしょう。

 また、それっぽく見えるようにするには、ある程度、抑揚のある音源が求められることは言うまでもありません。

備考

 当初、サウンドセンサの使い道を模索、イコライザー風にしようと思いたち、リアルタイムなグラフの描画は簡単だろうと思いこんでArduinoのスケッチも単にアナログ入力値を電圧変換して送信...としてみましたが、これがよくないようで音源再生時のみならず、何もしていない時にも過剰な反応を示すなど、どうも、うまくいかない...。

 調整を試みる中でオーディオ用アンプやオペアンプが必要なのか?手持ちないし...と諦めかけたものの、気を取り直して[arduino eqaulizer]で検索、先のArduinoのスケッチにたどり着き、思い描いていた通りの結果を得ることができた次第。

 ちなみに当記事用にYouTubeに上げた動画を張ってみましたが、YouTube上では再生できますが、当サイト上だと、なぜか、再生できず、調べてみると、デモとしてIcecastのインターネットラジオ局放送の曲を流していたのですが、どうやら、これが著作権チェックにひっかかった模様...ということでYouTubeから削除しました。

ホーム前へ次へ