Case Switching w/ Button Press

I've looked through a this forum and found some solid examples on how to do this. Unfortunately I cannot get mine to work as intended.

I'm writing code to switch melodies on a passive speaker by pushing a button. However, the way the code is currently written, I can't get the button to do anything. I checked the wiring and there is nothing wrong with my circuit. Help would be appreciated

byte ledPin[] = {6, 7, 8, 9, 10, 11, 12, 13};
int currentLED = 0;
int buttonPin = 2;
int speakerPin = 3;
int buttonCounter = 1;
int buttonState = 0;
int currentState = 0;
int length;

#define R   25000

#define C2  65
#define CS2 69
#define D2  73
#define DS2 78
#define E2  82
#define F2  87
#define FS2 93
#define G2  98
#define GS2 104
#define A2  110
#define AS2 117
#define B2  123

#define C3  131
#define CS3 139
#define D3  147
#define DS3 156
#define E3  165
#define F3  175
#define FS3 185
#define G3  196
#define GS3 208
#define A3  220
#define AS3 233
#define B3  247

#define C4  262
#define CS4 277
#define D4  294
#define DS4 311
#define E4  330
#define F4  349
#define FS4 370
#define G4  392
#define GS4 415
#define A4  440
#define AS4 466
#define B4  494

#define C5  525

#define W 1
#define H 0.5
#define Q 0.25
#define E 0.125
#define S 0.0625


void setup() {
  for (int x = 0; x < 8;  x++) {
    pinMode (ledPin[x], OUTPUT);
  }
  pinMode (2, INPUT);
  pinMode (3, OUTPUT);
}

void loop() {

  switch (buttonCounter)
  {
    case 1:
      break;
    case 2:
      melody1();
      break;
    case 3:
      melody2();
      break;
    case 4:
      // melody3();
      break;
    case 5:
      // melody4();
      break;
    case 6:
      // melody5();
      break;
  }
}

int buttonPress()
{
  buttonState = digitalRead(buttonPin);
  if (currentState != buttonState) {
    if (buttonState == LOW) {
      buttonCounter++;
    }
    if (buttonCounter == 5) {
      buttonCounter = 1;
    }
  }
}

void melody1() {
  int tune[] = {   B3, D4, G4, B4, B4, D4, A4, C5, B4, G4, G3, B3, D4, G4, G4, A3, FS4, A4, G4,
                   R, G4, G4, G4, G4, FS4, A4, G4, D4, R, B3, D4, D4, B3, A3, D4, B3, R,
                   R, G4, G4, G4, G4, FS4, A4, G4, D4, R, B3, D4, D4, B3, A3, D4, B3, R,
                   R, E4, G4, G4, E4, D4, G4, D4, G4, R, FS4, A4, A4, G4, B4, A4, G4, R,
                   R, E4, G4, G4, E4, D4, G4, D4, G4, R, FS4, A4, A4, G4, B4, A4, G4, R,
                   R, B4, A4, G4, E4, R, R, B4, A4, G4, A4, R,
                   R, B4, A4, G4, E4, D4, B4, A4, G4, E4, D4, B4, A4, G4, B4,
                   R, B4, A4, G4, E4, G4, G4, E4, A4, R, A4, A4, G4, B4, A4, G4, B4, G4,
                   R, B4, A4, G4, E4, D4, B4, A4, G4, E4, D4, B4, A4, G4, G4
               };
  float duration[] = {  E, E, E, Q, Q, E, Q, Q, Q, Q, E, E, E, Q, Q, E, Q, Q, H,
                        Q, E, Q, Q, E, Q, Q, Q, Q, Q, E, Q, Q, E, Q, Q, Q, Q,
                        Q, E, Q, E, Q, Q, Q, Q, Q, Q, E, Q, Q, E, Q, Q, Q, Q,
                        Q, E, Q, Q, E, Q, Q, Q, Q, Q, E, Q, Q, E, Q, Q, Q, Q,
                        Q, E, Q, E, Q, Q, Q, Q, Q, Q, E, Q, Q, E, Q, Q, Q, Q,
                        Q + E, Q, E, Q, H, H, Q + E, Q, E, Q, H, H,
                        Q + E, Q, E, Q, E, Q, Q, E, Q, E, Q, Q, E, Q, W,
                        Q + E, Q, Q, E, Q, E, Q, E, Q, Q + E, Q, Q, E, Q, E, Q, E, Q,
                        Q + E, Q, E, Q, E, Q, Q, E, Q, E, Q, Q, E, Q, W
                     };
  length = sizeof(tune) / sizeof(tune[0]);
  for (int x = 0; x < length; x++) {
    tone(3, tune[x]);
    delay(1500 * duration[x]);
    noTone(3);
    buttonPress();
  }
  buttonPress();
}

void melody2() {
  int tune[] = { AS3, F4, AS3, C4, AS3, F4, R, AS3, F4, AS3, C4, CS4, AS3, R,
                 AS2, F3, F3, AS2, F3, F3, AS2, F3, FS3, F3, F2, C3, C3, F2, C3, C3, F2, C3, CS3, C3,
                 AS2, F3, F3, AS2, F3, F3, AS2, F3, FS3, F3, DS3, R
               };
  float duration[] = {Q, H, Q + W, Q, Q, H, Q, Q + H, Q, H, Q + W, Q, Q, Q, Q, W + H, H,
                      Q, E, E, Q, E, E, Q, Q, Q, Q, Q, E, E, Q, E, E, Q, Q, Q, Q, Q, E, E, Q, E, E, Q, Q, Q, Q, W + H, Q
                     };
  length = sizeof(tune) / sizeof(tune[0]);
  for (int x = 0; x < length; x++) {
    tone(3, tune[x]);
    delay(1000 * duration[x]);
    noTone(3);
    buttonPress();
  };
  buttonPress();
}

So far so good.

In your melody routines, the use of delay will make the button seems very unresponsive as it will be checked only between notes, you'll have to hold it down until that happens.

But the real problm (!) is that you do not have a mechanism for interrupting the currently playing melody. You check the button, and buttonCounter is probably being incremented, but there is no logic to return to your switch statement in the loop() function.

This is a bit kludgy, but you could use the return value of buttonPress, which you declare but do not actually yet return antthing from buttonPress. Make it 0 if buttonPress did not increment the counter, make it return 1 if it did increment.

Then in your melody functions check the return value of buttonPress, and if it indicates that the button was pressed / buttonCointer incremented, use that to immediately return, breaking the melody and allowing your loop switch to, er, switch to the next melody.

BTW the two melody functions have some common code that begs to be made into a "play melody" function they both could call.

HTH

a7

It looks to me like you only call buttonPress() from inside the melody playing functions. You initialise buttonCounter to 1 but if it's 1 you do nothing...so you never get into a melody function and buttonPress() never gets called.

A few Serial.print()s to show where in the code it gets to and useful values like buttonCounter would probably have helped.

Steve