Go Down

Topic: Unable to get ArduinoSound library to work with Nano 33 BLE boards (Read 189 times) previous topic - next topic

John_Conrad

For the MP34DT05 PDM microphone we have an inbuilt example sketch - PDMSerialPlotter for the Nano 33 BLE boards (which works fine). Here is the reference to the PDM library.

There the reference quotes -
Quote
The library takes care of the audio that will be accessible also through the ArduinoSound Library.
However that isn't quite clear.
Does this mean that we can use the PDM class/library with the ArduinoSound classes like FFTAnalyzer class. Example:
Code: [Select]
if (!fftAnalyzer.input(AudioInI2S))
 Here the `AudioInI2S` class is used by FFTAnalyzer class.

Cause I tried that (replacing `AudioInI2S` with `PDM`) and it failed i.e didn't compile for the nano board.

I believe this is an architectural issue as when I change the board to SAMD21 based boards, the issue comes with PDM Library and when the boards are kept as the new Nano 33 BLE boards then the issue comes with ArduinoSound library.

EDIT: Moreover with the Board selected as Arduino Nano 33 BLE, the `ArduinoSound` library is listed under **INCOMPATIBLE**.

What I wanted to do was to run FFT on the PDM input of the microphone to determine what frequencies are present.

Any hint would be much appreciated.

John_Conrad

Does anyone know where I can get the source files of the PDM Library ? I tried looking in my installation but there is no file by the name of PDM.h. Neither did I find it anywhere on the internet.
How is it getting imported ?

johnandrewjustice

I need to do the exact same thing.  To no avail I have tried mulitiple libraries and edits.  The new BLE sense board is a bit too light on examples for the mic.  Anyone have any knowledge as to the structure of the PDM data and maybe a method to do FFT "manually"?

johnandrewjustice

I think I got something close to working.  Note I put some limits on it because of the range I was working on.  You can just change the lines in the loop for the "println" of "oldx"

/*

   Example of use of the FFT libray
        Copyright (C) 2014 Enrique Condes

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

/*
  In this example, the Arduino simulates the sampling of a sinusoidal 1000 Hz
  signal with an amplitude of 100, sampled at 5000 Hz. Samples are stored
  inside the vReal array. The samples are windowed according to Hamming
  function. The FFT is computed using the windowed samples. Then the magnitudes
  of each of the frequencies that compose the signal are calculated. Finally,
  the frequency with the highest peak is obtained, being that the main frequency
  present in the signal. This frequency is printed, along with the magnitude of
  the peak.
*/

#include "arduinoFFT.h"

// start edit
#include <PDM.h>

// buffer to read samples into, each sample is 16-bits
short sampleBuffer[256];
short oldx;

// number of samples read
volatile int samplesRead;
//stop edit

arduinoFFT FFT = arduinoFFT(); /* Create FFT object */
/*
These values can be changed in order to evaluate the functions
*/
const uint16_t samples = 256; //This value MUST ALWAYS be a power of 2
const double signalFrequency = 1000;
const double samplingFrequency = 16000;
const uint8_t amplitude = 100;
/*
These are the input and output vectors
Input vectors receive computed results from FFT
*/
double vReal[samples];
double vImag[samples];

#define SCL_INDEX 0x00
#define SCL_TIME 0x01
#define SCL_FREQUENCY 0x02
#define SCL_PLOT 0x03

void setup()
{
  Serial.begin(115200);
  Serial.println("Ready");
 
// start edit
    PDM.onReceive(onPDMdata);

  // optionally set the gain, defaults to 20
  // PDM.setGain(30);

  // initialize PDM with:
  // - one channel (mono mode)
  // - a 16 kHz sample rate(1600hz edit)
  if (!PDM.begin(1, 16000)) {
    Serial.println("Failed to start PDM!");
    while (1);
  }
// end edit
  delay(9000);
}

void loop()
{
  /* Build raw data */
  double cycles = (((samples-1) * signalFrequency) / samplingFrequency); //Number of signal cycles that the sampling will read
  for (uint16_t i = 0; i < samples; i++)
  {
    vReal = int8_t((amplitude * (sin((i * (twoPi * cycles)) / samples))) / 2.0);/* Build data with positive and negative values*/
    //vReal = uint8_t((amplitude * (sin((i * (twoPi * cycles)) / samples) + 1.0)) / 2.0);/* Build data displaced on the Y axis to include only positive values*/
    vImag = 0.0; //Imaginary part must be zeroed in case of looping to avoid wrong calculations and overflows
  }
  /* Print the results of the simulated sampling according to time */
 // Serial.println("Data:");
//  PrintVector(vReal, samples, SCL_TIME);
  FFT.Windowing(vReal, samples, FFT_WIN_TYP_HAMMING, FFT_FORWARD);   /* Weigh data */
 // Serial.println("Weighed data:");
//  PrintVector(vReal, samples, SCL_TIME);
  FFT.Compute(vReal, vImag, samples, FFT_FORWARD); /* Compute FFT */
 // Serial.println("Computed Real values:");
 // PrintVector(vReal, samples, SCL_INDEX);
//  Serial.println("Computed Imaginary values:");
//  PrintVector(vImag, samples, SCL_INDEX);
  FFT.ComplexToMagnitude(vReal, vImag, samples); /* Compute magnitudes */
//  Serial.println("Computed magnitudes:");
//  PrintVector(vReal, (samples >> 1), SCL_FREQUENCY);
  double x;
  double v;
  FFT.MajorPeak(vReal, samples, samplingFrequency, &x, &v);
  if (v>5000){
 if(x<2000)
   oldx=x;
  }
  Serial.println(oldx);
 
 //Serial.print(", ");
//Serial.println(v);
  //while(1); /* Run Once */
   //delay(1000); /* Repeat after delay */
}

void PrintVector(double *vData, uint16_t bufferSize, uint8_t scaleType)
{
  for (uint16_t i = 0; i < bufferSize; i++)
  {
    double abscissa;
    /* Print abscissa value */
    switch (scaleType)
    {
      case SCL_INDEX:
        abscissa = (i * 1.0);
   break;
      case SCL_TIME:
        abscissa = ((i * 1.0) / samplingFrequency);
   break;
      case SCL_FREQUENCY:
        abscissa = ((i * 1.0 * samplingFrequency) / samples);
   break;
    }
    Serial.print(abscissa, 6);
    if(scaleType==SCL_FREQUENCY)
      Serial.print("Hz");
    Serial.print(" ");
    Serial.println(vData, 4);
  }
  Serial.println();
}

//start edit
void onPDMdata() {
  // query the number of bytes available
  int bytesAvailable =  PDM.available();

  // read into the sample buffer
  PDM.read(sampleBuffer, bytesAvailable);

    for (int i = 0; i < samplesRead; i++) {
         
vReal=sampleBuffer;
    }

  // 16-bit, 2 bytes per sample
  samplesRead = bytesAvailable / 2;
}
//end edit

Go Up