レベルメーター的な物を作りたいのです…!
ステレオミニプラグには交流が流れている
ステレオミニプラグ(フォーンプラグ)から、音の大きさの大小を取得したい。3極のステレオミニプラグは手前からGND、R、Lとして取得できる。まずは信号の取得のために適当なオーディオジャック変換基板で手軽に扱えるようにする。
続いて一定の波形を出力するため、Mac で 1kHz のサイン波を出力し、音量最大でステレオミニプラグに入力する。今回はAudioTest のソフトウェア(シェアウェア)を利用した。
以下はオシロスコープによるMacからの出力の波形。1メモリが左下にあるとおり500mVなので、だいたいピーク値が±1.9Vほどの交流で出力されている。また、iPhone 6s でアプリを使って同様に 1kHzのサイン波を流したところ、ピーク値が±1.4V。機器によって結構違うようだ。
つまるところ、音の大きさを読み取るには、交流 ±2.0V ほどの交流の電圧値をうまく Arduino 等から読み取れれば良いが、A/Dコンバータが交流を読めないので、値を読めるようにする必要がある。
単相半波で整流して値を取得する
まずは単純に机の上にあったスイッチングダイオード(1N4148)一本で単相半波で整流直流にしてみた。
最大値が1.2Vほどと、600mVほど下がってしまってる。1N4148のVF(順方向電圧)はスペック的には700mVほどなのでだいたい正しい。また0.6V以下の電圧だとそもそも0になってしまい、小さめの音はほぼ0になってしまう。
こんなときはVFが低いショットキーバリアダイオードを、ということで手元にある 1N5819 に変更したところ、だいたい400mVほど降下しているがだいぶましに。もっとVFが低いショットキーバリアダイオードのほうが良さそう。
あとはこの単相半波の値を Arduino で読み込んでそれっぽくする。なお通常の曲ではピーク値でも1Vも超えることがほぼ無いため、analogRead() の ADC の基準値を、標準の 5V から 1.1V へと analogReference(INTERNAL)
で変更する。少しの期間をサンプリングして適当に平均を返す。わりとこれでもそれっぽく音の大小をとれる。
#define LEFT A2
#define SAMPLE 100
void setup() {
Serial.begin(9600);
analogReference(INTERNAL);
pinMode(LEFT, INPUT);
}
void loop() {
Serial.println(getLevel(LEFT));
}
uint8_t getLevel(uint8_t pin) {
float avg = 0;
float raw;
for (int sample = 0; sample < SAMPLE; sample++) {
raw = analogRead(pin);
avg += raw;
}
return avg/SAMPLE;
}
ちなみに全波で整流すると、VF*2の電圧下降が起こるのでちょっと厳しそう。
追記・静かな曲だと 400mV の電圧降下でもほぼ値をとれなくなってしまう…。
レベルシフトで持ち上げる (Arduino の 5V を使う)
ピーク値が交流±1.8Vなら、それをレベルシフトして読み取れる範囲にする方法。
にあるとおり、レベルシフトで Arduino の出力している直流 5V を抵抗分圧で 2.5V にしてを加えることによって、信号を2.5Vの±1.8Vにすることで、 ADC で読み取れる 0V~5V の範囲に収める。
10uFのコンデンサは直流をカットして交流成分だけ流す用途、だと思う…。(違ったら教えてください…。)
なお交流からの入力が何も無い場合、2.5Vを期待する(analogRead()で512になってほしい)が、実際は抵抗分圧時の誤差があるので、少しずれる(カーボン抵抗の5%誤差から、金属皮膜抵抗の0.5%や1%誤差だとだいぶ緩和する)ので、中央値を512から変える必要が出てくる。
#define LEFT A2
#define SAMPLE 100
#define CENTER 512
void setup() {
Serial.begin(9600);
pinMode(LEFT, INPUT);
}
void loop() {
Serial.println(getLevel(LEFT));
}
uint8_t getLevel(uint8_t pin) {
float avg = 0;
float raw;
for (int sample = 0; sample < SAMPLE; sample++) {
raw = analogRead(pin);
avg += abs(raw - CENTER);
}
return avg/SAMPLE;
}
OPアンプを使う
非反転アンプ単電源用 交流結合型の方法で、+2.5Vに増幅の基準電圧をあわせることにより、0~5V の値として取得できる。ググっても出てくるけど、書籍 回路の素101 の項目007の「非反転アンプ単電源用 交流結合型」が大変解りやすかった。
その回路のオペアンプを LM358N に変えて 1000Hz のサイン波のオーディオ入力を2倍の出力に増幅してみた。最初C1(0.1u)を入れずに全く出力が出なくてうーん、と思ったんだけど、コンデンサを入れて直流成分のカットが必要なことが解った。(直流成分のカットが具体的に何かはまだ解っていない…)
まとめ
音量がコンスタントに大きいなら、単相短波なら1ショットキーと1抵抗の整流でも割とそれっぽい値がとれる。そうじゃないならダイオードによる電圧降下が馬鹿にならないので、レベルシフトなりオペアンプを使った方が良さそう。