Manually stop and start looping music

This is a kid’s game project (Buzz Wire) I got off the internet. Thanks to very good help from groundFungus on this forum, it works fine, but…

The original code includes the Monty Python theme played on piezos. It’s a nice bit of programming but somewhat grating as it repeats endlessly and rather loudly.

I’m a rank beginner, but I have worked through two online tutorials (Code Academy was quite basic, but I got through about 12 or 14 lessons on Alex Allain’s cprogramming.com before finding myself over my head). I’ve been able to modify the code so that when the circuit is completed the game actually ends (using “exit(0)”), which also stops the music. So now the problem is that ending the annoying music is not only a distraction, but a positive incentive to lose the game!

What I’d like to do is have the ability to manually turn the music on or off. I’m thinking I could add a button switch that would start or stop the music whenever it was pushed. I’ve made a few attempts, but I really can’t see how the code flows, so all my tries have been way off the mark.

Can anyone help me out with a plausible solution? And if so, I need guidance on what areas of the code you need to see. I’m including the “sing()” block, which is what runs the music. I’m also including the fritz board diagram, in case that’s helpful.

void sing()
{
   // play the song in a non blocking way
   unsigned long currentMillis = millis();

   if (currentMillis - previousMillis2 >= interval2)
   {
      previousMillis2 = currentMillis;
      int noteDuration = 1000 / tempo[songState];
      buzz(10, melody[songState], noteDuration);
      int pauseBetweenNotes = noteDuration;
      delay(pauseBetweenNotes);

      // stop the tone playing:
      buzz(10, 0, noteDuration);

      ++songState; 
      // start song again if finished
      if (songState > 79)
      {
         songState = 14; // skip intro
      }
   }
}

BuzzGame_bb.pdf (187 KB)

Here is an example to toggle a flag with a button press. Use the flag and an if statement to conditionally call the sing function.

const int  buttonPin = 8;    // the pin that the pushbutton is attached to
const int ledPin = 13;       // the pin that the LED is attached to
// Variables will change:
boolean buttonState = 0;         // current state of the button
boolean lastButtonState = 0;     // previous state of the button
boolean playMontyFlag = true;  // initial value of play the tune flag

void setup()
{
   // initialize the button pin as a input with internal pullup enabled
   pinMode(buttonPin, INPUT_PULLUP);
   // initialize the LED as an output:
   pinMode(ledPin, OUTPUT);
   // initialize serial communication:
   Serial.begin(9600);
}

void loop()
{
   // read the pushbutton input pin:
   buttonState = digitalRead(buttonPin);
   // compare the buttonState to its previous state
   if (buttonState != lastButtonState)
   {
      if (buttonState == LOW)
      {
         // if the current state is LOW then the button
         // went from not pressed to pressed:         
         digitalWrite(ledPin, !digitalRead(ledPin));
         // toggle a flag to run the sing function or not
         playMontyFlag = !playMontyFlag;
         if(playMontyFlag == true)
         {
          Serial.println("playing Monty Python tune");
         }
         else
         {
          Serial.println("Blessed Silence");
         }
      }
      lastButtonState = buttonState;     
   }
}

Wire the switch like this:

digin.jpg

Thanks Charlie. I will try to work through this tomorrow and let you know how I do.

One question, though. I'm not sure what your reference to an LED is.

  • Jeff

I’m including a fritz of how I set up the new button (see note, “Button 2”) on the board because, sorry to say, I’m not sure I understood your schematic. I just set it up as the existing button was set up, except that I used a 10k resistor (brown/black/orange) as your schematic called for. Guessing that R1 is the 10k resistor and C1 is a capacitor, and since both are optional, I tried replacing the resistor with a direct ground connection, but then nothing worked. (And I didn’t try the capacitor because I haven’t worked with them at all yet.)

I integrated your code into the existing code. The declarations are above Void Setup, the Pin Initializations are at the top of Void Setup, and Button Read is at the top of Void Loop. I added “sing();” to your If statement, right below “Serial.println(“playing Monty Python tune”);”.

HERE’S WHERE I ADDED sing() TO YOUR CODE:

if (buttonState == LOW)
      {
         // if the current state is LOW then the button
         // went from not pressed to pressed:         
         digitalWrite(ledPin, !digitalRead(ledPin));
         // toggle a flag to run the sing function or not
         playMontyFlag = !playMontyFlag;
         if(playMontyFlag == true)
         {
          Serial.println("playing Monty Python tune");
          sing();
         }
         else
         {
          Serial.println("Blessed Silence");
         }
      }

When I run it, I see your printouts change on the serial monitor as I press the new button. But if I leave the original call to “sing()” (see the very bottom of the code below) the tune goes on regardless, and if I rem that Else statement out, then I only get one note of the tune as I lift my finger off the button on the play cycle. The original call is part of the procedure that is checking whether the handle touches the course wire.

HERE’S WHERE sing() WAS ORIGINALLY CALLED:

  //Pin 9 is the course-handle circuit. When 9 is activated "Game Over" is displayed and game ends.
  //Press the reset button on the UNO board to reload and play again.
   if (digitalRead(9) == HIGH)
   {
      delay(25);
      if (digitalRead(9) == HIGH)
      {
         quit = true; //When the course circuit is complete the quit flag is set.
         while (digitalRead(9) == HIGH)
         {
            buzz(8, NOTE_B0, 1000 / 24);
            
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("Game Over! RESET");
            lcd.setCursor(0,1);
            lcd.print("to play again");
         }
         
         //Regarding exiting the loop, see Zoul007's post here:  
         //https:stackoverflow.com/questions/23096366/how-to-stop-a-loop-arduino

         if (quit == true){exit(0);} //When the course circuit is broken again, the game ends
      }
   }
   else
   {
       sing();
   }

BuzzWire_Button2_bb.pdf (714 KB)

One question, though. I’m not sure what your reference to an LED is.

The LED is the built in LED (pin 13) just for visual indication of operation. Not required.

The switch wiring is how to wire a switch using the internal pullup resistor. Each digital input has a pullup resistor built into the chip that is enabled using the pinMode(INPUT_PULLUP) function. It is the preferred way to wire a switch. The fact that you wired the switch differently may not matter as the state change is still detected.

The call to the sing function does not belong in the switch state detection part,

 if(playMontyFlag == true)
         {
          Serial.println("playing Monty Python tune");
          sing();  // REMOVE THIS
         }
         else
         {
          Serial.println("Blessed Silence");
         }

Put the if statement to control whether the tune plays or not in this part of the code.

    if (quit == true){exit(0);} //When the course circuit is broken again, the game ends
      }
   }
   else
   {
        // ADD THIS HERE
        if(playMontyFlag == true)
       {  
            sing();
        }
   }

Yes!! Perfect! Ahhhhh, “Blessed Silence”. I had figured that logic out for my “quit” flag, but completely missed it on this.

I assume there’s no problem using pin 13 for the switch, is there? Pin 3 is the only other pin I have available and I could use that. I just chose the one that is physically closer. And it works.

May I ask another? Would it be possible to power this contraption other than with a USB printer cable? Such as with a 9V battery? That’s is, without too much reconfiguration? In the Starter Kit project book, they have two projects that use a battery, but they are both for running a motor, which requires extra juice. I’m just wondering if my grandson and his friends could play with this thing without a computer handy.

Once again, thanks very much, Charlie. I really appreciate your efforts. Thanks to you I was able to get all the pieces ready and Chance and I spent a very nice afternoon building it all like a kit.

  • Jeff

P.S. Here’s a picture of what we ended up with:

Buzz Wire Game 2.jpg

A 9V transistor battery will power that for at least a few hours, I think. Those batteries do not have much capacity. The major current draws are the Uno (30 to 50 mA) and the LCD backlight (maybe 30 mA at most). Discharges at that rate the capacity of an alkaline 9V battery is around 300 to 400 mAh (milli Amp hours). Connect the battery through Vin or the barrel jack. The barrel jack being preferred, in my opinion, because of the reverse polarity protection diode.

There is no problem using pin 13 for the switch.

Nice job on the project. You must have a good helper.

How about this AC adapter? Power Adapter - Arduino

I've got two good helpers: Chance is pretty savvy at 10 years old; and you.

That adapter looks good. 9V to 12V output, check,. 2.1mm plug, check, Greater than 250mA output, check. Center pin positive, check.
Here is a page that describes the power pack requirements.

For my projects, I often use 5V (500mA to 1A) cell phone chargers connected to the 5V input (bypassing the 5V regulator). I buy those (used) chargers at my local thrift store for $0.50 to $1.00 each.

And thanks for the compliment. It is appreciated.

I see the Vin jack and I have a few old cell phone chargers that fit that description, but how would I configure the plug? It looks like two wires going to the plug that goes to the phone. Could I just cut that off, strip the wires, twist them together and plug them in like that? Or maybe cannibalize a plug pin from another Arduino connector?

I usually cut the micro USB connector off and solder a 2 pin header on the end to plug into the 5V and ground female pins on the Uno power header. Don't put a plug on and connect to the barrel jack or connect to Vin. The 5V output of the phone charger is not enough voltage to operate the 5V regulator. Check the output of the phone charger with your meter, before connecting, for correct polarity and voltage. There is no protection between the 5V input and the processor so polarity is very important and the charger output voltage needs to be berween 4.7 and 5.5 Volts for a 16MHz Uno.

If the wires fit into the header snugly enough you can do it that way.

Whew! Fact is I don't know enough to attempt such low-cost alternatives. I can sport for an $8 cord. Thanks for checking out the specs on that for me.

  • Jeff