Mp3 shield with a simple sketch, but, of course, issues

I am making a sort of electronic music box for a friend for Christmas, using a Sparkfun MP3 Shield and an uno.

Simple design, button attached to the side of the box, take the lid off and it plays a track. Except that it does not work. My circuit is fine, I have quadrupel checked that, just the button example except its attached to pin 12. Switch is high when the lid is on, low when its off. This is what I tried first:

#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h> 
#include <SFEMP3Shield.h>

SFEMP3Shield MP3player;

int buttonState = 0;
const int buttonPin = 12;
void setup() {

  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
  MP3player.begin();
  MP3player.SetVolume(50, 50);
  
}

void loop() {
  
  buttonState = digitalRead(buttonPin);
  
  if(buttonState == LOW){
    MP3player.playTrack(1);
  }
}

Just a about as simple as it gets, right? No good, I realized later that since the playTrack() function actually doesn't pause your loop and that it was trying to always start the track. So I poked around the examples and found the state change detection, modified it a bit:

#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h> 
#include <SFEMP3Shield.h>

SFEMP3Shield MP3player;
const int  buttonPin = 12;   
int buttonState = 0;         // current state of the button
int lastButtonState = 1;     // previous state of the button

void setup() {
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
  MP3player.begin();
  MP3player.SetVolume(50, 50);
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {

    if (buttonState == LOW) {
      MP3player.playTrack(1);
    } 
    else {
     }
  }
  // save the current state as the last state, 
  //for next time through the loop
  lastButtonState = buttonState;
}

Seems like it should work too, huh? There are a couple others I've tried and none work. I am an expert at making stupid mistakes and overlooking small errors. Any suggestions? What am I doing wrong? Thanks a ton, happy holidays!!!

In these situations, it's helpful to divide and conquer. Does this play track 1...

#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h> 
#include <SFEMP3Shield.h>

SFEMP3Shield MP3player;

void setup() 
{
  MP3player.begin();
  MP3player.SetVolume(50, 50);
  MP3player.playTrack(1);
}

void loop() 
{
}

yes indeed, I have gotten the track to play multiple times, just not in the way I want. Like in the original sketch it only works with a press and release, not a plain release. Thanks for the quick reply!

Do you have a pull-up or pull-down resistor connected to buttonPin (pin 12)?

yep, it registers the button fine, trouble shot that with the serial monitor.

I can see only two things left: 1. The initial values of buttonState and lastButtonState; 2. Debouncing the push-button.

First, change the initialization to match the usage (won't help with the current problem but it makes it clear to the future-you how the variables are used)...

int buttonState = LOW; // current state of the button
int lastButtonState = HIGH; // previous state of the button

How you initialize the variables will affect how the box behaves on startup. Do you want the music to play on startup if the lid is already open? Or would you prefer the lid to have to be closed then opened for the music to play?

Second, try adding debouncing to the push-button. I've never used any of these so I can't recommend one...
https://www.google.com/search?q=debounce%20arduino

no good. I'd want it to do both. The debouncing also seems like it should work...

/* 
 Debounce
 
 Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
 press), the output pin is toggled from LOW to HIGH or HIGH to LOW.  There's
 a minimum delay between toggles to debounce the circuit (i.e. to ignore
 noise).  
 
 The circuit:
 * LED attached from pin 13 to ground
 * pushbutton attached from pin 2 to +5V
 * 10K resistor attached from pin 2 to ground
 
 * Note: On most Arduino boards, there is already an LED on the board
 connected to pin 13, so you don't need any extra components for this example.
 
 
 created 21 November 2006
 by David A. Mellis
 modified 30 Aug 2011
 by Limor Fried
 
This example code is in the public domain.
 
 http://www.arduino.cc/en/Tutorial/Debounce
 */
#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h> 
#include <SFEMP3Shield.h>

SFEMP3Shield MP3player;
// constants won't change. They're used here to 
// set pin numbers:
const int buttonPin = 12;     // the number of the pushbutton pin
//const int ledPin =  13;      // the number of the LED pin

// Variables will change:
//int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = HIGH;   // the previous reading from the input pin

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 100;    // the debounce time; increase if the output flickers

void setup() {
  pinMode(buttonPin, INPUT);
  //pinMode(ledPin, OUTPUT);
  MP3player.begin();
  MP3player.SetVolume(50, 50);
}

void loop() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button 
  // (i.e. the input went from LOW to HIGH),  and you've waited 
  // long enough since the last press to ignore any noise:  

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  } 
  
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonState = reading;
    MP3player.playTrack(1);
  }
  
  // set the LED using the state of the button:
  //digitalWrite(ledPin, buttonState);

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
}

I dont know, maybe i put the playTrack in the wrong spot? im running out of ideas... Thanks!

Might I suggest that you put each { on a new line, and use Tools + Auto Format to properly indent your code. I think that seeing the structure of the program properly will reveal that you did indeed put the code to play the music in the wrong place.

Ask yourself, for each block, what has to happen to get here.

I like names like currState and prevState to keep track of the current and previous state of the switch. To me, they make a lot more sense than reading and lastButtonState. I look at those names and I can't see a relationship. I look at currState and prevState, and the relationship is obvious.

It's also obvious that you don't need three variables to determine whether the lid was removed. It either was last time and is now, wasn't last time and isn't now, was last time and isn't now, or wasn't last time and is now.

All 4 of those possibilities can be determined from just the current state and the previous state.

Alright, here is Debounce and StateChangeDetection modified to your standards:

#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h> 
#include <SFEMP3Shield.h>

SFEMP3Shield MP3player;
const int  buttonPin = 12;   
int currState = 0;         // current state of the button
int prevState = 0;     // previous state of the button

void setup() {
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
  MP3player.begin();
  MP3player.SetVolume(50, 50);
}


void loop() {
  // read the pushbutton input pin:
  currState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (currState != prevState) 
  {
    if (currState == LOW) 
    {
      MP3player.playTrack(1);
    } 
    else 
    {
    }
  }
  // save the current state as the last state, 
  //for next time through the loop
  prevState = currState;
}
#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h> 
#include <SFEMP3Shield.h>

SFEMP3Shield MP3player;

const int buttonPin = 12;     // the number of the pushbutton pin

int currState;             // the current reading from the input pin
int prevState = HIGH;   // the previous reading from the input pin

long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 100;    // the debounce time; increase if the output flickers

void setup() {
  pinMode(buttonPin, INPUT);
  MP3player.begin();
  MP3player.SetVolume(50, 50);
}

void loop() {

  int reading = digitalRead(buttonPin);

 
  if (reading != prevState) 
  {
    lastDebounceTime = millis();
  } 
  
  if ((millis() - lastDebounceTime) > debounceDelay) 
  {
    currState = reading;
    MP3player.playTrack(1);
  }
  
  prevState = reading;
}

Still not working... Notice the stupid mistake yet?

Alright, here is Debounce and StateChangeDetection modified to your standards:

Not to my standards...

void setup() {
void loop() {

Which of those sketches are you trying to execute?

How is the switch wired?

Where are the Serial.print() statements that could tell you what is happening?

@Paranemertes, did you get it working?

Oh jeez, sorry about the wait I was relying on the 'email me when replies are posted' and I haven't gotten a single email.

Which of those sketches are you trying to execute?

Both

How is the switch wired?

Exactly as it is in the examples, except it is attached to pin 12.

Where are the Serial.print() statements that could tell you what is happening?

On vacation. I have included them in previous sketches and they confirm that my button is working.

@Coding Badly, Not yet....... :frowning:

We'll start with the first one, with some additions.

#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h> 
#include <SFEMP3Shield.h>

SFEMP3Shield MP3player;
const int  buttonPin = 12;   
int currState = 0;         // current state of the button
int prevState = 0;     // previous state of the button

void setup()
{
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
  MP3player.begin();
  MP3player.SetVolume(50, 50);
}

void loop()
{
  // read the pushbutton input pin:
  currState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (currState != prevState) 
  {
    Serial.println("A transition occurred...");
    if (currState == LOW) 
    {
      Serial.println("...to pressed. Play the 1st track");
      MP3player.playTrack(1);
    } 
  }
  // save the current state as the last state, 
  //for next time through the loop
  prevState = currState;
}

What gets printed? What happens, sound-wise?

Ok gave it a try, Held the button and started serial monitor, waited 10 seconds then released the button. Here is what I got serial-wise:

A transition occurred...
A transition occurred...
...to pressed. Play the 1st track
A transition occurred...
A transition occurred...
...to pressed. Play the 1st track
A transition occurred...
A transition occurred...
...to pressed. Play the 1st track
A transition occurred...
A transition occurred...
...to pressed. Play the 1st track
A transition occurred...
A transition occurred...
...to pressed. Play the 1st track
A transition occurred...
A transition occurred...
...to pressed. Play the 1st track

That just kept going infinitely, looks like it is constantly trying to play the track so it never actually starts. That was the problem I was getting earlier! Sound-wise I am getting nothing. Thanks for sticking with it! Belated Christmas presents are always more fun anyway.

That just kept going infinitely

Whether you push the switch or not? If that happens without you pushing the switch, there is something wrong with your switch or wiring.

Serial monitor starts up and I get this:

A transition occurred...

Then I release the button and get this continuously:

A transition occurred...
A transition occurred...
...to pressed. Play the 1st track
A transition occurred...
A transition occurred...
...to pressed. Play the 1st track
A transition occurred...
A transition occurred...
...to pressed. Play the 1st track
A transition occurred...
A transition occurred...
...to pressed. Play the 1st track
A transition occurred...
A transition occurred...
...to pressed. Play the 1st track
A transition occurred...
A transition occurred...
...to pressed. Play the 1st track

If I press the button while it is doing that it pause the deluge, release it and it resumes.

I'd suggest rewiring the switch. Connect one side to ground. Connect the other side to pin 12.

void setup()
{
  pinMode(buttonPin, INPUT);
  digitalWrite(buttonPin, HIGH); // Add this

No good. I don't think its the button, that has been working fine throughout the project.