4 Channel TDM (I2S) Teensy 3.6 with Invensense ics 52000

Status
Not open for further replies.

amperwest1

New member
------------------------------------
Admin Edit: ICS-52000 microphones do not appear to work well with Teensy at 44100 Hz sample rate.
------------------------------------



Firstly apologies if in wrong part of forum, please move/advise if wrong. My first post so be gentle.

I am working on an audio recording project looking at using the Invensense ics52000 (https://www.invensense.com/products/ics-52000/), I have bought the larger development board(to allow expansion later in project) (https://www.digikey.com/en/product-highlight/i/invensense/ics-52000-tdm-array-demo-board).
(the array board has jumper selection to allow 4,8,12,16 mics on the line, currently using only 4)

I have followed the previous threads on here using the 4 microphone array board from notwired, and have successfully recorded sound with one microphone to sd card using the recorder example and Dreggory's final code post on another thread.(https://forum.pjrc.com/threads/48563-Cheap-ICS-52000-Microphone-Array-Board-for-TDM-evaluation)

However, my project is hoping to use 4x microphones sharing the TDM bus with potential to use 8 microphones.

From what I've learnt from the previous code and playing with the GUI designer is that I can attach queues to the TDM input device and then read them sequentially using available() and then read() functions. I have tried expanding Dreggory's code by adding 8x queues and then writing them to Sd in the same style, but when I import these files into Matlab/Audacity the files are much shorter (4sec instead of 11sec) and often missing data. (testing by playing pure 300Hz sine wave from speaker closer to mic array)

Sorry for the long post, I just wanted to show that I'm working through it before asking for help, so a few questions:
-One microphone records at 44.1kHz, does this mean 4 at at 44.1k or is the frequency divided by 4?
-Is the teensy 3.6 capable of this speeds with writing to the SD card for long period of time (end product is looking at ~10min recording time)
- Is it possible to use the audio library for this task or will I have to 'roll my own'?

Thanks in advance
 
Last edited by a moderator:
-One microphone records at 44.1kHz, does this mean 4 at at 44.1k or is the frequency divided by 4?

No. They're all at 44.1 kHz.


-Is the teensy 3.6 capable of this speeds with writing to the SD card for long period of time (end product is looking at ~10min recording time)

Maybe with SdFat. And with it's more complex way of writing larger blocks. And perhaps with pre-allocating the file and using the command to make sure the flash is erased. Maybe?

But definitely not with the normal SD library.
 
Thanks for the quick reply.

I shall look into the SdFat library, currently using a very cheap microSD (free with an rc toy) as my other ones are all 64gb+. I have a new one arriving hopefully tomorrow, hopefully i can inch some more speed with that.

Is there a way to reduce the sample rate from 44.1k to 10k as the frequencies I'm concerned with are <1k, I have seen some previous posts on 'setI2Sfreq' but many are from a few years ago and I'm wondering if such a function has been implemented yet?

Thanks again
 
Is there a way to reduce the sample rate from 44.1k to 10k as the frequencies I'm concerned with are <1k,

Yes, there is a way, but it will require editing of the TDM configuration code in the library. If you slow down MCLK, everything else should follow. Just be sure you do *not* use any other input or output objects (like DAC, ADC, etc) which depend on the entire library running at the same speed.
 
Thanks for help.
Just as a summary of what I have done, just in case anyone else is looking at using these libraries for non-pure audio recording.
The following allowed simultaneous recording at 10kHz per channel for 4 channels.

Adjusted the MCLK to 10kHz:
By changing defines for the MCLK fraction and divider in output_tdm.cpp (line 141 onward)
Teensy libs here (Win 10):C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio
Looking at the datasheet (https://www.pjrc.com/teensy/K66P144M180SF5RMV2.pdf) page:2138 I worked out what the different divider values were doing.
For TDM it needs a clock for 16 words (16*32=512), so for any sample rate (Fs) you must divide the system clock (Fcpu) down and then divide by 512 to get Fs.

Formula for calculating this: (Fs*512)/Fcpu=(Fract/Divider)
eg. (10000*512)/240,000,000=(8/375)
edited code:
Code:
#if F_CPU == 96000000 || F_CPU == 48000000 || F_CPU == 24000000
  // PLL is at 96 MHz in these modes
  #define MCLK_MULT 4
  #define MCLK_DIV  17
#elif F_CPU == 72000000
  #define MCLK_MULT 16
  #define MCLK_DIV  51
#elif F_CPU == 120000000
  #define MCLK_MULT 16
  #define MCLK_DIV  85
#elif F_CPU == 144000000
  #define MCLK_MULT 8
  #define MCLK_DIV  51
#elif F_CPU == 168000000
  #define MCLK_MULT 16
  #define MCLK_DIV  119
#elif F_CPU == 180000000
  #define MCLK_MULT 32
  #define MCLK_DIV  255
  #define MCLK_SRC  0
#elif F_CPU == 192000000
  #define MCLK_MULT 2
  #define MCLK_DIV  17
#elif F_CPU == 216000000
  #define MCLK_MULT 16
  #define MCLK_DIV  153
  #define MCLK_SRC  0
#elif F_CPU == 240000000
 //#define MCLK_MULT 8			//original for 44.1kHz
 //#define MCLK_DIV  85
  #define MCLK_MULT 8			//edit for 10kHz sample
  #define MCLK_DIV  375
//#define MCLK_MULT 32			//edit for 8kHz sample
//#define MCLK_DIV  1875
//#define MCLK_MULT 4			//edit for 5kHz sample
//#define MCLK_DIV  375
#else
  #error "This CPU Clock Speed is not supported by the Audio library";
#endif

Then using Dreggory's code as a template I edited it for use with 4 microphones, here:
Code:
// Record TDM input sound as raw data (16ch, Signed 24-bit little-endian PCM, 44.1kHz, little-endian) to a SD card.
// Note: Format is modified so that mics align their 24 bit data to 32 bit slots, half of the 16 bit
// channels end up being the 8 low bits, and 8 more zeros which are discarded.
//
// Hardware:
//   Mic Pin 6  (SD_O)  to Teensy Pin  13 SDATA  (Input, 11.3 Mbit/sec)
//   Mic Pin 8  (SCK_I) to Teensy Pin  9 SCK     (Output, 11.3 MHz, Checked)
//   Mic Pin 10 (WS_I)  to Teensy Pin  23 FS     (Output, 44100 Hz, Checked)
//
//   Mic GND Pins (1, 3, 5, 7 and 9) to Teensy GND
//   Mic VDD to Teensy 3.3V

//   At startup of the ICS-52000, the start of the frame sync (WS_I) signal should be delayed from the start of the serial clock (SCK_I) by at
//   least 10 ms. This enables the microphone’s internal circuits to completely initialize before starting the synchronization sequence
//   with other microphones in the TDM array. This delay can be implemented either by enabling the WS output (FS) on the clock master at
//   least 10 ms after the SCK_I is enabled, or by externally controlling the signals given to the ICS-52000s.
//
//
// This example code is in the public domain.

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

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

// GUItool: begin automatically generated code
AudioInputTDM            tdm1;           //xy=151,223
AudioRecordQueue         queue4;         //xy=416,221
AudioRecordQueue         queue5;         //xy=416,254
AudioRecordQueue         queue6;         //xy=416,287
AudioRecordQueue         queue7;         //xy=416,320
AudioRecordQueue         queue3;         //xy=417,187
AudioRecordQueue         queue8;         //xy=417,353
AudioRecordQueue         queue2;         //xy=418,154
AudioRecordQueue         queue1;         //xy=419,120
AudioConnection          patchCord1(tdm1, 0, queue1, 0);
AudioConnection          patchCord2(tdm1, 1, queue2, 0);
AudioConnection          patchCord3(tdm1, 2, queue3, 0);
AudioConnection          patchCord4(tdm1, 3, queue4, 0);
AudioConnection          patchCord5(tdm1, 4, queue5, 0);
AudioConnection          patchCord6(tdm1, 5, queue6, 0);
AudioConnection          patchCord7(tdm1, 6, queue7, 0);
AudioConnection          patchCord8(tdm1, 7, queue8, 0);
// GUItool: end automatically generated code

// GUItool: end automatically generated code

// 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
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used

// Use these for the SD+Wiz820 or other adaptors
//#define SDCARD_CS_PIN    4
//#define SDCARD_MOSI_PIN  11
//#define SDCARD_SCK_PIN   13

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

unsigned int tsamplemillis = 10000;

String typeofsound;

int16_t* buffer1;
int16_t* buffer2;
int16_t* buffer3;
int16_t* buffer4;
int16_t* buffer5;
int16_t* buffer6;
int16_t* buffer7;
int16_t* buffer8;

// The file where data is recorded
File frec;

void setup() {

  Serial.begin(115200);
  // Audio connections require memory, and the record queue
  // uses this memory to buffer incoming audio.
  AudioMemory(512);

  // 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);
    }
  }
  while (!Serial);
  Serial.println("Welcome to the 4-channel TDM recording test bench");
}

void loop() {

  if (choice == 0) {
    Serial.println("\nEnter new filename for sound archive: ");
    while (!Serial.available());
    typeofsound = Serial.readString();
    sample_number = 0;
    record(typeofsound, sample_number);
  } else if (choice == 1) {
    sample_number++;
    record(typeofsound, sample_number);
  } else {
    //Do nothing
  }

  Serial.print("\nEnter 1 to take another sample in this archive or 0 to enter a new file archive: ");
  while (!Serial.available());
  choice = Serial.readString().toInt();
  Serial.println(choice);
}

void record(String type, int number)
{
  Serial.println("Recording " + type + String(number) + "...");
  String sname = type + number + ".RAW";
  String path = type + "/" + type + number + ".RAW";
  startRecording(sname, path, type);
  continueRecording();
  stopRecording();
}

void startRecording(String sname, String path, String type)
{
  int str_len = path.length() + 1;
  char charpath[str_len];
  path.toCharArray(charpath, str_len);

  if (SD.exists(charpath)) {
    // 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(charpath);
  }

  str_len = type.length() + 1;
  char chartype[str_len];
  type.toCharArray(chartype, str_len);

  if (!SD.exists(chartype)) {
    SD.mkdir(chartype);
  }

  frec = SD.open(charpath, FILE_WRITE);
  if (frec) {
    Serial.println("File Open");
  }
}

void continueRecording() {
  int data = 0, num = 0;
  elapsedMillis recordingTime = 0;
  queue1.begin();
  queue2.begin();
  queue3.begin();
  queue4.begin();
  queue5.begin();
  queue6.begin();
  queue7.begin();
  queue8.begin();
  mode = 1;
  while (recordingTime < tsamplemillis)
  {
    data = queue1.available();
    if (data > 0)
    {
      buffer1 = queue1.readBuffer();      //read all queue buffers in sets of 128 16bit num
      buffer2 = queue2.readBuffer();
      buffer3 = queue3.readBuffer();
      buffer4 = queue4.readBuffer();
      buffer5 = queue5.readBuffer();
      buffer6 = queue6.readBuffer();
      buffer7 = queue7.readBuffer();
      buffer8 = queue8.readBuffer();
      queue1.freeBuffer();                //free queue buffers to allow system to re issue storage
      queue2.freeBuffer();
      queue3.freeBuffer();
      queue4.freeBuffer();
      queue5.freeBuffer();
      queue6.freeBuffer();
      queue7.freeBuffer();
      queue8.freeBuffer();
      if (data > 48)        //test if queue buffers are getting too full, the serial write will probably cause a back log if it does happen.
      {
        Serial.write('.');    //dots in the serial monitor mean that the system isnt processing data fast enough
      }
      for (int i = 0; i < 128; i ++)                        //write data to sd card in 24bit signed pcm format (i think) (audacity seems to accept it)
      { //frames are built of 2 16 bit numbers where only 24 bits are useful, so only 3 bytes are saved to save space. Frames are little endian
        frec.write(highByte(buffer2[i])); // LSB            //<---------------------sample 1---------------------><---------------------sample n--------------------->
        frec.write(lowByte(buffer1[i])); // Middle Byte     //<----ch1----><----ch2----><----ch3----><----ch4----><----ch1----><----ch2----><----ch3----><----ch4---->
        frec.write(highByte(buffer1[i])); // MSB            //<LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB>
        frec.write(highByte(buffer4[i])); // LSB
        frec.write(lowByte(buffer3[i])); // Middle Byte
        frec.write(highByte(buffer3[i])); // MSB
        frec.write(highByte(buffer6[i])); // LSB
        frec.write(lowByte(buffer5[i])); // Middle Byte
        frec.write(highByte(buffer5[i])); // MSB
        frec.write(highByte(buffer8[i])); // LSB
        frec.write(lowByte(buffer7[i])); // Middle Byte
        frec.write(highByte(buffer7[i])); // MSB
        num++;
      }
    }
  }
  queue1.end();     //stop the background sampling
  queue2.end();
  queue3.end();
  queue4.end();
  queue5.end();
  queue6.end();
  queue7.end();
  queue8.end();
  Serial.print("num of samples written per channel:");
  Serial.println(num);
}


void stopRecording() {
  Serial.println("Finished recording.");
  queue1.end();
  queue2.end();
  queue3.end();
  queue4.end();
  queue5.end();
  queue6.end();
  queue7.end();
  queue8.end();
  queue1.clear();
  queue2.clear();
  queue3.clear();
  queue4.clear();
  queue5.clear();
  queue6.clear();
  queue7.clear();;
  queue8.clear();
  frec.close();
  mode = 0;
}

And recorded 99968 4-channel samples in 10 seconds (i can cope with being 32 off for now)

The result when imported into audacity using 24bit signed pcm, 4 channel, Fs=10000. The result of a recorded 300Hz sine wave looked like this:
Capture.jpg
(amplitudes are very small, due to having to play sound with pc speakers quietly as its late)

Apologies if any of the things stated aren't true, attempting to self teach myself in the early hours. Feel free to correct me or suggest improvements.

After only having the Teensy for 2 days now, I am already very impressed. Thanks for a great product and the forum!
 
NO data save on the SD card , why?

Thanks for help.
Just as a summary of what I have done, just in case anyone else is looking at using these libraries for non-pure audio recording.
The following allowed simultaneous recording at 10kHz per channel for 4 channels.

Adjusted the MCLK to 10kHz:
By changing defines for the MCLK fraction and divider in output_tdm.cpp (line 141 onward)
Teensy libs here (Win 10):C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Audio
Looking at the datasheet (https://www.pjrc.com/teensy/K66P144M180SF5RMV2.pdf) page:2138 I worked out what the different divider values were doing.
For TDM it needs a clock for 16 words (16*32=512), so for any sample rate (Fs) you must divide the system clock (Fcpu) down and then divide by 512 to get Fs.

Formula for calculating this: (Fs*512)/Fcpu=(Fract/Divider)
eg. (10000*512)/240,000,000=(8/375)
edited code:
Code:
#if F_CPU == 96000000 || F_CPU == 48000000 || F_CPU == 24000000
  // PLL is at 96 MHz in these modes
  #define MCLK_MULT 4
  #define MCLK_DIV  17
#elif F_CPU == 72000000
  #define MCLK_MULT 16
  #define MCLK_DIV  51
#elif F_CPU == 120000000
  #define MCLK_MULT 16
  #define MCLK_DIV  85
#elif F_CPU == 144000000
  #define MCLK_MULT 8
  #define MCLK_DIV  51
#elif F_CPU == 168000000
  #define MCLK_MULT 16
  #define MCLK_DIV  119
#elif F_CPU == 180000000
  #define MCLK_MULT 32
  #define MCLK_DIV  255
  #define MCLK_SRC  0
#elif F_CPU == 192000000
  #define MCLK_MULT 2
  #define MCLK_DIV  17
#elif F_CPU == 216000000
  #define MCLK_MULT 16
  #define MCLK_DIV  153
  #define MCLK_SRC  0
#elif F_CPU == 240000000
 //#define MCLK_MULT 8			//original for 44.1kHz
 //#define MCLK_DIV  85
  #define MCLK_MULT 8			//edit for 10kHz sample
  #define MCLK_DIV  375
//#define MCLK_MULT 32			//edit for 8kHz sample
//#define MCLK_DIV  1875
//#define MCLK_MULT 4			//edit for 5kHz sample
//#define MCLK_DIV  375
#else
  #error "This CPU Clock Speed is not supported by the Audio library";
#endif

Then using Dreggory's code as a template I edited it for use with 4 microphones, here:
Code:
// Record TDM input sound as raw data (16ch, Signed 24-bit little-endian PCM, 44.1kHz, little-endian) to a SD card.
// Note: Format is modified so that mics align their 24 bit data to 32 bit slots, half of the 16 bit
// channels end up being the 8 low bits, and 8 more zeros which are discarded.
//
// Hardware:
//   Mic Pin 6  (SD_O)  to Teensy Pin  13 SDATA  (Input, 11.3 Mbit/sec)
//   Mic Pin 8  (SCK_I) to Teensy Pin  9 SCK     (Output, 11.3 MHz, Checked)
//   Mic Pin 10 (WS_I)  to Teensy Pin  23 FS     (Output, 44100 Hz, Checked)
//
//   Mic GND Pins (1, 3, 5, 7 and 9) to Teensy GND
//   Mic VDD to Teensy 3.3V

//   At startup of the ICS-52000, the start of the frame sync (WS_I) signal should be delayed from the start of the serial clock (SCK_I) by at
//   least 10 ms. This enables the microphone’s internal circuits to completely initialize before starting the synchronization sequence
//   with other microphones in the TDM array. This delay can be implemented either by enabling the WS output (FS) on the clock master at
//   least 10 ms after the SCK_I is enabled, or by externally controlling the signals given to the ICS-52000s.
//
//
// This example code is in the public domain.

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

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

// GUItool: begin automatically generated code
AudioInputTDM            tdm1;           //xy=151,223
AudioRecordQueue         queue4;         //xy=416,221
AudioRecordQueue         queue5;         //xy=416,254
AudioRecordQueue         queue6;         //xy=416,287
AudioRecordQueue         queue7;         //xy=416,320
AudioRecordQueue         queue3;         //xy=417,187
AudioRecordQueue         queue8;         //xy=417,353
AudioRecordQueue         queue2;         //xy=418,154
AudioRecordQueue         queue1;         //xy=419,120
AudioConnection          patchCord1(tdm1, 0, queue1, 0);
AudioConnection          patchCord2(tdm1, 1, queue2, 0);
AudioConnection          patchCord3(tdm1, 2, queue3, 0);
AudioConnection          patchCord4(tdm1, 3, queue4, 0);
AudioConnection          patchCord5(tdm1, 4, queue5, 0);
AudioConnection          patchCord6(tdm1, 5, queue6, 0);
AudioConnection          patchCord7(tdm1, 6, queue7, 0);
AudioConnection          patchCord8(tdm1, 7, queue8, 0);
// GUItool: end automatically generated code

// GUItool: end automatically generated code

// 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
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used

// Use these for the SD+Wiz820 or other adaptors
//#define SDCARD_CS_PIN    4
//#define SDCARD_MOSI_PIN  11
//#define SDCARD_SCK_PIN   13

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

unsigned int tsamplemillis = 10000;

String typeofsound;

int16_t* buffer1;
int16_t* buffer2;
int16_t* buffer3;
int16_t* buffer4;
int16_t* buffer5;
int16_t* buffer6;
int16_t* buffer7;
int16_t* buffer8;

// The file where data is recorded
File frec;

void setup() {

  Serial.begin(115200);
  // Audio connections require memory, and the record queue
  // uses this memory to buffer incoming audio.
  AudioMemory(512);

  // 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);
    }
  }
  while (!Serial);
  Serial.println("Welcome to the 4-channel TDM recording test bench");
}

void loop() {

  if (choice == 0) {
    Serial.println("\nEnter new filename for sound archive: ");
    while (!Serial.available());
    typeofsound = Serial.readString();
    sample_number = 0;
    record(typeofsound, sample_number);
  } else if (choice == 1) {
    sample_number++;
    record(typeofsound, sample_number);
  } else {
    //Do nothing
  }

  Serial.print("\nEnter 1 to take another sample in this archive or 0 to enter a new file archive: ");
  while (!Serial.available());
  choice = Serial.readString().toInt();
  Serial.println(choice);
}

void record(String type, int number)
{
  Serial.println("Recording " + type + String(number) + "...");
  String sname = type + number + ".RAW";
  String path = type + "/" + type + number + ".RAW";
  startRecording(sname, path, type);
  continueRecording();
  stopRecording();
}

void startRecording(String sname, String path, String type)
{
  int str_len = path.length() + 1;
  char charpath[str_len];
  path.toCharArray(charpath, str_len);

  if (SD.exists(charpath)) {
    // 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(charpath);
  }

  str_len = type.length() + 1;
  char chartype[str_len];
  type.toCharArray(chartype, str_len);

  if (!SD.exists(chartype)) {
    SD.mkdir(chartype);
  }

  frec = SD.open(charpath, FILE_WRITE);
  if (frec) {
    Serial.println("File Open");
  }
}

void continueRecording() {
  int data = 0, num = 0;
  elapsedMillis recordingTime = 0;
  queue1.begin();
  queue2.begin();
  queue3.begin();
  queue4.begin();
  queue5.begin();
  queue6.begin();
  queue7.begin();
  queue8.begin();
  mode = 1;
  while (recordingTime < tsamplemillis)
  {
    data = queue1.available();
    if (data > 0)
    {
      buffer1 = queue1.readBuffer();      //read all queue buffers in sets of 128 16bit num
      buffer2 = queue2.readBuffer();
      buffer3 = queue3.readBuffer();
      buffer4 = queue4.readBuffer();
      buffer5 = queue5.readBuffer();
      buffer6 = queue6.readBuffer();
      buffer7 = queue7.readBuffer();
      buffer8 = queue8.readBuffer();
      queue1.freeBuffer();                //free queue buffers to allow system to re issue storage
      queue2.freeBuffer();
      queue3.freeBuffer();
      queue4.freeBuffer();
      queue5.freeBuffer();
      queue6.freeBuffer();
      queue7.freeBuffer();
      queue8.freeBuffer();
      if (data > 48)        //test if queue buffers are getting too full, the serial write will probably cause a back log if it does happen.
      {
        Serial.write('.');    //dots in the serial monitor mean that the system isnt processing data fast enough
      }
      for (int i = 0; i < 128; i ++)                        //write data to sd card in 24bit signed pcm format (i think) (audacity seems to accept it)
      { //frames are built of 2 16 bit numbers where only 24 bits are useful, so only 3 bytes are saved to save space. Frames are little endian
        frec.write(highByte(buffer2[i])); // LSB            //<---------------------sample 1---------------------><---------------------sample n--------------------->
        frec.write(lowByte(buffer1[i])); // Middle Byte     //<----ch1----><----ch2----><----ch3----><----ch4----><----ch1----><----ch2----><----ch3----><----ch4---->
        frec.write(highByte(buffer1[i])); // MSB            //<LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB>
        frec.write(highByte(buffer4[i])); // LSB
        frec.write(lowByte(buffer3[i])); // Middle Byte
        frec.write(highByte(buffer3[i])); // MSB
        frec.write(highByte(buffer6[i])); // LSB
        frec.write(lowByte(buffer5[i])); // Middle Byte
        frec.write(highByte(buffer5[i])); // MSB
        frec.write(highByte(buffer8[i])); // LSB
        frec.write(lowByte(buffer7[i])); // Middle Byte
        frec.write(highByte(buffer7[i])); // MSB
        num++;
      }
    }
  }
  queue1.end();     //stop the background sampling
  queue2.end();
  queue3.end();
  queue4.end();
  queue5.end();
  queue6.end();
  queue7.end();
  queue8.end();
  Serial.print("num of samples written per channel:");
  Serial.println(num);
}


void stopRecording() {
  Serial.println("Finished recording.");
  queue1.end();
  queue2.end();
  queue3.end();
  queue4.end();
  queue5.end();
  queue6.end();
  queue7.end();
  queue8.end();
  queue1.clear();
  queue2.clear();
  queue3.clear();
  queue4.clear();
  queue5.clear();
  queue6.clear();
  queue7.clear();;
  queue8.clear();
  frec.close();
  mode = 0;
}

And recorded 99968 4-channel samples in 10 seconds (i can cope with being 32 off for now)

The result when imported into audacity using 24bit signed pcm, 4 channel, Fs=10000. The result of a recorded 300Hz sine wave looked like this:
View attachment 14406
(amplitudes are very small, due to having to play sound with pc speakers quietly as its late)

Apologies if any of the things stated aren't true, attempting to self teach myself in the early hours. Feel free to correct me or suggest improvements.

After only having the Teensy for 2 days now, I am already very impressed. Thanks for a great product and the forum!


I have bought a Teensy 3.6, and connect the Teensy 3.6 with the ICS52000 microphone array compile and upload the exact code to teensy 3.6.
Every things seems to be fine, but just no data is stored on the SD card.
IMG_20210630_210727_1.jpg

I do not know why? Am I using the right SD card? Can I pull the SD card out of teensy after it finish writing the file?

Can some one help me, we have spend more than two months on these, very fraustrated.
 
Try to upgrade to the new 1.54 Beta 12 (see "Announcements").

I have done the update,
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#define SDCARD_CS_PIN    BUILTIN_SDCARD
/////////////////////////////////////////////////////////////////////////////////
int a=0;

unsigned int tsamplemillis = 60000;

String typeofsound;

int16_t* buffer1;
int16_t* buffer2;

File frec;

////////////////////////////////////////////////////////////////////////////////

AudioInputTDM            tdm1;   
        
AudioRecordQueue         queue1;       
AudioRecordQueue         queue2;  
     
AudioConnection          patchCord1(tdm1, 0, queue1, 0);
AudioConnection          patchCord2(tdm1, 1, queue2, 0);

////////////////////////////////////////////////////////////////////////////////

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

  // Initialize the SD card

  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);
    }
  }
  while (!Serial);
  Serial.println("Welcome to the 4-channel TDM recording test bench");
  
  delay(1000); // for warm up the microphone 
}

void loop() {
    if(a<1)
    {
    record();
    continueRecording();
    stopRecording();
    a = 1;
    }
}

void record()
{
  
  frec = SD.open("test_9.raw", FILE_WRITE);
  if (frec) {
    Serial.println("File Open");
  }
}

void continueRecording() {
  int data = 0, num = 0;
  elapsedMillis recordingTime = 0;
  queue1.begin();
  queue2.begin();
  
  while (recordingTime < tsamplemillis)
  {
    data = queue1.available();
    if (data > 0)
    {
      buffer1 = queue1.readBuffer();     
      buffer2 = queue2.readBuffer();
      
      queue1.freeBuffer();                
      queue2.freeBuffer();
     
      for (int i = 0; i < 128; i ++)                       
      { 
        frec.write(highByte(buffer2[i])); // Middle Byte 
        frec.write(lowByte(buffer1[i])); // Middle Byte     
        frec.write(highByte(buffer1[i])); // MSB           
        num++;
      }
    }
  }
  queue1.end();     //stop the background sampling
  queue2.end();
  Serial.print("num of samples written per channel:");
  Serial.println(num);
}

void stopRecording() {
  Serial.println("Finished recording.");
  queue1.end();
  queue2.end();
  queue1.clear();
  queue2.clear();

  frec.close();
}

I have saved some data on the SD card.
I played a loud sine wave close to the microphone array,
THe recording does not show a sine wave form but a very strange wave from
untitled.png


I do not konw why?
 
Status
Not open for further replies.
Back
Top