気の向くままに辿るIT/ICT/IoT
webzoit.net
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。

EasyWordMall Arduino UNO R3互換ボード(USBケーブル付属)

EasyWordMall Arduino Pro Mini互換ボード Atmega328 5V 16MHz

Rasbeeオリジナル FT232RL互換 3.3V/5V FTDI/USB/TTL変換アダプタ

HiLetgo Mini USB Nano V3.0 ATmega328P CH340G 5V 16MHz マイクロコントローラーボード Arduinoと互換 改良版(5個セット)

KKHMF サウンドセンサーモジュール声検出声コントロールスイッチ

Rasbee 400穴 ブレッドボード 8.5*5.5cm 1個

HiLetgo 400穴 ブレッドボード 8.5*5.5cm 5個セット

HiLetgo 400穴 ブレッドボード 8.5*5.5cm 10個セット

Rasbee SY-170 ミニブレッドボード カラフルブレッドボード 5個

Rasbee 40PCS デュポン ワイヤー ジャンパー ブレッドボード 接続ワイヤー (オス-メス)1P-1Pピッチ 2.54mm 長さ 20CM 1個 [並行輸入品]

HiLetgo ジャンパーワイヤー(オス-オス) 20cmx40本 5セット

Rasbee ジャンパーワイヤー(オス-オス) 各種長さx65本

HiLetgo 37センサーモジュールアソートキット/Arduino開発スターターキット

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から削除した。

ウェブ造ホーム前へ次へ