How to get the Microphone (PDM) working with WS2812FX

The PDM example alone runs. Also the WS2812FX effects are working well on the RP2040 Connect. But as soon as I want to use both together (for sound/noise based effects) the board does nothing or freezes to a point where i have to flash it with "Blink.ino.elf.uf2".

Is it not possible to read the Microphone data without killing the WS2812 functionality?

#include <Arduino.h>
#include <WS2812FX.h>
#include <PDM.h>

#define LED_COUNT 8
#define LED_PIN 13

WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);



bool LED_SWITCH = false;
// default number of output channels
static const char channels = 1;
// default PCM output frequency
static const int frequency = 20000;
// Buffer to read samples into, each sample is 16-bits
short sampleBuffer[512];
// Number of audio samples read
volatile int samplesRead;


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

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

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

void audioservice(){

 if (samplesRead) {

    // Print samples to the serial monitor or plotter
    for (int i = 0; i < samplesRead; i++) {
      if (channels == 2) {
        Serial.print("L:");
        Serial.print(sampleBuffer[i]);
        Serial.print(" R:");
        i++;
      }
      Serial.println(sampleBuffer[i]);

      if (sampleBuffer[i] > 10000 || sampleBuffer[i] <= -10000) {
        LED_SWITCH = !LED_SWITCH;
        if (LED_SWITCH) {
          Serial.println();
          Serial.println("ON!");
          Serial.println();
          delay(1000);
        }
        else {
          Serial.println();
          Serial.println("OFF!");
          Serial.println();
          delay(1000);
        }
      }
    }

    // Clear the read count
    samplesRead = 0;
  }
}


void setup() {


  Serial.begin(9600);
  while (!Serial);
  sleep_ms(1000);
  Serial.println("Setup");

  // PDM.onReceive(onPDMdata);
  // // Configure the data receive callback
  // if (!PDM.begin(channels, frequency)) {
  //   Serial.println("Failed to start PDM!"); 
  // }

  ws2812fx.init();
  ws2812fx.setBrightness(100);
  ws2812fx.setSpeed(2000);
  ws2812fx.setMode(FX_MODE_RAINBOW_CYCLE);
  ws2812fx.start();

}

unsigned long lastTime = 0;
unsigned long timer = 0;

void loop() {
  ws2812fx.service();
  //audioservice();
}




The board is always doing exactly what you told it to do. I can see two "delay(1000);" where you are telling the board to "do nothing"... you also have a "for" loop, disallowing any activity outside that loop. Did you write this, or ChatGPT?

Look for "arduino blink without delay" and "arduino several things happening" Programming Electronics Academy did these well.

its from the official PDM example. if you clap your hands the board pauses for 1 second. otherwise it prints out the audio wave. (if the WS2812FX is not enabled)

I am guessing... WSFX did not expect (or program for) any other devices needing service (blocking code). Try writing your own wsfx? It wont take long to learn.

I tried to read the data during the loop(), instead of using the callback function.

// query the number of bytes available
int bytesAvailable = PDM.available();
// read into the sample buffer
PDM.read(sampleBuffer, bytesAvailable);

but ws2812fx still did not work.

With the help of this thread I got it working:

platformio.ini:

[env:nanorp2040Pico]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = nanorp2040connect
framework = arduino
board_build.core = earlephilhower
lib_deps = kitesurfer1404/WS2812FX@^1.4.2

Just put the Audio stuff on one core and the LED stuff on the other:

void setup1(){

  while (!Serial);
  sleep_ms(1000);
  Serial.println("Setup1");

  ws2812fx.init();
  ws2812fx.setBrightness(100);
  ws2812fx.setSpeed(2000);
  ws2812fx.setMode(FX_MODE_RAINBOW_CYCLE);
  ws2812fx.start();
}

void loop1(){
  //sleep_ms(1000);
  //Serial.println("loop1");
  ws2812fx.service();
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.