0
/**************************************/
const int lowestPin = 1;//the lowest one attach to
const int speaker = 13;
int ts = 4;//how many beats you want
int count = 1;
const int keyPin = 12;
int buttonState = 0;
int bpm = 120;
/**************************************/
void setup()
{
 for (int thisPin = 1; thisPin <= ts; thisPin++)
 {
 pinMode(thisPin, OUTPUT); //initialize thisPin as an output
 pinMode(6, INPUT);
 }
 pinMode(keyPin, INPUT);
}
/****************************************/
void loop()
{
 //iterate over the pins
 //turn the led on from lowest to the highest
 if (digitalRead(keyPin) == HIGH && ts == 2) {
 ts = 3;
 delay(2000);
 }
 else if (digitalRead(keyPin) == HIGH && ts == 3) {
 ts = 4;
 delay(2000);
 }
 else if (digitalRead(keyPin) == HIGH && ts == 4)
 {
 ts = 2;
 delay(2000);
 }
 for (int thisPin = 1; thisPin <= ts; thisPin++)
 {
 bpm = pulseIn(6, HIGH);
 pinMode(13, OUTPUT);
 if (ts > 4)
 {
 if (count > 3)
 for (int a = 4; a <= ts; a++) {
 digitalWrite(a - 3, HIGH);
 }
 }
 else
 digitalWrite(thisPin, HIGH);
 if (count == 1)
 tone(13, 1500, 100);
 else
 tone(13, 1000, 100);
 delay(bpm - 52);
 pinMode(13, INPUT);
 digitalWrite(thisPin, LOW);
 count++;
 if (count > ts)
 count = 1;
 }
}

I am trying to make a metronome using Arduino Uno, with 4 LEDs, each LED is a beat. I want to change the time signature every time I press the pushbutton, so that there are different number of beats per measure, but when I do press the button, it runs the code for 2 and 3 beats per measure once, and then goes back to its default, 4 beats per measure.

Sometimes, it even changes without pressing the button, randomly. I am using a 220 ohm resister instead of 10, as 10 starts much more randomly than the 220.

Metronome project picture

Nick Gammon
38.9k13 gold badges69 silver badges125 bronze badges
asked Mar 12, 2016 at 21:21
2
  • Do you have resistors in series with those LEDs? Commented Mar 13, 2016 at 0:30
  • No resistors are with those LEDs Commented Mar 13, 2016 at 2:47

1 Answer 1

1

You must have resistors in series with the LEDs. See The care and feeding of LEDs. 330 ohms in series with each LED would be about right in your situation.

With no resistors you are drawing far too much current from the output pins. That would drop the voltage and the processor would reset. Thus it goes back to the default of 4 beats per measure.

It also damages both the processor and the LEDs.

You can tell if the processor resets by putting extra code into setup. For example, after setting the pins to outputs:

 for (int i = 0; i < 10; i++)
 {
 digitalWrite (3, HIGH);
 delay (200);
 digitalWrite (3, LOW);
 delay (200);
 }

If you see pin 3 flashing 10 times, you know the processor has reset.


I think your problem now is that you have a floating input for the switch. When I tried your sketch, with a couple of modifications, it worked fine.

My code:

/**************************************/
const int lowestPin = 1;//the lowest one attach to
const int speaker = 13;
int ts = 4;//how many beats you want
int count = 1;
const int keyPin = 12;
int buttonState = 0;
int bpm = 120;
/**************************************/
void setup()
{
 for (int thisPin = 1; thisPin <= ts; thisPin++)
 {
 pinMode(thisPin, OUTPUT); //initialize thisPin as an output
 pinMode(6, INPUT);
 }
 pinMode(keyPin, INPUT_PULLUP);
}
/****************************************/
void loop()
{
 //iterate over the pins
 //turn the led on from lowest to the highest
 if (digitalRead(keyPin) == LOW && ts == 2) {
 ts = 3;
 delay(2000);
 }
 else if (digitalRead(keyPin) == LOW && ts == 3) {
 ts = 4;
 delay(2000);
 }
 else if (digitalRead(keyPin) == LOW && ts == 4)
 {
 ts = 2;
 delay(2000);
 }
 for (int thisPin = 1; thisPin <= ts; thisPin++)
 {
 bpm = pulseIn(6, HIGH);
 //bpm = 1000;
 pinMode(speaker, OUTPUT);
 if (ts > 4)
 {
 if (count > 3)
 for (int a = 4; a <= ts; a++) {
 digitalWrite(a - 3, HIGH);
 }
 }
 else
 digitalWrite(thisPin, HIGH);
 if (count == 1)
 tone(speaker, 1500, 100);
 else
 tone(speaker, 1000, 100);
 unsigned long now = millis ();
 while (millis () - now < (bpm - 52))
 {
 // quit delay if switch pressed
 if (digitalRead(keyPin) == LOW)
 break;
 }
 pinMode(speaker, INPUT);
 digitalWrite(thisPin, LOW);
 count++;
 if (count > ts)
 count = 1;
 } // end of for each pin
} // end of loop

Note that the input from the switch is now INPUT_PULLUP which means it is pulled HIGH by an internal resistor. Thus, the tests are now for == LOW rather than == HIGH.

Also, instead of a delay for the timing of the metronome, I changed it to testing millis() and seeing if time is up. Otherwise you have to hold the switch down for the entire time that a cycle repeats.

answered Mar 13, 2016 at 20:43
2
  • Now that I have resistors, the button still does not change the time signature (ts). How can I wire this differently or change the code? Commented Mar 14, 2016 at 0:58
  • See amended reply. Commented Mar 14, 2016 at 1:45

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.