recording audio with i2s microphone, teensy 3.6, audio shield or no audio shield

Status
Not open for further replies.

tmratwork

Member
i have tried the example teensy programs to test my audio shield, and my record files full of zeros. for beginner, maybe it is easier to do version one of recording without the audio shield (one less piece of hardware to hookup, and the audio shield covers all the holes in my breadboard).

looks like two ways to record audio:
.. Teensy's audio library
.. i2s (the only one i could get to work is at https://github.com/nodae/teensy_i2s_experimental)

Teensy audio library:
1) has anyone found sample code using teensy audio library to record from an i2s mic like Adafruit I2S MEMS Microphone Breakout - SPH0645LM4H (3421)? i have tried with the example codes, including File > Examples > Audio > Recorder. the recorder program shows how to wire analog mic, or line in from external equipment, but cannot find anything about how to wire the SPH0645LM4H i2s digital mic. nor could i find the sample rate or bits per sample.

i2s:
2) onehorse code looks like what i need, it shows pin connections clearly (https://forum.pjrc.com/threads/4085...-without-board?p=128167&viewfull=1#post128167), but when i run it, capture the serial output, import to audacity, my recordings a constant high pitch sound. i am using sample rate of 48000 and 32 bits per sample. this is guess based on onehorse code. has anyone experience issue of recordings being 100% high pitch tone?

i've spent two days googling. i'm ready to spend more, any hints?

thanks!
 
i have tried with the example codes, including File > Examples > Audio > Recorder. the recorder program shows how to wire analog mic, or line in from external equipment, but cannot find anything about how to wire the SPH0645LM4H i2s digital mic.

The I2S connections are documented in the design tool (like almost everything about the audio library). Here's a direct link.

https://www.pjrc.com/teensy/gui/?info=AudioInputI2S

In the right side panel, scroll down to "Hardware" and look for the table showing the 4 signals.

The SPH0645LM4H mic does not use MCLK (but many other I2S chips need it), so do not connect any wire from Teensy pin 11 to this mic. The other 3 signals and GND need to be connected to Teensy GND, and 3V on the mic connects to 3.3V on Teensy. The mic also has a SEL pin, which needs to be connected to either GND or 3V. That pin determines whether the mic sends it data on the left or right channel. If you get all zeros, try the other channel.

If it *still* won't work, we can try to help you troubleshoot, but you need to post photos showing how you actually connected everything.

nor could i find the sample rate or bits per sample.

The audio lib always uses 16 bits and 44.1 kHz sample rate. Those aren't configurable (unless you hack the code... it is all open source) so there aren't any options for configuring those things.
 
How do you check if the RAW file is all zeros?

If you get all zeros, try the other channel.

Hi, I followed the instructions above of how to connect this particular microphone. And I slightly changed the code so that I could control record, play and stop using three buttons. When I pressed "Record", I could see that the time of writing each buffer was being printed out. But I don't hear any sound being played back when I pressed the "play", not even small impulses. I tried change the channel and it still woundn't work. However, there was a RAW file stored in the SD card when I plugged it into my computer.

Could you help me? Thank you!!



Code:
// https://forum.pjrc.com/threads/46150-Recording-Stereo-Audio-to-SD-Card?p=158682&viewfull=1#post158682
// 16 bit 44.1khz

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>

// GUItool: begin automatically generated code
// AudioInputI2S            i2s1;           //xy=168,145
// AudioRecordQueue         queue1;         //xy=360,62
// AudioRecordQueue         queue2;         //xy=389,145
// AudioConnection          patchCord1(i2s1, 0, queue1, 0);
// AudioConnection          patchCord2(i2s1, 1, queue2, 0);
AudioInputI2S            i2s1;           //xy=795.0507765549878,631.375527015099
AudioPlaySdRaw           playSdRaw1;     //xy=914.281545785757,742.9139885535606
AudioRecordQueue         queue1;         //xy=974.281545785757,586.7601423997144
AudioRecordQueue         queue2;         //xy=975.8200073242185,654.4524500920221
AudioOutputI2S           i2s2;           //xy=1095.0507765549878,740.6062962458683
AudioConnection          patchCord1(i2s1, 0, queue1, 0);
AudioConnection          patchCord2(i2s1, 1, queue2, 0);
AudioConnection          patchCord3(playSdRaw1, 0, i2s2, 0);
AudioConnection          patchCord4(playSdRaw1, 0, i2s2, 1);
// AudioControlSGTL5000     sgtl5000_1;     //xy=981.2046227088339,815.2216808612528
// GUItool: end automatically generated code

// which input on the audio shield will be used?
// const int myInput = AUDIO_INPUT_LINEIN;
// const int myInput = AUDIO_INPUT_MIC;


// Use these with the Teensy Audio Shield
// #define SDCARD_CS_PIN    10
// #define SDCARD_MOSI_PIN  7
// #define SDCARD_SCK_PIN   14

// Use these with the Teensy 3.5 & 3.6 SD card
#define SDCARD_CS_PIN    BUILTIN_SDCARD // 254?
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used

Bounce buttonRecord = Bounce(4, 8);
Bounce buttonStop =   Bounce(3, 8);  // 8 = 8 ms debounce time
Bounce buttonPlay =   Bounce(2, 8);

// Remember which mode we're doing
int mode = 0;  // 0=stopped, 1=recording, 2=playing

// The file where data is recorded
File frec;

void setup() {
  // Configure the pushbutton pins
  pinMode(4, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  
  // record queue uses this memory to buffer incoming audio.
  AudioMemory(120); // 60

  // Enable the audio shield, select input, and enable output
  // sgtl5000_1.enable();
  // sgtl5000_1.inputSelect(myInput);
  // sgtl5000_1.volume(0.5);
   
  // Initialize the SD card
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    // stop here if no SD card, but print a message
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  // startRecording();
}


void loop() {
  buttonRecord.update();
  buttonStop.update();
  buttonPlay.update();
  
  // Respond to button presses
  if (buttonRecord.fallingEdge()) {
    Serial.println("Record Button Press");
    if (mode == 2) stopPlaying();
    if (mode == 0) startRecording();
  }
  if (buttonStop.fallingEdge()) {
    Serial.println("Stop Button Press");
    if (mode == 1) stopRecording();
    if (mode == 2) stopPlaying();
  }
  if (buttonPlay.fallingEdge()) {
    Serial.println("Play Button Press");
    if (mode == 1) stopRecording();
    if (mode == 0) startPlaying();
  }

  // If we're playing or recording, carry on...
  if (mode == 1) {
    continueRecording();
  }
  if (mode == 2) {
    continuePlaying();
  }
  
  // if (millis() > 20000 && mode == 1) {
  //  stopRecording();
  // }
  // else {
  //  if (mode == 1) continueRecording();
  // }
  
}

void startRecording() {
  Serial.println("StartRecording");
  if (SD.exists("RECORD.RAW")) {
    // The SD library writes new data to the end of the
    // file, so to start a new recording, the old file
    // must be deleted before new data is written.
    SD.remove("RECORD.RAW");
  }
  frec = SD.open("RECORD.RAW", FILE_WRITE);
  if (frec) {
    Serial.println("File Open");
    queue1.begin();
    queue2.begin();
    mode = 1;
  }
}

// write all 512 bytes to the SD card   
void continueRecording() {
  if (queue1.available() >= 2 && queue2.available() >= 2) {
    byte buffer[512];
    // Fetch 2 blocks from the audio library and copy
    // into a 512 byte buffer.  The Arduino SD library
    // is most efficient when full 512 byte sector size
    // writes are used.
    byte bufferL[256];
    byte bufferR[256];
    memcpy(bufferL, queue1.readBuffer(), 256);
    queue1.freeBuffer();
    memcpy(bufferR, queue2.readBuffer(), 256);
    queue2.freeBuffer();
    int b = 0;
    for (int i = 0; i < 512; i += 4) {
      buffer[i] = bufferL[b];
      buffer[i + 1] = bufferL[b + 1];
      buffer[i + 2] = bufferR[b];
      buffer[i + 3] = bufferR[b + 1];
      b = b+2;
    }
    elapsedMicros usec = 0;
    frec.write(buffer, 512);
    // print out how long SD writes are taking
    Serial.print("SD write, us=");
    Serial.println(usec);
  }
}

void stopRecording() {
  Serial.println("StopRecording");
  queue1.end();
  queue2.end();
  if (mode == 1) {
  // flush buffer
    while (queue1.available() > 0 && queue2.available() > 0) {
      queue1.readBuffer();
      queue1.freeBuffer();
      queue2.readBuffer();
      queue2.freeBuffer();
    }
    frec.close(); // close file
  }  
  mode = 0;
}

void startPlaying() {
  Serial.println("startPlaying");
  playSdRaw1.play("RECORD.RAW");
  mode = 2;
}

void continuePlaying() {
  if (!playSdRaw1.isPlaying()) {
    playSdRaw1.stop();
    mode = 0;
  }
}

void stopPlaying() {
  Serial.println("stopPlaying");
  if (mode == 2) playSdRaw1.stop();
  mode = 0;
}
 
@yihanhu - Please start a new thread, and in your first message show us how to connected the hardware. You need to show, not just tell but show (like photos, diagrams, etc), what was actually done. We're pretty good here about figuring out why projects don't work when we can see everything. But from description that gives no more info than "I followed the instructions", we just can't do much. Also harder as a reply. Please start a new thread, and start it by actually showing photos and details of exactly how you connected these parts.
 
Status
Not open for further replies.
Back
Top