2016年6月10日金曜日

デジタルマイクSPM0405HD4Hがデジタルで動いた!

このまま「またデジタルマイクが動かない」「やっぱりデジタルマイクが動かない」「まだまだデジタルマイクが動かない」と長編化するかと思われたデジタルシリコンマイク、ついに動きました!


■考察■

今までも動いていたけどノイズに埋もれてわからなかった、というのが真相だと思います。

動かなかったバージョンでは100-10000回のカウントを終えるとLoopを抜けていました。これはESP-WROOM-02にはWDTがついていて、約1秒間loop()から抜けないとリセットがかかるのです。

何となくloop()抜けてもすぐに帰ってくるんだろ、ぐらいに考えていたんですが、これが想定以上に大きくて、抜けるたびに処理が止まってノイズとなっていました。loopから抜けるのをやめてESP.wtdFeed()にしたところ、かすかなノイズは入りますがマイクの前の音声がちゃんとADCから出力されるようになりました。

■ソース■

loopの値は100(サンプリング周波数10khz)ぐらいが良いようで、10(100khz)だとDACに出力するためのブランクの比率が著しいノイズとなり1000(1khz)にすると割れて何が何だか、という感じでした。また、countとして++だけでなく--も入れてみたところ、音量がかなり大きくなりました。100の場合で値は-100〜+100まで振れるので、精度は8bit、速度は10khzということになります。



// ESP_Digital_MIC_To_DAC
// by koichi kurahashi 2016-06-08
//
// read SPM0405HD4H and write to MCP4921
//
// Thanks:
// http://www.pwv.co.jp/~take/TakeWiki/index.php?arduino%2FDACを試す
// arduino/DACを試す
//
#include <Arduino.h>
#include <SPI.h>
extern "C" {
#include <user_interface.h>
}
//
// SPM0405
//
#define kOutClock 5 // to CLK
#define kInSignal 4 // from DAT
// L/R is connected to GND -> down edge mode
//
// DAC MCP4921
//
// GPIO 13 - Pin 5 SDI
// 14 - 4 SCK
// 15 - 3 !CS
// 16 - 8 LDAC
// 1, 9, 11, 13 - Vcc
// 12 - Gnd
// 1 - 0.1uF - 13
//
const int kPinLatchDAC = 16;
void setup() {
// put your setup code here, to run once:
Serial.begin(230400);
pinMode(kOutClock, OUTPUT);
pinMode(kInSignal, INPUT);
setupDac();
}
// DAC init
//
void setupDac() {
// set pinMode
pinMode(kPinLatchDAC, OUTPUT);
pinMode(SS, OUTPUT);
// init SPI for DAC
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV8);
SPI.setDataMode(SPI_MODE0);
}
//
// loop
//
const int kMaxLoop = 100;
const int kMaxDAC = 4095;
const int kMaxRate = 2000 / kMaxLoop;
const int kMaxOffset = kMaxDAC / 2;
const int kOutLoop = 10000 / kMaxLoop;
long a, b; // dummy wait
void loop() {
// int min = 32767;
// int max =-32767;
while (1) {
for (int i = 0; i < kOutLoop; i++) {
int count = 0;
for (int l = 0; l < kMaxLoop; l++) { // 25n
digitalWrite(kOutClock, LOW); // low 212.5n
a++; b++;
if (digitalRead(kInSignal) == HIGH) {
count++;
}
else {
count--;
}
if (l < kMaxLoop - 1) {
digitalWrite(kOutClock, HIGH); // high=225.0n
digitalWrite(kOutClock, HIGH); // high=225.0n
}
}
count = count * kMaxRate + kMaxOffset;
outputToDAC(count);
// if (count > max) max = count;
// if (count < min) min = count;
}
// Serial.print(min);
// Serial.print(",");
// Serial.println(max);
ESP.wdtFeed();
}
}
void outputToDAC(uint16_t inData) {
inData = inData & 0xfff;
digitalWrite(kPinLatchDAC, HIGH);
digitalWrite(SS, LOW);
SPI.transfer16(inData | 0x3000);
digitalWrite(SS, HIGH);
digitalWrite(kPinLatchDAC, LOW) ;
}


お騒がせしました&ありがとうございました>電子工作部各位殿

もうちょっと高速のCPUが使えれば、DAC出力その他のための中断を回避できるので、もっといい音になると思います。現状で160Mhzクロックの32bit CPUなので、これより上のCPUを用意するよりはFPGAで作るべきものだと思います。約400円で専用チップ売ってるんですけどねw

ちなみにマイクの性能には「14bit相当・10khz」とのこと。うーん、どういう演算処理をすればそういう信号が得られるのでしょう。思いついたらまた試してみます。

■使用部品紹介という名のCM■

今回の実験では、
同社サイトより


同社サイトより

同社サイトより

を使用しました。

マイクモジュールとアンプへの3v3はBoard1搭載の安定化電源から供給しています。何かと電源にシビアなESPですが、(プログラムのバグ以外では)安定して動作しています。

タフな電源にしといてよかった…と設計者は胸をなでおろすのであった(完)。

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。