/* Tap Tempo An experiment to detect tempo by tapping a button Press a button connected to digital pin 12. LED on pins 2-12 displays the beat pulse LED on pin 13 shows the current button state (dim when button is pressed) Digital Output <--------/\/ 220 ohm /\/----[LED]----> GND (Digital 13 is wired up to the LED on the NG board. If you have an older board, drop the standard LED between pin 13 and GND) +------> +5 power | Digital 12 <-----+----[ switch ]-----/\/ 10k ohm /\/-----> GND */ void setup() { pinMode( 12, INPUT ); /* tap button - press it to set the tempo */ pinMode( 13, OUTPUT ); /* button state display - not necessary */ for( int i=2 ; i<12 ; i++ ) { pinMode( i, OUTPUT ); /* tempo display light - shows the current tempo */ } } int lastTapState = LOW; /* the last tap button state */ unsigned long currentTimer[2] = { 500, 500 }; /* array of most recent tap counts */ unsigned long timeoutTime = 0; /* this is when the timer will trigger next */ unsigned long indicatorTimeout; /* for our fancy "blink" tempo indicator */ void loop() { /* read the button on pin 12, and only pay attention to the HIGH-LOW transition so that we only register when the button is first pressed down */ int tapState = digitalRead( 12 ); if( tapState == LOW && tapState != lastTapState ) { tap(); /* we got a HIGH-LOW transition, call our tap() function */ } lastTapState = tapState; /* keep track of the state */ /* check for timer timeout */ if( millis() >= timeoutTime ) { /* timeout happened. clock tick! */ indicatorTimeout = millis() + 30; /* this sets the time when LED 13 goes off */ /* and reschedule the timer to keep the pace */ rescheduleTimer(); } /* display the button state on LED 2 */ digitalWrite( 13, tapState ); /* display the tap blink on LED 13 */ for( int i=2 ; i<12 ; i++ ) { if( millis() < indicatorTimeout ) { digitalWrite( i, HIGH ); } else { digitalWrite( i, LOW ); } } } unsigned long lastTap = 0; /* when the last tap happened */ void tap() { /* we keep two of these around to average together later */ currentTimer[1] = currentTimer[0]; currentTimer[0] = millis() - lastTap; lastTap = millis(); timeoutTime = 0; /* force the trigger to happen immediately - sync and blink! */ } void rescheduleTimer() { /* set the timer to go off again when the time reaches the timeout. The timeout is all of the "currentTimer" values averaged together, then added onto the current time. When that time has been reached, the next tick will happen... */ timeoutTime = millis() + ((currentTimer[0] + currentTimer[1])/2); }