2019年09月02日

サウンドグラフィックイコライザーシールド -スケッチその2(ノイズ処理 移動平均・指数平滑)

はじめに

 前回はMSGEQ7のデータを取得しました。図1の青線がMSGEQ7から取得した1kHzの無音時波形なのですが、無音時でも波形にノイズが多く乗っています
 この状態のデータでは使えませんので、Arduinoのスケッチにノイズを除去するためのフィルターを実装します。図1の赤線と青線はそれぞれ異なるノイズフィルターを適用した後の波形です。ノイズによる変化がかなり穏やかになっています

2019-08-27.png
図1 無音時のMSGEQ7 1kHz出力(青:生値 赤:移動平均 緑:指数平滑)

 今回はこのノイズフィルターについて解説します。


目次



1. ノイズフィルタの種類

 Arduinoで実装しやすいノイズフィルターには移動平均指数平滑(RCフィルタ)があります。図1の赤線が移動平均、緑線が指数平滑を適用した波形です。それぞれのフィルターを大雑把に説明すると、移動平均は一定数のデータの平均値、指数平滑は新しいデータに重みをおいて平滑化した値です。
 データ数をi、入力をx[i]、出力をy[i]として式で表すと以下のようになります。aは指数平滑の係数です。大きくするほど変化がなだらかになります。自分が試した範囲では0.9~0.99くらいが良かったです。

移動平均
$\displaystyle {y[i] = \frac{1}{n} \sum_{j=0}^{n-1}x[i-j] }$

指数平滑
$\displaystyle {y[i] = a \times  x[i] + (1-a) \times  y[i-1]}$

 正直に言うとこれらの式でノイズが除去出来る理由をちゃんと説明出来るほど、理解出来ていません。これらのフィルタについては下記のWebサイトを参考にいたしましたので、詳しく知りたい方はそちらをご覧ください。

"センサの入力などに使うディジタルフィルタ" なんでも独り言

"THREE METHODS TO FILTER NOISY ARDUINO MEASUREMENTS" MegunoLink
 この2つのフィルタをArduinoに実装します。


2. ノイズフィルタの実装

 MSGEQ7から1[kHz]の値を取得するスケッチに移動平均と指数平滑のフィルタを実装しました。移動平均に関する箇所は41行目〜51行目指数平滑に関する箇所は51行目です。
/*
* グラフィックイコライザー用IC MSGEQ7の値を取得し、ノイズをフィルタにて除去する
* 2019.8.30
*/

//MSGEQ7関連
#define MSGEQ7_RESET 8
#define MSGEQ7_STROBE 7
#define MSGEQ7_OUT A0
#define FREQ_NUM 7
int valAmplitude[FREQ_NUM]={0};

//移動平均関連
#define BLOCK_LENGTH 64 //移動平均長
int tempValAmp[BLOCK_LENGTH] = {0};
long sumAmp = 0;
double aveAmp;
byte cnt = 0;

//指数平滑関連
#define EXPO_FIL_COEF 0.98
double expoFilOut =0.0;

void ReadMSGEQ7(); //MSGEQ7の読み取り

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

//MSGEQ7の初期設定
pinMode(MSGEQ7_RESET, OUTPUT);
pinMode(MSGEQ7_STROBE, OUTPUT);
digitalWrite(MSGEQ7_RESET, HIGH);
digitalWrite(MSGEQ7_STROBE, HIGH);
delayMicroseconds(1); //Reset Pulse Width(tr)
}

void loop() {
ReadMSGEQ7();

//移動合計の更新・レジスタへの格納
sumAmp = sumAmp + valAmplitude[3] - tempValAmp[cnt];
tempValAmp[cnt] = valAmplitude[3];

//配列の最後ならば、先頭に戻る。そうでなければ次のレジスタへ
if( cnt == BLOCK_LENGTH -1 ){
cnt = 0;
} else {
cnt++;
}
//移動合計を移動平均へ
aveAmp = (double)(sumAmp/BLOCK_LENGTH); // -H31.4.18 ExpoFil

//指数平滑
expoFilOut = expoFilOut*EXPO_FIL_COEF + (1.0-EXPO_FIL_COEF)*valAmplitude[3];

//波形表示
Serial.print(valAmplitude[2]);
Serial.print(", ");
Serial.print(aveAmp);
Serial.print(", ");
Serial.print(expoFilOut);
Serial.print(", ");
Serial.print(1024);
Serial.print("\n");


}


//MSGEQ7の読み取り
void ReadMSGEQ7(){
digitalWrite(MSGEQ7_RESET, LOW);
delayMicroseconds(100); //Reset to Strobe Delay(trs)

for(byte freq=0; freq<FREQ_NUM; freq++){
digitalWrite(MSGEQ7_STROBE, LOW);
delayMicroseconds(50); //Output Setting Time(to)
valAmplitude[freq] = analogRead(MSGEQ7_OUT);
delayMicroseconds(20); //指定や名称無し。これとtoとtsの合計がStrobe to Strobe Delay(tss)
digitalWrite(MSGEQ7_STROBE, HIGH);
delayMicroseconds(30); //Strobe Pulse Width(ts)
}

digitalWrite(MSGEQ7_RESET, HIGH);
delayMicroseconds(1); //Reset Pulse Width(tr)
}
 ソースコードの該当する箇所を見れば分かるように、移動平均はシフトレジスタを実装しないといけませんのでソースコードが多くなります。一方、指数平滑の方は1行で記述することが出来ます
 またシフトレジスタは値を保存しないといけないので、使用するメモリ量が多いです。まぁ指数平滑も小数の乗算がありますので、計算量は多いのですが……。


3. ノイズフィルタの結果

 それぞれのフィルタの波形を比較し、どちらのフィルタを使うか決めます。
 図2は音の強弱がなだらかに変化しているときの波形です。このような波形だとどちらのフィルタもよくノイズを除去出来ています

2019-08-27 (2).png
図2 強弱変化遅め時のMSGEQ7 1kHz出力(青:生値 赤:移動平均 緑:指数平滑)

 一方、図3は音の強弱が急に変化しているときの波形です。この場合移動平均のピークは一定時間続きますが、指数平滑のピークは一瞬です

2019-08-27 (3).png

 実際のそれぞれのフィルタでLEDを光らせた場合、ピークが一瞬となる指数平滑の方が自然に光りました


おわりに

 MSGEQ7の出力値のノイズを除去するために、移動平均や指数平滑の説明や比較を行いました。比較結果をまとめると以下の通りです。
  • 指数平滑は記述するコードや使用するメモリが少ない
  • 指数平滑はLEDの光り具合が自然
 プログラム的にもLEDの光り具合的にも指数平滑の方がメリットが多いので、指数平滑を使用することにします。

2019年07月14日

サウンドグラフィックイコライザーシールド -スケッチその1(MSGEQ7の制御)

はじめに

 今回も制作中のサウンドグラフィックイコライザーシールド(SGES)について説明します。ブログの更新が久し振りですので、制作物の紹介動画を載せておきます。


 前回はSGESの部品構成を説明しました。SGESはArduinoで動かしていますので、今回はSGESを動かすためのスケッチについて説明をします。スケッチの主な流れは下記の通りです。
  1. 各値の初期設定
  2. MSGEQ7から音の大きさ値を取得
  3. 音の大きさに応じてLEDを制御
 今回説明するのは2番のMSGEQ7から音の大きさを取得するスケッチです。それに伴ってピン配置やタイミングチャートなども説明します。


目次



1. MSGEQ7の概要

 まずはMSGEQ7が何かということですが、MSGEQ7はグラフィックイコライザー用ICです。入力された音声信号から7つの周波数の音の強さをアナログ出力します。周波数は63[Hz]、160[Hz]、400[Hz]、1[kHz]、2.5[kHz]、6.25[kHz]、16[kHz]です。

I-12887.jpg
図1 MSGEQ7の外観(写真は秋月電子から)

 このMSGEQ7にマイクやAUXなどから音声信号を入力し、MSGEQ7の出力をArduinoで読み取って、周囲の音の大きさを測ります。


2. MSGEQ7の接続

 ArduinoでMSGEQ7を制御するためにはピンを接続する必要があります。接続するのはArduinoのデジタル入出力ピンにMSGEQ7のRESETとSTROBEアナログ入力ピンにOUT、合計3本のピンです。

0711_MSGEQ7ピン配置.png
図2 ArduinoとMSGEQ7の接続

 RESETとSTROBEの2つの線でMSGEQ7を制御し、OUTからのアナログ値をArduinoでA/D変換して読み取ります。


3. MSGEQ7の制御方法

 MSGEQ7はRESETとSTROBEの2本で制御するわけですが、これらの信号はデータシートに記載されているタイミングチャートに従って動かします。

2019-07-11.png
図3 MSGEQ7のタイミングチャート(データシートから)

 このタイミングチャートを満たすようにArduinoのピンを動かします。下記がMSGEQ7制御部分のみを抜粋したソースコードです。

void ReadMSGEQ7(){
digitalWrite(MSGEQ7_RESET, LOW);
delayMicroseconds(100); //Reset to Strobe Delay(trs)

//FREQ_NUMは7
for(byte freq=0; freq<FREQ_NUM; freq++){
digitalWrite(MSGEQ7_STROBE, LOW);
delayMicroseconds(50); //Output Setting Time(to)
valAmplitude[freq] = analogRead(MSGEQ7_OUT);
delayMicroseconds(20); //指定や名称無し。これとtoとtsの合計がStrobe to Strobe Delay(tss)
digitalWrite(MSGEQ7_STROBE, HIGH);
delayMicroseconds(30); //Strobe Pulse Width(ts)
}

digitalWrite(MSGEQ7_RESET, HIGH);
delayMicroseconds(1); //Reset Pulse Width(tr)
}
 簡単に説明すると「STROBEを変化させながらOUTPUTを読み込む処理を7回繰り返す」ということをしています。時間は余裕を持たせてタイミングチャートの1.5倍くらいにしています。


4. スケッチの実行結果

 上記のソースコードを実際に動かしたときのSTROBE(赤線)とOUT(青線)の波形が下図です。

0711_タイミングチャート.png
図4 MSGEQ7制御時の波形

 STROBE信号やOUT出力の変化がちゃんと7回ありますので、7つの周波数を読み取れていることが分かります。この波形は確か適当な音楽を流しながら測定したものでした。400[Hz]や1[kHz]の音が大きく鳴っていることが分かります。
 STROBE信号の設定したタイミングと実際のタイミングについてですが、HIGHの時間はスケッチの設定が30[us]に対して実際は約35[us]とそこまで差がありません。ですがLowの時間はスケッチが70[us]に対して実際は190[us]と結構差があります。これはanalogRead()の処理で100[us]〜200[us]かかるためです。ですので、問題はありません。


おわりに

 今回はこのようにArduinoでMSGEQ7をきちんと制御することが出来ました。次回は取得した値からLEDを光らせるスケッチの説明をする予定です

2019年05月07日

サウンドグラフィックイコライザーシールド -構成

はじめに

今回はサウンドグラフィックイコライザーシールドの構成について説明します


目次



1. 部品構成

下図はサウンドグラフィックイコライザーシールドのブロック図です。主要な部品を記しています。

Apr30_SGESブロック図3.png
図1 サウンドグラフィックイコライザーシールドのブロック図

音声周りの主な部品はマイクアンプキットとグラフィックイコライザー用IC MSGEQ7の2つです。
MSGEQ7は入力された音声信号から、7つの周波数の音の強さをアナログ出力します。周波数は63[Hz]、160[Hz]、400[Hz]、1[kHz]、2.5[kHz]、6.25[kHz]、16[kHz]です。
MSGEQ7のアナログ出力をArduinoのA/Dピンへ入力し、周囲の音の大きさを読み取っています。

LED周りの主な部品はフルカラーLED(PL9823)×7個5[V]出力DC/DCコンバーター(BP5293-50)です。
PL9823はNeoPixel系のフルカラーLEDですので、信号線を直列接続出来ます。よってArduinoの必要な出力ピンは1つだけです。


2. 電源の分離

サウンドグラフィックイコライザーシールドでは音声周りとLED周りで異なる5[V]電源を使用しています。これはフルカラーLEDによるノイズを音声周りに与えないためです。

実験段階ではパソコンのUSB 5[V]から音声周りにもLED周りにも電力を供給していました。(電流不足にならないよう、フルカラーLEDの明るさは抑えて)
ですが、下図のような構成で実験していたところ、フルカラーLEDが点灯するとArduinoが読み取るMSGEQ7の出力にノイズが乗りました。そのため周囲の音の大きさを上手く読み取ることが出来ませんでした。

Apr30_SGESブロック図_fig2-4.png
図2 サウンドグラフィックイコライザーシールドの実験時ブロック図

詳しい理由は不明ですが、フルカラーLEDが消灯時はノイズが乗らなかったので、フルカラーLEDが音声周りに悪影響を与えていることは間違いありません。

ですので、図1のように音声周りとLED周りで使用する5[V]電源を分離しました。音声周りにはArduino内蔵のレギュレーターから、LED周りにはDC/DCコンバーターから、5[V]を供給しています。
どのみちArduino内蔵のレギュレーターだとフルカラーLEDに対して電流が不足するので、DC/DCコンバーターを使うことでそれも解消することも出来ました。

電源を分離したら、フルカラーLEDが点灯してもノイズは乗らなくなりました


おわりに

以上がサウンドグラフィックイコライザーシールドの構成の説明です。
音声周りのノイズを減らすために、フルカラーLED専用の電源を使用しています。

次回はArduinoのスケッチを解説するつもりです

2019年04月12日

サウンドグラフィックイコライザーシールド -概要紹介

前回の記事では音楽連動照明の機能を説明しました。その記事内で最後にこのように書きました。
Arduinoシールド単体で動くように簡素化し、安価になるよう設計を変更中です。
というわけで、周囲の音に反応してLEDが光るArduinoシールドを作りました。使用しているLEDはフルカラーLEDです。

P2320575-2.jpg

P2320577-HDR-2.jpg

作り直すにあたってLEDを複数にし、LEDごとに反応する音の高さを変更しました。画像左側のLEDが低い音に反応し、右側のLEDが高い音に反応します。
グラフィックイコライザーとしても使えるので、サウンドグラフィックイコライザーシールドと呼ぶことにしました。
集音にはマイクアンプキットを、グラフィックイコライザーの処理には専用IC MSGEQ7を使っています。

実際に周囲の音に合わせて光らせたり、機能を説明している動画がこちらです。


用途としてはスピーカーの横に置いて観賞用として使うなどを想定しています。

とりあえずユニバーサル基板に実装してどんなものかなーと試してみましたが、LEDが音に対して結構いい感じに反応しているかなと思っています。
良さそうなので、このままサウンドグラフィックイコライザーシールドをプリント基板化したり外装を作ったりするなどして、改良していきます。

2019年02月07日

音楽連動照明 -機能の説明

前回は作り直した音楽連動照明について外装を中心に説明しました。

P2300757.jpg

今回はこの照明を実際に使い、光りに関する機能を説明します。



この照明は光り方を3つのモードに切り替えることが出来ます。
  1. 通常  :普通の照明のように一定の明るさで点灯する
  2. ゆらぎ :明るさを不規則にゆっくりと変化させる
  3. 音楽連動:入力された音の大きさに合わせて、明るさを変化させる。音の入力はAUX端子とマイクの2種類がある
これらの機能は基板にあるトグルスイッチ(下図の「Mode」と書かれているスイッチ)で切り替えます。Normalが通常、1/fがゆらぎ、Musicが音楽連動です。

P2310009.jpg

その他のスイッチや半固定抵抗(青いダイヤル)については、このようになっています。
  • Power:電源のオン・オフ
  • Response:音楽連動モード時の応答速度
  • Blightness:通常モード時の明るさ
  • AUX Vol:音楽連動モード時のAUX端子からの音量設定
  • Mic Vol:音楽連動モード時のマイクからの音量設定

音楽連動照明を実際に動かした動画をYouTubeに上げました。




以上で説明したことが音楽連動照明の機能です。

マイコンはATMEGA328Pを使っており、Arduinoと互換性を持たせております。ですので外付けのUSB-シリアル変換モジュールを使えば、音楽連動照明のスケッチを書き換えることが出来ます

当初はこれの販売を考えていたのですが材料費が結構かかってしまったため、販売するなら売値が7千円〜1万円と結構高めになってしまいそうです。
ですので、Arduinoシールド単体で動くように簡素化し、安価になるよう設計を変更中です。
posted by ました at 14:22| Comment(0) | 自作LED照明 | このブログの読者になる | 更新情報をチェックする