Delay on Audio Output when using acceleration sensor on ESP32

Hello there, I am using a MPU6050 combined with an ESP32 to measure acceleration. At a curtain acceleration a sound is sent from an microSD-Breakout Board (Adafruit 254) over the ESP32 to an amplifier (MAX98357A) and frome there to a 8 Ohm speaker (LSF-15M/S).

The problem: after swinging the MPU6050 there is a delay (about a second) to the speaker so the sound appears to late for being "in the swing".

Is there a way to get rid of that delay?

Here is my current Code:

// Include required libraries
#include<Wire.h>
#include "FS.h"
#include <SD.h>
#include <SPI.h>
#include "Arduino.h"
#include "Audio.h"

#define SDA 33
#define SCL 32

// microSD Card Reader connections
#define SD_MISO     2
#define SD_MOSI     15
#define SD_SCLK     14
#define SD_CS       13
SPIClass sdSPI(VSPI);
long long timer;
const int MPU_addr=0x68;  // I2C address of the MPU-6050
int16_t GyX,GyY,GyZ;
 
// I2S Connections
#define I2S_DOUT      22
#define I2S_BCLK      26
#define I2S_LRC       25
 
 // Create Audio object
Audio audio;
 
void setup() {

  // Monitoring
  Wire.begin(SDA, SCL);
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(115200);
 
  // SD-Karten Lesen
  sdSPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS);
  if(!SD.begin(SD_CS, sdSPI)) {
    Serial.println("SD-Karte kann nicht geöfffnet werden.");
    return;
  }
  uint8_t cardType = SD.cardType();
  if(cardType == CARD_NONE) {
    Serial.println("Keine SD-Karte vorhanden.");
    return;
  }
  if (!SD.begin(SD_CS)) {
    Serial.println("Fehler beim Lesen der SD-Karte");
    return;    
  }
    
  //Audio-Setup
  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
  audio.setVolume(30);
    
}

void loop()
{   
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,6,true);  // request a total of 14 registers
  GyX=Wire.read()<<8|Wire.read();  
  GyY=Wire.read()<<8|Wire.read();  
  GyZ=Wire.read()<<8|Wire.read();  


  if (abs(GyX/1325) > 12 || abs(GyY/1325) > 12) {
    audio.connecttoFS(SD,"/Swing01.mp3");
    timer = millis();
    while (abs(millis()-timer)<=1000){
      audio.loop();    
    }
    audio.stopSong(); 
  }

  else {
    audio.connecttoFS(SD,"/coolsaber.mp3");
    audio.loop();  

  }   
}  

timer = millis();
while (abs(millis()-timer)<=1000){
  audio.loop();    
}

Could this one second while loop be the reason ?

I am not familiar with the library but which command actually starts the file playing and what does audio.loop() do ?

How large is each file Swing01.mp3 and coolsaber.mp3?

I'd use SPI for the MPU over I2C.

If freeRTOS was used, which is included with an ESP32, I'd see about assigning each sound to a task and have the task triggered.

Why the 1000mS delay?

Thank you for your reply. The library I am using ( ESP32-audioI2S) needs to loop the "audio.loop" function as long as the sound plays. So this part of the code let the sound be played for 1 second. That is not the problem :slight_smile:

Hey thank you for the reply.
The files have a size between 4.5 and 70KB.
I am not that deep into protocols. Using SPI for the Breakout Board and I2C for the MPU. Not sure how to use SPI for the MPU.
Never heard of freeRTOS, when this can help to solve the problem I can try to get into it.
The delay I made is used to keep the audio.loop going, it has nothinng to do with the speaker delay.

It's true that i2c is slower than SPI, but that would make maybe 1 millisecond difference. It can't explain the 1 second delay described. It's a distraction, and so is using FreeRTOS to try to fix the problem.

I suggest adding lots of Serial.println("doing XYZ"); to the sketch to understand what's going on during the unexpected delay.

Thank you. I tried to add some Serial.println() like this:

    timer = millis();
    Serial.println("Timer started");
    while (abs(millis()-timer)<=1000){
        
      audio.loop();    
    }
    audio.stopSong();
      Serial.println("Song stopped"); 
  }

The important outputs:

20:34:28.035  -> Timer started  //first print
20:34:28.355  -> Timer started  //approximately the time when I start hearing a sound 
20:34:29.118  -> Song stopped //time when the sound stopped

As it seems there are two different delays:

  1. Delay between start of the swing and starting the timer (can not measure it but it is there)
  2. Delay between timer start and sound file play ( ~300ms)

If thats right, there are two delays to remove/reduce....

More importantly, why are we seeing "Timer started" twice in succession without "Song stopped" between them? How can each "Timer started" not have an accompanying "Song stopped", given the structure of the code?

I can think of a way that can happen...

Put Serial.println("start/end of setup/loop") at the first and last lines of setup() and loop().

I moved the MPU two times while recording.

20:59:29.814 -> end of setup
20:59:29.814 -> start of loop
20:59:30.311 -> end of loop
20:59:30.311 -> start of loop
20:59:30.825 -> end of loop
20:59:30.825 -> start of loop
20:59:31.324 -> Timer started
20:59:32.350 -> Song stopped
20:59:32.350 -> end of loop
20:59:32.350 -> start of loop
20:59:32.754 -> end of loop
20:59:32.754 -> start of loop
20:59:33.128 -> Timer started
20:59:34.153 -> Song stopped
20:59:34.153 -> end of loop
20:59:34.153 -> start of loop

What is your idea, what does it tell you?

Now, every "Timer started" is followed by "Song stopped". We are not seeing the same situation as before.

My idea was that the Arduino was resetting unexpectedly. If that was true we would have seen something like:
"Timer started"
"start of setup"
"end of setup"
"start of loop"
"Timer started"

1 Like

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