An updated version with some corrections and one new feature.
now you can configure MAXTAP in this line:
#define MAXTAP 8000
It defines a timeout between taps. Any tap interval higher than this value will be ignored. This avoid that after some minutes, if you push the tap once, everything is screwed.
/*
Tap Tempo using Jleds
*/
#include <jled.h>
#define THRESHOLD 20
#define EXP1 A0
#define MAXDELAY 3000
#define MINDELAY 1
#define MAXTAP 8000
int period = 2000;
JLed leds[] = {
JLed(3).Breathe(period).Forever(),
JLed(4).Blink(period/4*3, period/4).Forever(),
JLed(5).FadeOff(period).Forever(),
JLed(6).FadeOn(period).Forever(),
JLed(LED_BUILTIN).Blink(period/2, period/2).Forever()};
int lastVal = 0;
int tempAnalog = 0;
boolean PotControls = true;
void setup()
{
pinMode( 12, INPUT ); /* tap button - press it to set the tempo */
}
int lastTapState = LOW; /* the last tap button state */
unsigned long currentTimer[2] = { 500, 500 }; /* array of most recent tap counts */
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 */
// update leds
for (auto& led : leds) {led.Update();}
// check pot value
poll_pot();
delay(1);
}
unsigned long lastTap = 0; /* when the last tap happened */
void tap()
{
if ((millis()-lastTap)>MAXTAP){
lastTap = millis();
return;
}
/* we keep two of these around to average together later */
currentTimer[1] = currentTimer[0];
currentTimer[0] = millis() - lastTap;
lastTap = millis();
// establish new period
period = ((currentTimer[0] + currentTimer[1])/2);
PotControls = false;
// update leds period
update_leds();
}
void update_leds(){
leds[0] = JLed(3).Breathe(period).Forever();
leds[1] = JLed(4).Blink(period/4*3, period/4).Forever();
leds[2] = JLed(5).FadeOff(period).Forever();
leds[3] = JLed(6).FadeOn(period).Forever();
leds[4] = JLed(LED_BUILTIN).Blink(period/2, period/2).Forever();
}
void poll_pot() {
// Read analog value
tempAnalog = analogRead(EXP1);
// Convert 10 bit to milliseconds, 3 seconds maximum
tempAnalog = map(tempAnalog, 0, 1023, 0, MAXDELAY);
tempAnalog = constrain(tempAnalog, MINDELAY, MAXDELAY);
// Check pot value and compare variation with threshold
if((abs(tempAnalog-lastVal)>THRESHOLD))
{
// update period with pot value
period = tempAnalog;
//return control to Pot
PotControls = true;
// Store current value to be used laters
lastVal = tempAnalog;
// update leds with new timing
update_leds();
}
//delay(5);
}