/**************************************/
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.
-
Do you have resistors in series with those LEDs?Nick Gammon– Nick Gammon ♦2016年03月13日 00:30:21 +00:00Commented Mar 13, 2016 at 0:30
-
No resistors are with those LEDsMike Zhou– Mike Zhou2016年03月13日 02:47:54 +00:00Commented Mar 13, 2016 at 2:47
1 Answer 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.
-
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?Mike Zhou– Mike Zhou2016年03月14日 00:58:53 +00:00Commented Mar 14, 2016 at 0:58
-
See amended reply.2016年03月14日 01:45:07 +00:00Commented Mar 14, 2016 at 1:45