Audio Recording / Logging to SD card --> microSoundRecorder

After Paul integrated SdFat-V2 I updated code to include directly TD SdFat.h (no -beta anymore)
No need to download Bill's beta version.
Best to remove SdFat-beta from local Arduino Libs and only use TD version
 
Tim, Walter, thanks for the explanations, now I understand! I can confirm also, that the firmware compiles WITHOUT downloading the SdFat lib by Bill Greiman, thanks for your hints!

I have one further question:

* I built 12 new recorders, smaller and with a slightly modified layout, but still using the original T3.6 software and concept
* I purchased 64Gbyte microSD cards
* observation: when the software tries to activate the SD card after waking up to begin a new time window (sd.begin()), sometimes the Sd card refuses to work (this makes the software think there is no SD card inserted and it enters the never ending while loop with blinking pin 13 LED) --> it seems to me, the newly purchased SD cards are different in behaviour and need a higher power supply or a longer time before they respond . . . this is confirmed if I use older 64GByte SD cards, which work without problems [they are of exactly the same brand and type!]

The corresponding code lines are in audio_logger_if.h

Code:
  if (!sd.begin(SD_CONFIG))
  {
//    sd.errorHalt("sd.begin failed");
    while(1)
    {
      // blink code suggests insertion of an SD card
            pinMode(13,OUTPUT);
            digitalWriteFast(13,HIGH);
            delay(200);
            digitalWriteFast(13,LOW);
            delay(200);
    }
  }
I would like to cure this by letting the software make several trials in activating the SD card, but still indicate problems with not inserted SD cards by blinking with pin 13 LED.

However, as I understand it, this statement makes it impossible to use pin 13 for I2S afterwards.

Code:
pinMode(13,OUTPUT);

Can I revert this, so the code checks for SD card, blinks one second, and then checks again? Something like this:

Code:
 while (!sd.begin(SD_CONFIG))
  {
      // blink code suggests insertion of an SD card
            pinMode(13,OUTPUT);
            digitalWriteFast(13,HIGH);
            delay(200);
            digitalWriteFast(13,LOW);
            delay(200);
            pinMode(13, ???); // here, I do not know how I can re-assign pin 13 for correct I2S use

    }
 
one more thought:

maybe the reason for the sporadic failure of SD card begin statement is the usage of the new/faster SD lib?

Because the old SD cards were tested with the old software and the new SD cards with the new software!?
 
Testing with the following modification at the moment (this is expected to do a restart of the Teensy every time the SD card cannot be initiated):

Code:
#define CPU_RESTART_ADDR (uint32_t *)0xE000ED0C
#define CPU_RESTART_VAL 0x5FA0004
#define CPU_RESTART (*CPU_RESTART_ADDR = CPU_RESTART_VAL);
//____________________________ FS Interface implementation______________________
void c_uSD::init()
{
  delay(200);
  if (!sd.begin(SD_CONFIG))
  {
      delay(1000);
      CPU_RESTART;
  }

  // Set Time callback
  FsDateTime::callback = dateTime;
  //
  nbuf=0;
  state=0;
}

I will report back whether this cures the problem and allows to reliably start the acquisition, even when the SD card is sometimes not detected in the first attempt.
 
@DD4WH,
If you wanted to use I2S and also use LED for messaging, You should use
Code:
          CORE_PIN13_CONFIG = PORT_PCR_MUX(4);  // PTC5,  I2S0_RXD0
after you are done with LEDing and move on to I2S
 
perfect, thanks, exactly the info I was looking for! will try and report back and eventually place a PR after testing!
 
First test result:
* 7 recorders running for 4 days now
* 1-12h and 13-24h
* 15sec record, 15sec record, 30sec sleep
* all equipped with the suspect 64GB microSD cards, which caused problems because they were not recognized after deep sleep and recorder went into infinite blink while loop

Modification of the code in audio_logger_if.h (recorder blinks to indicate a missing SD card, but then trys again to mount the SD card, success of the mounting is saved into a file on the SD card)
Code:
void c_uSD::init()
{
  delay(200);
  int SD_success = 0;
  char text[32];
  char SD_filename[24];

  while (!sd.begin(SD_CONFIG))
  {
     // configure pin 13 for LED      
     pinMode(13,OUTPUT);
     for(int idx = 0; idx < 8; idx++)
     {
         digitalWriteFast(13,HIGH);
         delay(200);
         digitalWriteFast(13,LOW);
         delay(200);
     }
     delay(5000);
     SD_success++;
     // reconfigure pin 13 for I2S
     CORE_PIN13_CONFIG = PORT_PCR_MUX(4);  // PTC5,  I2S0_RXD0
  }

  sprintf(SD_filename, "SD_s_%s.txt", acqParameters.name);
  file.open(SD_filename, O_CREAT|O_WRITE|O_APPEND);
    sprintf(text, "%04d_%02d_%02d,", year(), month(), day());  file.write((char*)text, strlen(text));
    sprintf(text, "%02d_%02d_%02d,", hour(), minute(), second());   file.write((char*)text, strlen(text));
    sprintf(text, "%10d\r\n", SD_success);          file.write((char*)text, strlen(text));
  file.close(); 
  
  // Set Time callback
  FsDateTime::callback = dateTime;
  //
  nbuf=0;
  state=0;
}

Test is still running, but after four days, at least one recorder had 3 occasions of unsuccessful mounting of the SD card after waking up from deep sleep and in the very next trial, the SD card was mounted successfully and the recordings continued as expected [until the next deep sleep 11 hours later]!

Will continue the test until the recorders run out of battery and report the whole result.
 
Last edited:
Hi All, it appears I am late to the party... I am attempting to use the Teensy 3.6 to do time scheduled recording and write to micro SD. I am very new to teensy/arduino, so if anyone could point me in the right direction and help me understand exactly which code I need to use it would be much appreciated.
Thanks,
Ethan
 
Hi All, it appears I am late to the party... I am attempting to use the Teensy 3.6 to do time scheduled recording and write to micro SD. I am very new to teensy/arduino, so if anyone could point me in the right direction and help me understand exactly which code I need to use it would be much appreciated.
Thanks,
Ethan

Using microSoundRecorder in time scheduled recording is easy:
To start, please have a look into the wiki that is part of the repository.
there are two entries of concern "Recorder Menu" and "Time scheduled recording"
The first item explains how to enter menu mode and describes all menu options
the second item describes the parameters that are used for time scheduled recording.
 
Last edited:
Hi Walter,
I have ordered a Teensy 3.6 and a couple of microphones. I am trying to find any information on which pins need to be connected to the mic and I am confused on the statement of "connect pin 3 to GND" as there are several GND on teensy 3.6. Again, any help would be greatly appreciated.
Thanks
 
Hi Walter,
I have ordered a Teensy 3.6 and a couple of microphones. I am trying to find any information on which pins need to be connected to the mic and I am confused on the statement of "connect pin 3 to GND" as there are several GND on teensy 3.6. Again, any help would be greatly appreciated.
Thanks

All grounds are equal. So, any ground is OK to activate menu on startup.
Note, menu is only entered on startup (or after hibernating). A method to terminate recorder and entering menu by grounding pin3 must still be implemented, if needed.
 
Hi Walter, per the hardware setup section of the wiki, I have connected GND (teensy) to GND (mic), GND (teensy) to L/R (mic), and I have used AGND for the RC lowpass filter. However, I believe I need to connect pin 3 to GND to open the recorder menu, but I have used all of the GND connections on the teensy with the mentioned connections. This may be a silly question, but I am very lost.
Thanks,
Ethan
 
However, I believe I need to connect pin 3 to GND to open the recorder menu, but I have used all of the GND connections on the teensy with the mentioned connections.
Thanks,
Ethan
You can use always the same GND pin and any GND pin is OK. Note: AGND is different and best only to be used for Analog circuits (e.g. not for power filter).
 
Hi Walter,
I have completed all of the necessary connections and changed the power filter to a GND connection rather than AGND. I am now opening serial monitor, but when I type in 'a' to display all parameters, nothing is happening and the serial monitor remains blank as seen in the included screenshot. Pin 3 is connected to GND, so I know that isn't my issue.
Screen Shot 2021-07-20 at 12.42.38 PM.jpg
 
show please picture of your setup, config file (if modified) and all other changes you did to program (if any)
 
Code:
void setup() {
  // put your setup code here, to run once:
/* Sound Recorder for Teensy 3.6
 * Copyright (c) 2018, Walter Zimmer
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice, development funding notice, and this permission
 * notice shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

 /*********************** Begin possible User Modifications ********************************/
// possible modifications are marked with //<<<======>>>
//
//----------------------------------------------------------------------------------------
#define DO_DEBUG 1 // print debug info over usb-serial line  //<<<======>>>

#define F_SAMP 48000 // desired sampling frequency  //<<<======>>>
/*
 * NOTE: changing frequency impacts the macros 
 *      AudioProcessorUsage and AudioProcessorUsageMax
 * defined in stock AudioStream.h
 */

////////////////////////////////////////////////////////////
// ------------------------- Acquisition interface control ----------------------------
// possible ACQ interfaces
#define _ADC_0          0 // single ended ADC0
#define _ADC_D          1 // differential ADC0
#define _ADC_S          2 // stereo ADC0 and ADC1
#define _I2S            3 // I2S (16 bit stereo audio)
#define _I2S_32         4 // I2S (32 bit stereo audio), eg. two ICS43434 mics
#define _I2S_QUAD       5 // I2S (16 bit quad audio)
#define _I2S_32_MONO    6 // I2S (32 bit mono audio), eg. one ICS43434 mic
#define _I2S_TYMPAN     7 // I2S (16 bit tympan stereo audio audio) for use the tympan board
#define _I2S_TDM        8 // I2S (8 channel TDM) // only first 5 channels are used (modify myAcq.h if less or more channels)

#define ACQ   _I2S_32_MONO // selected acquisition interface  //<<<======>>>

// For ADC SE pins can be changed
#if ACQ == _ADC_0
  #define ADC_PIN A2 // can be changed  //<<<======>>>
  #define DIFF 0
#elif ACQ == _ADC_D
  #define ADC_PIN A10 //fixed analog pin
  #define DIFF 1
#elif ACQ == _ADC_S
  #define ADC_PIN1 A2 // can be changed //<<<======>>>
  #define ADC_PIN2 A3 // can be changed //<<<======>>>
  #define DIFF 0
#elif (ACQ == _I2S_32) || (ACQ == _I2S_32_MONO) || (ACQ == _I2S_TDM) 
  #define NSHIFT 12 // number of bits to shift data to the right before extracting 16 bits //<<<======>>>
#endif

#define MDEL -1     // maximal delay in buffer counts (128/fs each; for fs= 48 kHz: 128/48 = 2.5 ms each) //<<<======>>>
                    // MDEL == -1 connects ACQ interface directly to mux and queue
                    // MDEL >= 0 switches on event detector
                    // MDEL > 0 delays detector by MDEL buffers 
#define MDET (MDEL>=0)

#define GEN_WAV_FILE  // generate wave files, if undefined generate raw data (with 512 byte header) //<<<======>>>

}

void loop() {
  // put your main code here, to run repeatedly:

/****************************************************************************************/
// some structures to be used for controlling acquisition
// -----------------------scheduled acquisition------------------------------------------
typedef struct
{ uint32_t on;  // acquisition on time in seconds
  uint32_t ad;  // acquisition file size in seconds
  uint32_t ar;  // acquisition rate, i.e. every ar seconds (if < on then continuous acquisition)
  uint32_t T1,T2; // first acquisition window (from T1 to T2) in Hours of day
  uint32_t T3,T4; // second acquisition window (from T1 to T2) in Hours of day
  uint32_t rec;  // time when recording started
  char name[8];   // prefix for recorder file names
} ACQ_Parameters_s;

// T1 to T3 are increasing hours, T4 can be before or after midnight
// choose for continuous recording {0,12,12,24}
// if "ar" > "on" the do dutycycle, i.e.sleep between on and ar seconds
//
// Example
// ACQ_Parameters_s acqParameters = {120, 60, 180, 0, 12, 12, 24, 0, "WMXZ"};
//  acquire 2 files each 60 s long (totaling 120 s)
//  sleep for 60 s (to reach 180 s acquisition interval)
//  acquire whole day (from midnight to noon and noot to midnight)
//

ACQ_Parameters_s acqParameters = { 60, 10, 120, 0, 12, 12, 24, 0, "WMXZ"}; //<<<======>>>


//---------------------------------- snippet extraction module ---------------------------------------------
typedef struct
{  int32_t iproc;      // type of detection processor (0: high-pass-threshold; 1: Taeger-Kaiser-Operator)
   int32_t thresh;     // power SNR for snippet detection (-1: disable snippet extraction)
   int32_t win0;       // noise estimation window (in units of audio blocks)
   int32_t win1;       // detection watchdog window (in units of audio blocks typically 10x win0)
   int32_t extr;       // min extraction window
   int32_t inhib;      // guard window (inhibit follow-on secondary detections)
   int32_t nrep;       // noise only interval (nrep =0  indicates no noise archiving, TBD)
   int32_t ndel;       // pre trigger delay (in units of audio blocks)
} SNIP_Parameters_s; 
// Note: 375 blocks is 1s for 48 kHz sampling

#if MDEL<0
  // continuous acquisition; disable detector
  #define THR -1
#else
  #define THR 100 // detection threshold (on power: 100 == 20 dB) //<<<======>>>
#endif

SNIP_Parameters_s snipParameters = { 0, THR, 1000, 10000, 38, 375, 0, MDEL}; //<<<======>>>


//-------------------------- hibernate control---------------------------------------------------------------
// The following two lines control the maximal hibernate (sleep) duration
// this may be useful when using a powerbank, or other cases where frequent booting is desired
// is used in audio_hibernate.h
//#define SLEEP_SHORT             // comment when sleep duration is not limited   //<<<======>>>
#define ShortSleepDuration 60   // value in seconds     //<<<======>>>

//------------------------- Additional sensors ---------------------------------------------------------------
#define USE_ENVIRONMENTAL_SENSORS 0 // to use environmental sensors set to 1 otherwise set to 0  //<<<======>>>

//------------------------- special Hardware configuration ----------------------------------------------------
#if ACQ == _I2S_TYMPAN
  #undef USE_ENVIRONMENTAL_SENSORS
  #define USE_ENVIRONMENTAL_SENSORS 0 // for tympan switch off environmental sensors
  #define TYMPAN_REVISION         TYMPAN_REV_C         //TYMPAN_REV_C or TYMPAN_REV_D   //<<<======>>>
  #define TYMPAN_INPUT_DEVICE     TYMPAN_INPUT_ON_BOARD_MIC // use the on-board microphones   //<<<======>>>
                                  //TYMPAN_INPUT_JACK_AS_MIC // use the microphone jack - defaults to mic bias 2.5V
                                  //TYMPAN_INPUT_JACK_AS_LINEIN // use the microphone jack - defaults to mic bias OFF
  #define input_gain_dB   10.5f   //<<<======>>>
#endif

//
/*********************** End possible User Modifications ********************************/
}

And some images...
IMG_3922.jpgIMG_3926.jpg
 
Last edited:
Please edit you post and put your code into #code markdown, this way I cannot understand what you have done
only code that you modified
 
Yes that is better
Not sure what you have done and what you posted correspond to this.
splitting the config file and copying it to setup and loop is not the way this program can work.
maybe you got confused that microSoundRecorder.ino is empty. It has to be empty.

on HW, suggest to get you a breadboard and some jumper cables, and solder only when all is working.
for example, connection of pin3 to GND is only for rebooting into menu. otherwise it should not be grounded.
Also, with all wires having the same colour, it is difficult to check connection.
 
Ok, I see. I have now used the empty microSoundRecorder.ino file... now when I try to compile the sketch to teensy, I get the following errors...


/var/folders/x2/l1w9vpsn0_qbn7g0hvymh2zc0000gn/T/arduino_build_754050/core/core.a(main.cpp.o): In function `main':
/private/var/folders/x2/l1w9vpsn0_qbn7g0hvymh2zc0000gn/T/AppTranslocation/70477A6E-063C-44BD-8C4A-2142B3807D6F/d/Teensyduino.app/Contents/Java/hardware/teensy/avr/cores/teensy3/main.cpp:51: undefined reference to `setup'
/private/var/folders/x2/l1w9vpsn0_qbn7g0hvymh2zc0000gn/T/AppTranslocation/70477A6E-063C-44BD-8C4A-2142B3807D6F/d/Teensyduino.app/Contents/Java/hardware/teensy/avr/cores/teensy3/main.cpp:53: undefined reference to `loop'
collect2: error: ld returned 1 exit status
Error compiling for board Teensy 3.6.

Any thoughts on this?
 
Back
Top