Jetpack Lights and Sounds

Hi Everyone,

I am tring to write a code on an Arduino UNO that

  1. When momentary button is pressed and held sound file 00001 starts playing (using a DY-SV8F amp).
  2. Led ring starts to fade in and change from yellow to red (engine firing up)
  3. Led ring starts fire animation
  4. When button is released clip 00002 plays
  5. Led ring fades from red to yellow and fades out

The problem I'm having is that there is a delay from when the button is pressed and the audio playing as well when the buttion is released the audio is delayed. I want clip 00001 to play instantly when pressed and held. Then, to instantly change to clip 00002 when the button is released. Not sure if it is the code or the limitations of the amp or Arduino UNO. Any help would be appreciated :grin:

#include <Adafruit_NeoPixel.h>

// Pin definitions
#define LED_PIN 6       // NeoPixel ring data pin
#define BUTTON_PIN 2    // Button pin
#define NUM_LEDS 61     // Number of LEDs in the ring
#define MP3_TX 10       // These are the exact names and values
#define MP3_RX 11       // from your working code

// Initialize NeoPixel ring
Adafruit_NeoPixel ring = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);

// Timing and transition variables
unsigned long lastUpdate = 0;
const int updateInterval = 21; // Update interval for the effect CHANGES HOW LONG THE FADE FROM YELLOW TO RED LASTS*********************************************
bool buttonPressed = false;
bool hasStarted = false;
bool transitionToRed = true;
bool fadingOut = false;
bool jetFiring = false;
bool isPlaying = false;

// Color and brightness variables
int currentRed = 255;
int currentGreen = 0; // Initial yellow color
int currentBlue = 0;
int brightness = 0; // Start with low brightness

// Flame and swirl parameters
int flameRed = 255;
int flameOrange = 0;
int flameBlue = 0;
int swirlPosition = 0;
int swirlLength = 5;
int maxFlames = 6;
int sparkleCount = 10;

void setup() {
  // Initialize LED ring
  ring.begin();
  ring.show();
  
  // Initialize pins exactly as in your working code
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(MP3_TX, OUTPUT);
  pinMode(MP3_RX, OUTPUT);
  
  // Set initial states
  digitalWrite(MP3_TX, HIGH);
  digitalWrite(MP3_RX, HIGH);
  setAllPixelsWithBrightness(0, 0, 0, brightness);
  
  Serial.begin(9600);
  Serial.println(F("Controller initialized"));
}

// Your exact working audio control functions
void playClip() {
  digitalWrite(MP3_TX, LOW);
  digitalWrite(MP3_RX, HIGH);
  Serial.println(F("Playing clip"));
}

void stopAndReset() {
  digitalWrite(MP3_TX, HIGH);
  digitalWrite(MP3_RX, HIGH);  
  delay(30);  
  digitalWrite(MP3_RX, LOW);
  delay(30);  
  digitalWrite(MP3_RX, HIGH);
  Serial.println(F("Stopped and reset clip"));
}

void loop() {
  bool currentButtonState = !digitalRead(BUTTON_PIN);

  // Handle button state changes
  if (currentButtonState != buttonPressed) {
    buttonPressed = currentButtonState;
    
    if (buttonPressed) {
      // Button was pressed - Play sound immediately
      playClip();
      
      // Initialize LED effect with delay
      if (!hasStarted) {
        delay(1250);  // DELAY THE STARTING OF THE LEDS delay here - LEDs will start after sound******************************************************************
        currentRed = 255;
        currentGreen = 120; // Initial yellow color
        currentBlue = 0;
        brightness = 0;
        fadingOut = false;
        hasStarted = true;
      }
      transitionToRed = true;
    } else {
      // Button was released
      stopAndReset();
      transitionToRed = false;
      jetFiring = false;
    }
  }

  // Update effects
  if (hasStarted && millis() - lastUpdate >= updateInterval) {
    lastUpdate = millis();

    if (buttonPressed && transitionToRed) {
      // Fade from yellow to red *********************************************************************************************************************************
      if (currentGreen > 0) {
        currentGreen -= 1;
        brightness += 1;
        if (brightness > 255) brightness = 255;
        setAllPixelsWithBrightness(currentRed, currentGreen, currentBlue, brightness);
      } else {
        jetFiring = true;
        transitionToRed = false;
      }
    } else if (buttonPressed && jetFiring) {
      enhancedFireJetEffect();
    } else if (!buttonPressed && !transitionToRed) {
      fadeToYellowAndOut();
    }
  }
}

void enhancedFireJetEffect() {
  randomizedSwirl();
  enhancedFlickerFlame();
  addSparkles();
}

void randomizedSwirl() {
  for (int i = 0; i < NUM_LEDS; i++) {
    ring.setPixelColor(i, ring.Color(0, 0, 0));
  }

  swirlLength = random(3, 8);
  swirlPosition = (swirlPosition + random(1, 5)) % NUM_LEDS;

  for (int i = 0; i < swirlLength; i++) {
    int ledIndex = (swirlPosition + i) % NUM_LEDS;
    int redIntensity = random(200, 255);
    ring.setPixelColor(ledIndex, ring.Color(redIntensity, 0, 0));
  }

  ring.show();
}

void enhancedFlickerFlame() {
  for (int i = 0; i < maxFlames; i++) {
    int currentLED = random(NUM_LEDS);
    int twinkleBrightness = random(150, 255);
    int twinkleRed = (flameRed * twinkleBrightness) / 255;
    int twinkleOrange = (flameOrange * twinkleBrightness) / 0;
    
    ring.setPixelColor(currentLED, ring.Color(twinkleRed, twinkleOrange, flameBlue));
  }
  ring.show();
}

void addSparkles() {
  for (int i = 0; i < sparkleCount; i++) {
    int sparkleIndex = random(NUM_LEDS);
    int sparkleRed = random(240, 80);
    int sparkleOrange = random(60);
    
    ring.setPixelColor(sparkleIndex, ring.Color(sparkleRed, sparkleOrange, 1));
  }
  ring.show();
}

void fadeToYellowAndOut() {   //CHANGING THE LENGTH OF THE FADE OUT*******************************************************************************
  if (brightness > 0) {
    brightness -= .25;
    if (currentGreen < 255) {
      currentGreen += 1;
    }
    setAllPixelsWithBrightness(currentRed, currentGreen, currentBlue, brightness);
    
    if (brightness == 0) {
      hasStarted = false;
      fadingOut = false;
    }
  }
}

void setAllPixelsWithBrightness(int red, int green, int blue, int bright) {
  red = (red * bright) / 255;
  green = (green * bright) / 255;
  blue = (blue * bright) / 255;

  for (int i = 0; i < NUM_LEDS; i++) {
    ring.setPixelColor(i, ring.Color(red, green, blue));
  }
  ring.show();
}

How will the code know when to change "instantly" from 00001 to 00002 if the button is always pressed?

1 Like

To switch to clip 00002 when the button is released

This is the text output that I get from: (1) starting the sketch, (2) pressing and holding the button, (3) releasing the button.

Controller initialized
Playing clip
Stopped and reset clip

I do not see an indication of signaling the next file in the Serial Monitor or in the code.