2016年6月9日木曜日

デジタルマイクが動かない(SPI DAC出力編

Board1 - Mic - ADC+D級AMP

■ノイズしか出ねえ■

前回のあらすじ。秋月で300円のデジタルマイクモジュールを試してみたものの、マイコンからパルスを入れてもそれっぽい信号が取れている気がしない。でも、出力をLPF通してアンプにつないだら音が出ていた。

ということはPDMとしての動作はOKであとはデジタルとしてどうやったら信号を取り込めるか、ということになります。

ESP-WROOM-02を160Mhzで動かし、約1mhzでデューティー比50%近いパルスを入れてダウンエッジから約60nSecぐらいのところで取り込んだデータを集計してDACから出力してみたのですが…雑音しか出て来ませんでしたorz

ということで、以下失敗の記録です。なお、失敗記録を読んでもしょうがない、という方は先にこちら(デジタルマイクSPM0405HD4Hがデジタルで動いた!)をどうぞ。

■SPIと競合しちゃう■

最初GPIO12から信号を読み込んで居たのですが、ずっとゼロでした。SPIライブラリの内部で何かに使っているようです。GPIO5からクロック出力、GPIO4からデータ入力…という形にしたところ、読み込みできました。

なお、DACはMCP4922を使い、配線は以下の通りです。正しく動作しているかどうかは例によってノコギリ波で確認しました。

ESP8266SPM0405HD4HMCP4922
GPIO4DAT
GPIO5CLK
3v3Vcc1, 1, 11, 13
GndGnd, L/R12 GND
GPIO135 SDI
GPIO144 SCK
GPIO153 !CS
GPIO168 !LDAC


■最適化されちゃう■

タイミングやデューティー比を調整するために意味のないインクリメントを入れてみたのですが、localで宣言した意味のない演算は最適化で消されちゃうみたいですね。
for (int i = 0; i < n; i++) {
  int a = 0;
  a++;
  a++;
}
a++を増やしても結果変わりません。

void loop()の外で
int a = 0;
を宣言すると1つあたり25nSec程度の遅延が得られます。

digitalWrite(x, HIGH)で225nSec、digitalWrite(x, LOW)で212.5nSec程度の処理時間がかかります。

■試行錯誤しちゃう■

  • 現在のソースではダウンエッジだがアップエッジでも試す。ダウンエッジとアップエッジをLRライン=LOW/HIGH両方で試す。
  • ループ前にcountを0にして入力HIGHなら加算。あるいはLOWなら加算
    ▶ノイズだけ
  • ループ前にcountを毎回初期化せず、HIGHなら加算, LOWなら減算。あるいは逆
    ▶発散しました
  • ループ回数を減らしたり増やしたり
    ▶ノイズの音質が変わりますw
  • パルス出力からサンプリングまでのタイミングを増やしたり減らしたり
    ▶ノイズの音質が変わりますw
浩一はもう疲れました…。


■ソース■

loop内でforループから抜けた後のSerialは、タイミングなどを確認した後にコメントアウトしてます。処理時間がものすごく長いので。それとArduino IDEではツールメニュー>CPU Frequencyで160Mhzを選んでください。80Mhzだとクロック500khzしか出ませんので。

// ESP_Digital_MIC_To_DAC
// by koichi kurahashi 2016-06-08
//
// read SPM0405HD4H and write to MCP4921
//
// this source does not work. this is just a noise generater.
//
// 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
//
long a, b; // dummy wait
void loop() {
uint16_t count = 0;
int m = micros();
for (int l = 0; l < 256; l++) { // 25n
digitalWrite(kOutClock, LOW); // low 212.5n
a++; b++;
if (digitalRead(kInSignal) == HIGH) {
count++;
}
digitalWrite(kOutClock, HIGH); // high=225.0n
a++; b++;
}
Serial.print(micros() - m);
Serial.print(",");
Serial.println(count);
outputToDAC(count * 20);
}
void outputToDAC(uint16_t inData) {
inData = inData & 0xfff;
digitalWrite(kPinLatchDAC, HIGH);
digitalWrite(SS, LOW);
SPI.transfer16(inData | 0x3000);
digitalWrite(SS, HIGH);
digitalWrite(kPinLatchDAC, LOW) ;
}

■そして…■

0 件のコメント:

コメントを投稿

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