xiao-esp32C3 with MAX98357 / source of noise

Hi,
I’m working on a “walkie talkie” type project and am getting a lot of noise on top of delivered audio outputing through the MAX98357 amplifier. Tried my output setup on a simple example sketch outputing a sine wave - getting the same noise on top of the sine wave. Sound is clear for the first second upon receiving power than a repeating noise pattern is added… Looking for feedback on possible causes.
Setup and noise example youtube link.
Code:

/**
 * @file streams-generator-i2s.ino
 * @author Phil Schatzmann
 * @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/examples-stream/streams-generator-i2s/README.md 
 * @copyright GPLv3
 */
 
#include "AudioTools.h"

AudioInfo info(44100, 2, 16);
SineWaveGenerator<int16_t> sineWave(4000);                 // subclass of SoundGenerator with max amplitude of 8000
GeneratedSoundStream<int16_t> sound(sineWave);             // Stream generated from sine wave
I2SStream out; 
StreamCopy copier(out, sound);                             // copies sound into i2s

// Arduino Setup
void setup(void) {  
  // Open Serial 
  Serial.begin(115200);
  while(!Serial);
  //AudioLogger::instance().begin(Serial, AudioLogger::Info);

  // start I2S
  Serial.println("starting I2S...");
  auto config = out.defaultConfig(TX_MODE);
  config.copyFrom(info);
  config.pin_bck = 8;
  config.pin_ws = 9;
  config.pin_data = 20;
  out.begin(config);

  // Setup sine wave
  sineWave.begin(info, N_B4);
  Serial.println("started...");
}

// Arduino loop - copy sound to out 
void loop() {
  copier.copy();
}

Hi there,
From the looks and sound of it, I would suspect you need some filtering on the power supply.
Try a cap across the power input and check your ground connections. Those max boards are very sensitive to bad power supply decoupling. AFAIK.
If you attenuate the input signal and there is no change then look to the power supply.
HTH
GL :slight_smile: PJ
:v:

Take look at some of the other threads here on that MAX chip setup. others have had similar issues initially also. :+1:

interesting project keep us up to date

It appears that the amplifier is powered from the 3V3 pin of the XIAO .
If the amplifier can tolerate 5V, what happens if it is fed from the 5V pin?

AudioInfo info(16000, 1, 16);
If this line is changed, the noise disappears.

Thanks guys!
Turns out amp is actually MAX98357A and already has components for power supply filtration.
AudioInfo info(16000, 1, 16); - this line did it, noise is gone. However this just proved that my hardware isn’t faulty (having noise on my actual project I went for that sine example to test HW, noise on it made me think my HW is bad…).

To the problem with the actual project (btw, I’m no programmer, this a project I took up as a learning process): the setup so far: https://postimg.cc/4HJQdnzz

Button on remote (on the far right) activates microphone on mid. setup, than left setup should be outputting received audio BUT it has plenty of noise… Again YT link for noise sample.
Code on output setup:

// PUSH TO TALK - RECEIVER
 
#include <esp_now.h>
#include <WiFi.h>
#include <driver/i2s.h>

#define I2S_IN_SCK 8
#define I2S_IN_WS 9
#define I2S_OUT_SD 20
#define I2S_PORT I2S_NUM_0
#define bufferLen 250

int availableSamples = 0;
int sampleBufferIndex = 0;
int playSampleIndex = 0;

bool i2sStarted = false; //ar rodyti gaunamu reiksmiu info

// Received packet counter and timestamp for OnDataRecv triggers
int recvCount = 0;
unsigned long lastRecvTime = 0;
const unsigned long resetInterval = 2000; // 2 seconds


// kokio dydzio ateinancio audio buferis - dauginam issiuntimo dydi is X (kelis kartus didesnis nei issiuntimo)
const int sampleBufferLen = 5000;
uint8_t *sampleBuffer = (uint8_t *)malloc(sampleBufferLen);


void OnDataRecv(const esp_now_recv_info_t *recv_info, const uint8_t *incomingData, int incDataLen) {
  recvCount++;
  lastRecvTime = millis();
  saveSamples(incomingData, incDataLen);
}
//--------------------------------------------------------------------


//--------------------------------------------------------------------
void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA); //--> Set device as a Wi-Fi Station

  //----------------------------------------Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  } else {
    Serial.println("LISTENING FOR INCOMING TRANSMISIONS");
  }
  //----------------------------------------
  esp_now_register_recv_cb(OnDataRecv); //--> Register for a callback function that will be called when data is received

  delay(1000);
  i2s_install();
  i2s_setpin();
  i2s_start(I2S_PORT);
  i2sStarted = true;
  delay(500);
}
//--------------------------------------------------------------------

void i2s_install(){
  const i2s_config_t i2s_config = {
    .mode = i2s_mode_t(I2S_MODE_TX),
    .sample_rate = 8000,
    .bits_per_sample = i2s_bits_per_sample_t(16),
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),
    .intr_alloc_flags = 0, 
    .dma_buf_count = 4,
    .dma_buf_len = bufferLen*2,
    .use_apll = false
  };

  i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
}

void i2s_setpin(){
  const i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_IN_SCK,
    .ws_io_num = I2S_IN_WS,
    .data_out_num = I2S_OUT_SD,
  };

  i2s_set_pin(I2S_PORT, &pin_config);
}

//--------------------------------------------------------------------
void loop() {
  unsigned long currentMillis = millis();

  // Reset packet counter if OnDataRecv triggered for "resetInterval" (2) seconds
  if (currentMillis - lastRecvTime >= resetInterval && availableSamples < bufferLen) {
    recvCount = 0;
  }

  // delay in audio packets received (7) before output start
  if (recvCount >= 7) {
    if (availableSamples >= bufferLen) {
      if (!i2sStarted) {
        i2sStarted = true;
        i2s_start(I2S_PORT);
        //delay(500);
        Serial.println("RECEIVING AUDIO - OUTPUT STARTED.");
      }
      writeOutput(sampleBuffer, sampleBufferLen);
          } else {
      i2s_stop(I2S_PORT);
      i2sStarted = false;
      Serial.println("---- END OF OUTPUT ----");
      recvCount = 0;
      availableSamples = 0;
    }
  }
}

void saveSamples(const uint8_t *sample, int sampleLen) {
  int sampleIndex = 0;
  while (sampleIndex < sampleLen) {
    sampleBuffer[sampleBufferIndex] = sample[sampleIndex];
    sampleIndex++;
    sampleBufferIndex = (sampleBufferIndex + 1) % sampleBufferLen; // % reiskia liekana --> jei sampleBufferLen yra simtas, o index tampa simtu jis nunulinamas, kitu atveju tik +1
  }
  availableSamples += sampleLen;
}


void writeOutput(const uint8_t *sample, int sampleLen) {
  int writeBufferLen;
  int samples_writen;
  availableSamples > bufferLen ? writeBufferLen = bufferLen : writeBufferLen = availableSamples;

  uint16_t wBuffer[writeBufferLen];
  esp_err_t result;
  size_t bytesOut = 0;
  if (writeBufferLen > 0) {
    for (int i=0; i< writeBufferLen; i++) {
      wBuffer[i] = sample[playSampleIndex] << 8;
      playSampleIndex = (playSampleIndex + 1) % sampleBufferLen;
    }
    result = i2s_write(I2S_PORT, &wBuffer, sizeof(uint16_t) * writeBufferLen, &bytesOut, portMAX_DELAY);
    samples_writen = bytesOut/2;
    availableSamples -= samples_writen;
  }
}

Any obvious code bloopers?

Hi there,
Great Job , bro… thanks for staying with it and contributing to the pile. We all appreciate it.
GL :slight_smile: PJ
:v:

AudioInfo info(44100, 2, 16);

On C6 and S3 it works fine without noise.
What happens if you increase the buffer size?

1 Like