Adding a Button trigger for my Music Box Routine

So I have compiled 3 different routines into one code, but as I near the end of my project, I wanted to start fine-tuning the code by adding in a button trigger. The idea is to press the button to start the routine. Here is where I am stuck, I have added enough code that I'm not sure where my brackets should go and what is the "setup" and what is the "loop" in all of this.

#include <DFRobotDFPlayerMini.h>
#include <Stepper.h>
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#define BUTTON_PIN 8
#define BOX_PIN 9


//Box Routine Variable//
int boxRoutine;


//////////Create the Player object///////////////////////////////////////////////////
DFRobotDFPlayerMini player;

// Use pins 2 and 3 to communicate with DFPlayer Mini
static const uint8_t PIN_MP3_TX = 2; // Connects to module's RX 
static const uint8_t PIN_MP3_RX = 3; // Connects to module's TX 
SoftwareSerial softwareSerial(PIN_MP3_RX, PIN_MP3_TX);
//////////////////////////////////////////////////////////////////////////////////


//////////Create Light Variables///////////////////////////////////////////////////
int led = 9;           // the PWM pin the LED is attached to
int brightness = 3;    // how bright the LED is
int fadeAmount = 2;    // how many points to fade the LED by
//////////////////////////////////////////////////////////////////////////////////


//////////Stepper Motor Variables///////////////////////////////////////////////////
// change this to the number of steps on your motor
#define STEPS 200

// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it's
// attached to
Stepper stepper(STEPS, 4, 5, 6, 7);
//////////////////////////////////////////////////////////////////////////////////


void setup() {

//Button Trigger//
pinMode (BOX_PIN, OUTPUT);
pinMode (BUTTON_PIN, INPUT);


//Music Functions///////////////////////////////////////////
  // Init USB serial port for debugging
  Serial.begin(9600);
  // Init serial port for DFPlayer Mini
  softwareSerial.begin(9600);

  // Start communication with DFPlayer Mini
  if (player.begin(softwareSerial)) {
   Serial.println("OK");

     // Set volume to maximum (0 to 30).
    player.volume(23);
    // Play the first MP3 file on the SD card
    player.play(1);
  } else {
    Serial.println("Connecting to DFPlayer Mini failed!");
  }
/////////////////////////////////////////


  //Fairy Lights/////////////////////////////////////////
pinMode(led, OUTPUT); //declare pin 9 to be an output
//////////////////////////////////////////////////////////////////


//Stepper Motor/////////////////////////////////////////
  Serial.begin(9600);
  Serial.println("Stepper test!");
  // set the speed of the motor to 30 RPMs
  stepper.setSpeed(30);
///////////////////////////////////////////////////////////////


}


void loop() {

  if (digitalRead(BUTTON_PIN) == HIGH) {
    digitalWrite(BOX_PIN, HIGH);
  }
  else {
    digitalWrite(BOX_PIN, LOW);
  }
}
   // set the brightness of pin 9:
  analogWrite(led, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 1 || brightness >= 240) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(45);

//Stepper Motor Loop//
    Serial.println("Forward");
  stepper.step(STEPS);
  Serial.println("Backward");
  stepper.step(-STEPS);
}

I created a "int boxRoutine" variable in the off chance that I would require it store the other routines for the button. Not sure if that was necessary - hence why it was never used.

Next, according to the article I was reading, the loop designated the loop as:

  if (digitalRead(BUTTON_PIN) == HIGH) {
    digitalWrite(BOX_PIN, HIGH);
  }
  else {
    digitalWrite(BOX_PIN, LOW);
  }
}

inside the loop(), but this was using an LED as an example and not a series of functions, so i was confused as to how to translate multiple processes into one. Hopefully this makes sense - furthermore, I hope my code makes sense.

By itself, the code is doing what it's supposed to do, what I would like it do with a button is wait for the button to be pressed to begin the entire routine at once and then stop once the song is finished

Thanks for your format tip, that worked great! I'll remember to always format before copying code.

So after adding all of the pertinent code into what I want to run when the button is pressed, I'm getting a bizarre response where the whole routine will run for a few seconds and then restart. The button works to turn off the system when I hold it down but nothing else. If I change the state to "LOW", then it will not do anything and still do the same (turn off the system when pressed).

#include <DFRobotDFPlayerMini.h>
#include <Stepper.h>
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#define BUTTON_PIN 8
#define BOX_PIN 9



//////////Create the Player object//////////
DFRobotDFPlayerMini player;

// Use pins 2 and 3 to communicate with DFPlayer Mini
static const uint8_t PIN_MP3_TX = 2; // Connects to module's RX
static const uint8_t PIN_MP3_RX = 3; // Connects to module's TX
SoftwareSerial softwareSerial(PIN_MP3_RX, PIN_MP3_TX);


//////////Create Light Variables//////////
int led = 10;           // the PWM pin the LED is attached to
int brightness = 3;    // how bright the LED is
int fadeAmount = 2;    // how many points to fade the LED by

//////////Stepper Motor Variables//////////
// change this to the number of steps on your motor
#define STEPS 360

// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it's
// attached to
Stepper stepper(STEPS, 4, 5, 6, 7);




void setup() {

  //Button Trigger//
  pinMode (BOX_PIN, OUTPUT);
  pinMode (BUTTON_PIN, INPUT);


  //Music Functions//
  // Init USB serial port for debugging
  Serial.begin(9600);
  // Init serial port for DFPlayer Mini
  softwareSerial.begin(9600);

  //Fairy Lights
  pinMode(led, OUTPUT); //declare pin 9 to be an output
  /////////////////////////

  //Stepper Motor
  Serial.begin(9600);
  Serial.println("Stepper test!");
  // set the speed of the motor to 30 RPMs
  stepper.setSpeed(30);

}




void loop() {

  if (digitalRead(BUTTON_PIN) == HIGH) {

    // Start communication with DFPlayer Mini
    if (player.begin(softwareSerial)) {
      Serial.println("OK");

      // Set volume to maximum (0 to 30).
      player.volume(23);
      // Play the first MP3 file on the SD card
      player.play(1);
    } else {
      Serial.println("Connecting to DFPlayer Mini failed!");
    }
    /////////////////////////////////////////

    // set the brightness of pin 9:
    analogWrite(led, brightness);

    // change the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // reverse the direction of the fading at the ends of the fade:
    if (brightness <= 1 || brightness >= 240) {
      fadeAmount = -fadeAmount;
    }
    // wait for 30 milliseconds to see the dimming effect
    delay(45);

    //Stepper Motor Loop//
    Serial.println("Forward");
    stepper.step(STEPS);
  }

}

I stripped out all except the music related code and the following does run fine on my UNO. So you may find it helpful to study it, particularly the comments. Note that, like @Delta_G, I've used a LOW-going button. Changed a few pins to suit my current breadboard. The sketch plays a single file in setup() and then each time you press the button it plays the next.

// Thu 13 Jul 2023; removed all but music stuff
// Heavily commented

#include <DFRobotDFPlayerMini.h>
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#define BUTTON_PIN 7 // mine wired to 0V, so goes Low when pressed
// not High like original to pin 8

bool buttonState = 1; // Normally high, gpes low when pressed
bool previousButtonState = 1; // Because we will test when CHANGED

//////////Create the Player object///////////////////////////////////////////////////
DFRobotDFPlayerMini player;

// Use pins 2 and 3 to communicate with DFPlayer Mini
// My edit: Use pins 8 and 9 to communicate
static const uint8_t PIN_MP3_TX = 9; // UNO Tx connects module's RX
static const uint8_t PIN_MP3_RX = 8; // UNO Rx connects module's TX
SoftwareSerial softwareSerial(PIN_MP3_RX, PIN_MP3_TX);
//////////////////////////////////////////////////////////////////////////////////


void setup()
{
  //Button Trigger//
  pinMode (BUTTON_PIN, INPUT_PULLUP); // Avoids need for resistor

  // Music Functions///////////////////////////////////////////
  // Init USB serial port for debugging
  Serial.begin(115200); // Was 11500, typo?
  delay(200); // my addition
  Serial.println();

  // Init serial port for DFPlayer Mini
  softwareSerial.begin(9600);
  delay(1000);
  // Start communication with DFPlayer Mini
  if (!player.begin(softwareSerial, false))
  {
    Serial.println("Connecting to DFPlayer Mini failed!");
    while (true);
  }
  //  else
  //  {
  Serial.println("OK");
  //  }
  // The following NOT inside the previous if()
  // Set volume to maximum (0 to 30).
  player.volume(23);
  delay(500); // Usually fails unless delay over about 100 ms
  // Play the first MP3 file on the SD card
  player.play(1); // i.e. usually file 0001.mp3
}

void loop()
{
  // What exactly wanted here from the music player?
  // Only use of it in original was to play a single trackin setup()
  // - nothing here in loop(). Do you just want to play next track?
  // The following should do that.

  buttonState = digitalRead(BUTTON_PIN);


  // If button has just gone low (i.e. been pressed) play next track
  if (buttonState == LOW && previousButtonState == HIGH)
  {
    player.next(); // File 0002.mp3 in this example
    delay(100);
  }
}

Welp. I sure didnt....

Let's start there. What is the difference in wiring? I was just going along with this wiring:

50-50 chance of getting it right, due to the arrangement of button pins(can be rotated 90 degrees, but depends on what button you've got, exactly). Move the resistor so it connects directly to the processor pin, not to a third pin of the button.

That will take pin 2 high when the button is pressed.

You don’t need a resistor if you use INPUT_PULLUP as in the sketch I posted earlier.

It’s a personal choice. But I think it’s logical and intuitive that when a button is pressed down the voltage it delivers should be low.

Actually, if my goal is to only play a song when the button is pressed - does that mean i should keep my code exclusively in the Setup()? I dont actually want anything anything to happen without the button as a trigger and that is 1x per button press.

So… you press the button, a tune plays and then… you go back to waiting on the button. Sounds like looping code to me.

You could use your own loop statement and leave it in setup(), or leave the looping to loop() and place the "button causes play" code there, where it will get repeated automatically.

The latter would follow the Arduino model of "code here runs once" / "code here runs over and over" division of labor which is the setup()/loop() model.

LOL. It seems more logical that a pressed button is true, it is pressed, you should truly do something which would correspond to a button pressed delivering HIGH.

But we do it the other (your) way for reasons.

Fortunately there are many ways to compensate for however the buttons are wired and whatever they report for being pressed and not.

a7

*But we do it the other (your) way for reasons

I mentioned one in my post:

No, keep it in loop(). That allows you to trigger it manually at any time. And maybe other conditions will arise from the other parts of your circuit that you later decide should trigger the playing of a track, Or you might want it to play at certain intervals, etc,

Also as you saw in my sketch, it’s not to play when the button is pressed. Unless you really do want it to play only while you are pressing the button down?

LOL, just leaving the tech aside for a moment.

true yes high something positive green daytime on alive good can

flase no low nothing negative red night off dead bad cannot


We are, before all, hunans.

a7

oh, no. I just want the routine to play once when the button is pressed and then wait for the trigger (button) to be pressed again to run through the routine again.

So here is the current state of the project, to test out the button, I tried @Terrypin edits and removed all the other functions and just focused on playing the track when the pressing the button.

// Thu 17 Jul 2023; removed all but music stuff


#include <DFRobotDFPlayerMini.h>
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#define BUTTON_PIN 8 // mine wired to 0V, so goes Low when pressed


bool buttonState = 1; // Normally high, gpes low when pressed
bool previousButtonState = 1; // Because we will test when CHANGED

//////////Create the Player object///////////////////////////////////////////////////
DFRobotDFPlayerMini player;

static const uint8_t PIN_MP3_TX = 2; // UNO Tx connects module's RX
static const uint8_t PIN_MP3_RX = 3; // UNO Rx connects module's TX
SoftwareSerial softwareSerial(PIN_MP3_RX, PIN_MP3_TX);
//////////////////////////////////////////////////////////////////////////////////


void setup()
{
  //Button Trigger//
  pinMode (BUTTON_PIN, INPUT_PULLUP); // Avoids need for resistor

  // Music Functions///////////////////////////////////////////
  // Init USB serial port for debugging
  Serial.begin(115200); // Was 11500, typo?
  delay(200); // my addition
  Serial.println();

  // Init serial port for DFPlayer Mini
  softwareSerial.begin(9600);
  delay(1000);
  // Start communication with DFPlayer Mini
  if (!player.begin(softwareSerial, false))
  {
    Serial.println("Connecting to DFPlayer Mini failed!");
    while (true);
  }
  //  else
  //  {
  Serial.println("OK");
  //  }
  // The following NOT inside the previous if()
  // Set volume to maximum (0 to 30).
  player.volume(23);
  delay(500); // Usually fails unless delay over about 100 ms
  // Play the first MP3 file on the SD card
  player.play(1); // i.e. usually file 0001.mp3
}

void loop()
{

  buttonState = digitalRead(BUTTON_PIN);

  // If button has just gone low (i.e. been pressed) play next track
  if (buttonState == LOW && previousButtonState == HIGH)
  {
    player.next(); // File 0002.mp3 in this example
    delay(100);
  }
}

Its probably a lot easier to show you the results:

Routine in Action

at 0:13 I unplug the button and that is when the music starts playing. Otherwise the button is keeping the mp3 from doing anything. But I can see power going to the mp3 board and even the pop to the speakers. Not sure if my wiring needs to be changed or if I still need to revise the code further

Haha, right.

(I say, "Yes", but I may mean, "No")

I guess that's Lennon/McCartney's version of active low, or the possibility that anything might mean the exact opposite to what we think.

a7

Thanks! This is getting clearer and clearer. I did some more tweaks,

// Thu 17 Jul 2023; removed delays, removed "play next" function in loop for "player.play(1)" designed to play only 1 file


#include <DFRobotDFPlayerMini.h>
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#define BUTTON_PIN 8 // mine wired to 0V, so goes Low when pressed


bool buttonState = 1; // Normally high, goes low when pressed
bool previousButtonState = 1; // Because we will test when CHANGED

//////////Create the Player object///////////////////////////////////////////////////
DFRobotDFPlayerMini player;

static const uint8_t PIN_MP3_TX = 2; // UNO Tx connects module's RX
static const uint8_t PIN_MP3_RX = 3; // UNO Rx connects module's TX
SoftwareSerial softwareSerial(PIN_MP3_RX, PIN_MP3_TX);
//////////////////////////////////////////////////////////////////////////////////


void setup()
{
  //Button Trigger//
  pinMode (BUTTON_PIN, INPUT_PULLUP); // Avoids need for resistor

  // Music Functions///////////////////////////////////////////
  // Init USB serial port for debugging
  Serial.begin(115200); // Was 11500, typo?
  Serial.println();
  // Init serial port for DFPlayer Mini
  softwareSerial.begin(9600);
  delay(1000);


}

void loop()
{

  buttonState = digitalRead(BUTTON_PIN);

  // If button has just gone low (i.e. been pressed) play next track
  if (buttonState == LOW && previousButtonState == HIGH)
  {

    // Start communication with DFPlayer Mini
    if (!player.begin(softwareSerial, false))
    {
      Serial.println("Connecting to DFPlayer Mini failed!");
      while (true);
    }
    //  else
    //  {
    Serial.println("OK");
    //  }
    // The following NOT inside the previous if()
    // Set volume to maximum (0 to 30).
    player.volume(23);
    // Play the first MP3 file on the SD card
    player.play(1); // i.e. usually file 0001.mp3

    previousButtonState = buttonState;
  }
}

What im experiencing now is the music is playing automatically, without waiting for the button. Could this be a button state that is hardcoded? Oof. I feel like I'm so close now.

I am getting success when I press the button, the music starts.

See below:
Updated Progress

damn. no dice. still plays immediately once it gets power.

I did however, switch the push button to a rocker switch and that solved the issue - obviously there are different mechanics with different switches. But I can accommodate.

I'm guessing I could use a reset in that rocker switch.

All that stuff should be in setup(). Why have you moved it to loop()?

Honestly, i was trying anything to get the music to stop playing as soon as i turned on the board. But I see what you're saying now, I moved it back into the setup and it works.

I reintroduced the fairy lights into the code, when i hit the trigger, the lights and the music will turn on. but the fade routine will not start. Not sure what is keeping that from updating

// Tue 18 Jul 2023; moved music functions back into Setup(), added Fairy Lights functions into button state


#include <DFRobotDFPlayerMini.h>
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#define BUTTON_PIN 8 // mine wired to 0V, so goes Low when pressed


bool buttonState = 1; // Normally high, goes low when pressed
bool previousButtonState = 1; // Because we will test when CHANGED

///////////////Create the Player object/////////////////////////////
DFRobotDFPlayerMini player;

static const uint8_t PIN_MP3_TX = 2; // UNO Tx connects module's RX
static const uint8_t PIN_MP3_RX = 3; // UNO Rx connects module's TX
SoftwareSerial softwareSerial(PIN_MP3_RX, PIN_MP3_TX);

//////////////////////////////////////////////////////////////////


/////////////////Create Fairy Light Variables////////////////////

int led = 10;           // the PWM pin the LED is attached to
int brightness = 3;    // how bright the LED is
int fadeAmount = 2;    // how many points to fade the LED by

////////////////////////////////////////////////////////////////


void setup()
{

  ///////////////////////Button Trigger//////////////////////////

  pinMode (BUTTON_PIN, INPUT_PULLUP); // Avoids need for resistor

  ///////////////////////////////////////////////////////////////


  ///////////////////////Music Functions/////////////////////////

  // Init USB serial port for debugging
  Serial.begin(115200); // Was 11500, typo?
  Serial.println();
  // Init serial port for DFPlayer Mini
  softwareSerial.begin(9600);
  delay(1000);
  // Start communication with DFPlayer Mini
  if (!player.begin(softwareSerial, false))
  {
    Serial.println("Connecting to DFPlayer Mini failed!");
    while (true);
  }
  else
  {
    Serial.println("OK");
  }
  ///////////// End Music Functions/////////////////////////////


  ////////////////////Fairy Lights//////////////////////////////

  pinMode(led, OUTPUT); //declare pin 10 to be an output

  //////////////////End Fairy Light/////////////////////////////

}


void loop()
{

  buttonState = digitalRead(BUTTON_PIN);


  if (buttonState == LOW && previousButtonState == HIGH)
  {

    /////////////////////Play Song///////////////////////
    // The following NOT inside the previous if()
    // Set volume to maximum (0 to 30).
    player.volume(23);
    // Play the first MP3 file on the SD card
    player.play(1); // i.e. usually file 0001.mp3
    ////////////////////////////////////////////////////

    /////////////////Fairy Light Fading Routine////////////////////////
    // set the brightness of pin 10:
    analogWrite(led, brightness);

    // change the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // reverse the direction of the fading at the ends of the fade:
    if (brightness <= 1 || brightness >= 240) {
      fadeAmount = -fadeAmount;
    }
    // wait for 30 milliseconds to see the dimming effect
    delay(45);
    /////////////////////////////////////////////////////////////////

    previousButtonState = buttonState;

  }
}

You're saying music was playing when the board was off?

Sorry, no. The music would just play as soon as I turned the board on, regardless of whether I had pressed the switch or not.

But that was an issue with, as everyone has been telling me before, the placement of my functions. So I moved them into the correct place and I have more control of my code with my button. But I still am missing full control of my routine. Argh. So close.

// Wed 19 Jul 2023; added Stepper Motor Functions, Fairy Lights Control


#include <DFRobotDFPlayerMini.h>
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#include <Stepper.h>
#define STEPS 202
#define BUTTON_PIN 8 // mine wired to 0V, so goes Low when pressed


bool buttonState = 1; // Normally high, goes low when pressed
bool previousButtonState = 1; // Because we will test when CHANGED

///////////////Create the Player object/////////////////////////////
DFRobotDFPlayerMini player;

static const uint8_t PIN_MP3_TX = 2; // UNO Tx connects module's RX
static const uint8_t PIN_MP3_RX = 3; // UNO Rx connects module's TX
SoftwareSerial softwareSerial(PIN_MP3_RX, PIN_MP3_TX);

//////////////////////////////////////////////////////////////////


/////////////////Create Fairy Light Variables////////////////////

int led = 10;           // the PWM pin the LED is attached to
int brightness = 3;    // how bright the LED is
int fadeAmount = 2;    // how many points to fade the LED by

////////////////////////////////////////////////////////////////



///////////////////////////Create Stepper Motor Variables////////////////////////////////////

// initialize the stepper library on pins 4 through 7:
Stepper stepper(STEPS, 4, 5, 6, 7);

////////////////////////////////////////////////////////////////////////////////////////////


void setup()
{

  ///////////////////////Button Trigger//////////////////////////

  pinMode (BUTTON_PIN, INPUT_PULLUP); // Avoids need for resistor

  ///////////////////////////////////////////////////////////////


  ///////////////////////Music Functions/////////////////////////

  // Init USB serial port for debugging
  Serial.begin(115200);
  Serial.println();
  // Init serial port for DFPlayer Mini
  softwareSerial.begin(9600);
  delay(1000);
  // Start communication with DFPlayer Mini
  if (!player.begin(softwareSerial, false))
  {
    Serial.println("Connecting to DFPlayer Mini failed!");
    while (true);
  }
  else
  {
    Serial.println("OK");
  }
  ///////////// End Music Functions/////////////////////////////


  ////////////////////Fairy Lights//////////////////////////////

  pinMode(led, OUTPUT); //declare pin 10 to be an output

  //////////////////End Fairy Light/////////////////////////////


  /////////////////////Stepper Motor Functions///////////////////

  Serial.begin(9600);
  // set the speed of the motor in RPMs:
  stepper.setSpeed(70);

  /////////////////////End Stepper Motor Functions////////////////

}


void loop()
{

  buttonState = digitalRead(BUTTON_PIN);


  if (buttonState == LOW && previousButtonState == HIGH)
  {

    /////////////////////Play Song///////////////////////
    // The following NOT inside the previous if()
    // Set volume to maximum (0 to 30).
    player.volume(23);
    // Play the first MP3 file on the SD card
    player.play(1); // i.e. usually file 0001.mp3
    ////////////////////////////////////////////////////

    /////////////////Fairy Light Fading Routine////////////////////////
    // set the brightness of pin 10:
    analogWrite(led, brightness);

    // change the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // reverse the direction of the fading at the ends of the fade:
    if (brightness <= 1 || brightness >= 240) {
      fadeAmount = -fadeAmount;
    }
    // wait for 30 milliseconds to see the dimming effect
    delay(45);
    /////////////////////////////////////////////////////////////////

    /////////////////////Stepper Motor Functions///////////////////

    Serial.println("Forward");
    stepper.step(STEPS);

    /////////////////////End Stepper Motor Functions////////////////


    previousButtonState = buttonState;
  }
}

I added back in the other two routines, a Fairy Lights that fade and a Stepper motor that rotates. Now my issue is that neither of them operate as they should once I put their functions inside the buttonState when I call it in the loop(). Outside of it, they function as intended, inside - the lights just turn on and the stepper motor just turns for a second.

See below:

Im wondering if this is an issue that i will have to fix with wiring or if i still find a solution with code/button states?