PDM Microphone guidance/examples? Is PDM+I2S Possible?

Status
Not open for further replies.

dzalf

Member
Hello again guys

As I mentioned on a previous post, I am working on a project involving a PDM microphone pre-amplifier and a I2S UDA1334 decoder.

For now, I would like to test the PDM processing part using an Adafruit PDM Microphone.

My main issue right now is the lack of resources and examples of the usage of the library. I am using a Teensy 3.6 board.

I cannot figure out how to get the signal from the microphone. There is no clear indication if it can only be used with the Audio adaptor board or if it possible to use a standalone Teensy.

Here is what I've done so far:

1. Using the audio design tool GUI I created the following sketch:


GUIWiring_PDM-I2S.png

However, upon inspection of the wiring I believe that using PDM and I2S at the same time is NOT possible because they use the same pins (9 and 13 for PDM CLK/I2S BCLK and PDM DATA, respectively )

When loading the following code the Teensy 3.6 does NOT register any keys pressed and it seems to be stuck in the filtering process. Perhaps this is due to my lack of understanding of how to use the PDM libary. Any hints?

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

#define MUTE_SOUND HIGH
#define UNMUTE_SOUND LOW

// GUItool: begin automatically generated code
AudioInputPDM            pdm1;           //xy=242,248
AudioOutputI2S           i2s1;           //xy=559,257
AudioConnection          patchCord1(pdm1, 0, i2s1, 0);
AudioConnection          patchCord2(pdm1, 0, i2s1, 1);
// GUItool: end automatically generated code


// Bounce objects to read six pushbuttons (pins 0-5)
// I am only using two buttons as a test --> These will be used for increasing and decreasing a pointer
Bounce button0 = Bounce(30, 10);
Bounce button1 = Bounce(31, 10);  // 5 ms debounce time
Bounce muteButton = Bounce(32, 10);  // 5 ms debounce time

const int muteLED = 14;
const int mutePin = 25;

bool mutedFlag = false;


void setup() {

 
  Serial.begin(115200);
  
  Serial.println("********* Initialising Audio I2S Moudule: UDA1334 ******************");
  Serial.println(" Asisgning pins...");
  // Configure the pushbutton pins for pullups.
  // Each button should connect from the pin to GND.

  pinMode(30, INPUT_PULLUP);
  pinMode(31, INPUT_PULLUP);
  pinMode(32, INPUT_PULLUP);

  pinMode(mutePin, OUTPUT);
  pinMode(muteLED, OUTPUT);
  
  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  Serial.println(" Asisgning Audio Memory...");
  AudioMemory(50);

  digitalWrite(mutePin, UNMUTE_SOUND);

  pdm1.begin();

}
void loop() {
  
  pdm1.update();
  
  button0.update();
  button1.update();
  muteButton.update();

  if (button0.fallingEdge()) {

    Serial.println(" Button 0 pressed...");

  }

  if (button1.fallingEdge()) {

    Serial.println(" Button 1 pressed...");

  }

  if (muteButton.fallingEdge()) {

    if (mutedFlag == false) {

      digitalWriteFast(mutePin, MUTE_SOUND);
      Serial.println(" Muted Sound!");
      mutedFlag = true;
    } else {

      digitalWriteFast(mutePin, UNMUTE_SOUND);
      Serial.println(" Unmuted Sound!");
      mutedFlag = false;

    }
  }

}

I have the feeling that this usage is NOT allowed.

2. Then, I removed the I2S device trying to get something from the PDM microphone, however the library indicates that the AudioInputPDM object has no functions. Where can the data be read/accessed or viewed? What is Port Out 0 (according to the Audio Connections in the image attached below)?

PDMObject.png

As you might see I am completely lost :confused:

I would like to kindly ask you for further guidance on how to use this microphone as the information on PDM microphones+Teensy is scarce and there a re NO EXAMPLES available.

Is it possible to test the PDM microphone using Teensy 3.6 as an Audio Device in my PC? Any other alternatives/resources?


Thank you in advance

Edit: added hyperlink to the microphone preamplifier (FAN3852) that I plan to use later on


confined and confused dzalf
 
You should not be calling the PDM object's begin() an update() functions. That's handled by the audio library. Fix that and get rid of all your button handling code until you get the mic input to I2S output to work.

What is the I2S output connected to? Teensey Audio Shield?

What is 'mutePin' connected to?
 
here is a sketch i used with https://www.adafruit.com/product/3492 hooked to T3.2, using 3v3, GND, DAT to pin 13, CLK to 9, SEL not connected.
Code:
#include <Audio.h>
#define MICGAIN 100

// GUItool: begin automatically generated code
//AudioInputI2S i2s1;   // I2S mic
AudioInputPDM i2s1;   // PDM
AudioAnalyzePeak peak1;
AudioAnalyzeRMS rms1;
AudioConnection p1(i2s1, peak1);
AudioConnection p2(i2s1, rms1);
// GUItool: end automatically generated code


void setup() {
  AudioMemory(4);
  Serial.begin(9600);
  while(!Serial);
  delay(5000);
  Serial.println("RMS peak");
}

void loop() {
  Serial.print(MICGAIN * rms1.read()); Serial.print(" ");
  Serial.println(MICGAIN * peak1.read());
  delay(5);
}

you can use IDE's SerialPlotter to view the data
 
Last edited:
You should not be calling the PDM object's begin() an update() functions. That's handled by the audio library. Fix that and get rid of all your button handling code until you get the mic input to I2S output to work.

What is the I2S output connected to? Teensey Audio Shield?

What is 'mutePin' connected to?

Dear gfvalvo

Thank you for your kind response.

I've removed the functions. Still nothing.

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


// GUItool: begin automatically generated code
AudioInputPDM            pdm1;           //xy=182,235
AudioOutputI2S           i2s1;           //xy=465,236
AudioConnection          patchCord1(pdm1, 0, i2s1, 0);
AudioConnection          patchCord2(pdm1, 0, i2s1, 1);
// GUItool: end automatically generated code


void setup() {

  AudioMemory(20); // Is this correct?


}

void loop() {


}

The I2S output is connected to a UDA1334 decoder. I am not using the Teensy audio shield since originally I planned to use the UDA1334. As I mentioned, I believe that I cannot get an audio input using this I2S device due to the common pins being used by the two devices (Microphone and I2S decoder).

The mute pin was used in my previous circuit for testing the I2S device which works fine with the pinout I described there.

Any other advice? Should I be using different pins for each device? What alternative pins are compatible with PDM devices and/or I2S on Teensy 3.6?


As I understand, I should be getting audio signal out of my I2S without using any further instructions in my code. The library should be doing all the dirty work

Thank you once again

dzalf
 
I should work as-is with the BCLK supplied by the T3.6 (~2.8 MHz). The PDM object then filters the signal and provides the proper Audio Library sample stream to the following objects.

If it were my project, I'd divide and conqueror. Get the mic input going first as in @manitou's sketch.
 
Any other advice? Should I be using different pins for each device? What alternative pins are compatible with PDM devices and/or I2S on Teensy 3.6?

see post #3 to confirm PDM mic working.
 
Last edited:
Ah, looking at the code again (it's been quite a while since I wrote the PDM input code), it probably will not play nice with I2S output. To get the signal out, use Teensy 3.6's built in 12 bit DAC.
 
I should work as-is with the BCLK supplied by the T3.6 (~2.8 MHz). The PDM object then filters the signal and provides the proper Audio Library sample stream to the following objects.

If it were my project, I'd divide and conqueror. Get the mic input going first as in @manitou's sketch.

Dear gfvalvo

You are absolutely right and believe it or not this is exactly what I'm trying ;) Perhaps it matter of the resolution (pun intended) from my divide and conquer approach.

I tried to make some blocks work first but I've convinced myself that I really need to slow down and chop my project into smaller bits :)P ) for sure.

This is only the tip of the iceberg(-ish) project I am working on at the moment (from which I cannot disclose further details due to IP related issues).

I got it working now (I will share my results in my reply to manitou ;) )

Thank you very much for your help

dzalf
 
see post #3 to confirm PDM mic working.

Dear manitou

You are da man!

I got it working after using your guidance and Paul's advice (down here).

For now, the solution is to forget about my I2S board and simply use the internal DACs from the T3.6.

This is my code so far:


Code:
#include <Audio.h>
#define MICGAIN 50

// GUItool: begin automatically generated code
AudioInputPDM            mic;            
AudioOutputAnalogStereo  dacs1;         
AudioConnection          patchCord1(mic, 0, dacs1, 1);
AudioConnection          patchCord2(mic, 0, dacs1, 0);
AudioAnalyzePeak peak1;
AudioAnalyzeRMS rms1;
AudioConnection p1(mic, peak1);
AudioConnection p2(mic, rms1);
// GUItool: end automatically generated code

void setup() {
  AudioMemory(4);
  analogReference(INTERNAL);
  Serial.begin(9600);
}

void loop() {
  Serial.print(MICGAIN * rms1.read()); Serial.print(" ");
  Serial.println(MICGAIN * peak1.read());
  delay(5);
}


And the audio from the MIC is loud and clear (I still need to play around with some digital and analog filtering)

Here an image of the "I love Teensy" waveform:

IloveTeensyWaveform.png


Thank you VERY much for your help and be assured that I will come back very soon with more questions as these are my first steps with the Audio Design Tool

Stay safe and keep in the loop!

dzalf
 
Have you tested your UDA1334, like with the synth-only examples like Synth > Guitar?

Dear Paul

Yes, I successfully tested the UDA1334 using the SamplePlayer example and the following pinout:

Pin 9 (Teensy 3.6) to BCLK (UDA1334)
Pin 22 (Teensy 3.6) to DIN (UDA1334)
Pin 23 (Teensy 3.6) to WSEL (UDA1334)

I also assigned a push button to mute the device and that's when I ran into issues, as I described here. The solution to that "white noise" was to filter the Mute Pin from the UDA1334 with a 10nF capacitor to GND (weird because I had no issues with Teensy 4.0)

Following your advice from your second comment I used the DACs from T3.6 to test the Guitar synth and I can only say: Nice tune!

I am now going to design my own amplification solution based on an unused LM4861M that I just found in my parts bin ;)

As I mentioned to manitou, I need to learn a lot from the forums and keep practicing with the Audio GUI as I am an absolute n00b using it :(

Thank you for your kind help and more importantly for all the amazing effort and heart you've put on creating the Teensy ecosystem.

Hats off to you!

dzalf
 
Ah, looking at the code again (it's been quite a while since I wrote the PDM input code), it probably will not play nice with I2S output. To get the signal out, use Teensy 3.6's built in 12 bit DAC.

That's what I assumed.

I've abandoned the idea (for now) of using the UDA1334 and I will be using the DACs from T3.6.

This makes me wonder:

Is it possible to extract a digital audio stream in case I want to use an external DAC? In case I want moar resolution...:confused:

Cheers

dzalf
 
That's what I assumed.
Is it possible to extract a digital audio stream in case I want to use an external DAC? In case I want moar resolution...:confused:
A quick look at the code shows that the I2S RX hardware gets set up slightly differently by the AudioInputPDM class than by the AudioOutputI2S class (which configures both I2S TX and RX).

It seems that it would be a fairly straight-forward task to create your own set of PDM-In / I2S-Out Audio Library classes using AudioInputPDM, AudioOutputI2S, and AudioInputI2S as guides. But, you'd have to dig into the details to know for sure.
 
Last edited:
Status
Not open for further replies.
Back
Top