News:

SMF for DIYStompboxes.com!

Main Menu

ARDUINO TAP TEMPO experiments.

Started by deadastronaut, December 11, 2018, 08:06:50 AM

Previous topic - Next topic

deadastronaut

hi guys...just dug out my arduino UNO. as i have a tremolo on breadboard
and thought it would be fun to try a tap for it......simple led to ldr setup...

after seeing this guys video on tap tempo. which looks cool

https://www.youtube.com/watch?v=ur_PEUH7sns

however he is using an arduino NG.

and i cant get the code to load on my UNO. (forgive my noobyness) but can his NG code go onto my UNO?

here is his code : it compiles ok, but wont actually load. thanks in advance.. :)

/*
    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);
}
https://www.youtube.com/user/100roberthenry
https://deadastronaut.wixsite.com/effects

chasm reverb/tremshifter/faze filter/abductor II delay/timestream reverb/dreamtime delay/skinwalker hi gain dist/black triangle OD/ nano drums/space patrol fuzz//

anotherjim

There are some older sketches about that won't compile in the latest IDE, but you should get compiler warnings about that.
There probably aren't any good reasons why a sketch that compiles ok will be refused by the programmer because of what's in the program. There are many other possible reasons for it to fail to upload to the board...

Do you have the right board and processor selected in the Tools menu? I don't think you should get a processor item once UNO is selected because that board never had a choice of processor.
Have you got the right USB driver the UNO uses and is the right COM port selected in the tools menu?
Have you tried a simple example sketch to prove your board can be programmed ok?

A trivial thing in that code, and nothing to do with it working or not. I'm not quite sure what the instruction for the input button is in there...
Quote
                     +------> +5 power
                     |
    Digital 12 <-----+----[ switch ]-----/\/ 10k ohm /\/-----> GND
I've a feeling the formatting may be messed up. Probably it's a 10k pull-up to +5v and the button grounds pin12 when you press it? In which case you could lose the 10k and enable the pins internal pull-up by changing...
QuotepinMode( 12, INPUT );   /* tap button - press it to set the tempo */
To...
pinMode( 12, INPUT_PULLUP );   /* tap button - press it to set the tempo */
Then the only connection is to ground when the button is pressed.

deadastronaut

hi jim, got the code uploaded now, using a better usb pc socket....

so com port /compiling etc all ok....

not so sure on my connections though, the led was flashing, but being quite random...

and no tap...hmmm...
https://www.youtube.com/user/100roberthenry
https://deadastronaut.wixsite.com/effects

chasm reverb/tremshifter/faze filter/abductor II delay/timestream reverb/dreamtime delay/skinwalker hi gain dist/black triangle OD/ nano drums/space patrol fuzz//

deadastronaut

#3
hi im, yep tried that, when i push button it turns the arduino off...(powers off)

hmmm......

edit:  it works.

i removed the 5v supply. and the 10k. and changed the code according to your tip....

now it responds as it should...cheers man . rob .  8) 8) 8)
https://www.youtube.com/user/100roberthenry
https://deadastronaut.wixsite.com/effects

chasm reverb/tremshifter/faze filter/abductor II delay/timestream reverb/dreamtime delay/skinwalker hi gain dist/black triangle OD/ nano drums/space patrol fuzz//

anotherjim

Cool  8)
Odd the original external 10k pullup resistor caused a holdup. Looks like you're good to go though.
Incidentally, you don't usually have to have the Arduino wired to the application circuit to program it. It's probably a good idea to have nothing but the USB to your computer connected to program it. Normally, the Arduino won't mind things plugged into the I/O pins. But if the digital0 or digital1 pins are used, it can hold up the USB connection needed to program it.

deadastronaut

right, gotcha cheers jim....that makes sense, so it gets confused on uploading..

i tried sticking the code onto a nano earlier, just for neatness, but having grief with a dodgy ch403g driver...i'll persevere...

but yeah it works pretty good....very slow to mega fast...

i tapped along with a few drum riffs at different bpm's just to test ...looked pretty much bang on.
nifty... 8)
https://www.youtube.com/user/100roberthenry
https://deadastronaut.wixsite.com/effects

chasm reverb/tremshifter/faze filter/abductor II delay/timestream reverb/dreamtime delay/skinwalker hi gain dist/black triangle OD/ nano drums/space patrol fuzz//

deadastronaut

hi guys, well i managed to get it onto a nano...i had driver issues :icon_rolleyes:. done.

heres what i have, and the updated code for anyone playing along... :)

the square is fun and works really well, but how to make it switch between square and triangle..(pulsing led)?

excuse my noobness with this lark.. ::)




/*
    Tap Tempo
   
    An experiment to detect tempo by tapping a button
   
    Press a button connected to digital pin 12.
    LED on pins 2-11 displays the beat pulse
    LED on pin 13 shows the current button state (dim when button is pressed)
   
    Digital Output 2-11 pins <----- 220 ohm ----+[LED]----> GND
   
    (Digital 13 is wired up to the LED on the uno/nano board.  If you have an older
     board, drop the standard LED between pin 13 and GND)
     
    Digital 12 <---------[ switch ]--------> GND

*/

void setup()
{
  pinMode( 12, INPUT_PULLUP );   /*   /* 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);
}
https://www.youtube.com/user/100roberthenry
https://deadastronaut.wixsite.com/effects

chasm reverb/tremshifter/faze filter/abductor II delay/timestream reverb/dreamtime delay/skinwalker hi gain dist/black triangle OD/ nano drums/space patrol fuzz//

anotherjim

So you have pins 2 to 11 pulsing high in turn at the set tempo?
Do you want a 10 stage resistor ladder thing then to make a staircase ramp waveform?

deadastronaut

Hi jim. No i just have 1 led...i just showed it can be connected to any or all of those pins..
https://www.youtube.com/user/100roberthenry
https://deadastronaut.wixsite.com/effects

chasm reverb/tremshifter/faze filter/abductor II delay/timestream reverb/dreamtime delay/skinwalker hi gain dist/black triangle OD/ nano drums/space patrol fuzz//

potul

If you want to output something different than a square signal, you will need some sort of DAC.

For arduino, the simplest way is to use PWM in one of the compatible pins, and use the analogWrite() function.

In arduino nano, the pwm compatible pins are:

QuotePWM: 3, 5, 6, 9, 10, and 11. Provide 8-bit PWM output with the analogWrite() function.

potul

Note that you may need some filtering, and that the output is only 8 bits.... You could combine 2 outputs for better resolution, I guess.

anotherjim

Yeh, I thought PWM too.
If you have the tempo period as a value, you could divide that by how many "steps" for a staircase ramp wave you want. Use that time to delay between increments of a value that is used for the analogWrite to a PWM output. Reset the value to zero when it reaches a maximum for a saw wave or start decrementing back down toward zero for a triangle. You'll probably have to shave some time off the step delay time period to allow for calculation delays.
Alternatively for simple, scale the tempo value so that its range suits what the analogWrite can take, and treat it the PWM voltage as a control voltage, although it won't be scaled in any exact way to the tempo, just inversely proportional. Faster tempo = lower voltage.

deadastronaut

ha ha i'm lost already..... ::)

i was looking at the resistor ladder earlier...hmmmm.

couldn't i just take the arduino out to an opamp lfo with triangle and square
and use the tap part to control the speed of that?....just thinking aloud..  :-\

gets coat... :-\
https://www.youtube.com/user/100roberthenry
https://deadastronaut.wixsite.com/effects

chasm reverb/tremshifter/faze filter/abductor II delay/timestream reverb/dreamtime delay/skinwalker hi gain dist/black triangle OD/ nano drums/space patrol fuzz//

anotherjim

You could use the tempo pulse from the Arduino to clock a counter with a resistor ladder and use that as an LFO. There is a kind of sequencer, used for making evolving sounds, that's actually a step sequencer with pots instead of fixed resistors. There are some designs out there for that using CD4017 counter chips.

The problem with controlling an external LFO is in making the speed of that LFO match in sync with the tempo pulse. Just for kicks, hook up a simple RC low pass on the tempo output to get a poor man's triangle wave. You should find there is no way to have the full voltage swing up and down for a range of tempo. Either the cap charges too soon and you get flat top waves or never reaches the top before it goes back down.  It will only be close to ideal at one tempo rate. That said, with a variable resistor or some different caps in the RC, you might find that works well enough for your application.

The counter/step sequencer approach is sure to be in sync, but the period before it repeats will be some multiple slower than the tempo pulse. So a 4bit counter gives an LFO sequence of 16 steps, but the rate is 16 times slower than the tempo pulse. Ok for a flanger sweep, but maybe not a tremolo?

I don't know for sure how the Arduino LED acts in tempo. Is it like, if you tap 60 per minute, then it flashes 60 times per minute, so it's 1 pulse per quarter note? What most tap tempo devices do under the hood, is derive a pulse time a fraction of the BPM time. They can deliver the tempo control at rates like 48 or 96 PPQN or as fast as the processor allows. PPQN is pulses per quarter note. So if the tempo is 60BPM which is 60 quarter notes per minute, the tempo pulse may actually be up to 96 times faster (but it displays at a more human-readable rate). Then it can use that faster time or multiples of it, to step through a wavetable of a selected wave shape and deliver a reasonable quality LFO output via some kind of DAC that can be fast enough for vibe/trem use if it's called for.


deadastronaut

''hook up a simple RC low pass on the tempo output to get a poor man's triangle wave.''

hi jim, yeah i tried that, not good..didnt notice much difference if any...maybe i had wrong values.  ::)

anyway as for the bpm. i was tapping along with drum beats at different bpm's, and yes it does quarter notes

quite nicely ,60bpm, 120bpm, etc....it looks like its bang on going by the led on /off...it can go very slow , to very fast....


i now have 2 nanos on breadboard....one with the tap tempo as above...

and the other nano as a flash led with pot for speed control......

ive been trying to get the flash led with speed control to pulse (fade in / out instead of flash...

theres plenty of sketches out there to 'fade' but none that use the pot as the speed too...still looking/tweaking.

it would be nice to combine all 3,  flash, pulse (fade in/out) , with speed pot....and of course tempo.

then it would be pretty useful..

https://www.youtube.com/user/100roberthenry
https://deadastronaut.wixsite.com/effects

chasm reverb/tremshifter/faze filter/abductor II delay/timestream reverb/dreamtime delay/skinwalker hi gain dist/black triangle OD/ nano drums/space patrol fuzz//

deadastronaut

well ive been looking about, and found a great little gem...

https://github.com/jandelgado/jled/tree/master/examples/multiled

now i have 
1: flashing led : perfect for choppy trem. 8)
2 pulsing led   : perfect for smooth trem. 8)
3 ramp up then off led  : might be interesting ::)
4 ramp down then off led  :might be intersting ::)

all at the same time, in time too...as in the link.

here is code for above.

#include <jled.h>

JLed leds[] = {
    JLed(3).Breathe(2000).Forever(),
    JLed(4).Blink(750, 250).Forever(),
    JLed(5).FadeOff(1000).Forever(),
    JLed(6).FadeOn(1000).Forever(),
    JLed(LED_BUILTIN).Blink(500, 500).Forever()};

void setup() {
}

void loop() {
    for (auto& led : leds) {led.Update();}
    delay(1);
}


how to paste this into the above tap code if possible????....hmmmm...
https://www.youtube.com/user/100roberthenry
https://deadastronaut.wixsite.com/effects

chasm reverb/tremshifter/faze filter/abductor II delay/timestream reverb/dreamtime delay/skinwalker hi gain dist/black triangle OD/ nano drums/space patrol fuzz//

potul

Give this a try:


/*
    Tap Tempo using Jleds
   
*/

#include <jled.h>

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()};

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();}
    delay(1);
}

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();
 
  // establish new period
  period = ((currentTimer[0] + currentTimer[1])/2);

  // update leds period
  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();
}

deadastronaut

hi potul, thanks for taking a look, very much appreciated.

i tried it, but its not accepting any taps.....no tap tempo.

the 4 leds react as they should for a while,, then go a bit random...and fast..without tapping.

cheers rob .

https://www.youtube.com/user/100roberthenry
https://deadastronaut.wixsite.com/effects

chasm reverb/tremshifter/faze filter/abductor II delay/timestream reverb/dreamtime delay/skinwalker hi gain dist/black triangle OD/ nano drums/space patrol fuzz//

potul

crazy... I will try to debug it... I did not test it in an actual arduino, just simulated.

deadastronaut

cheers man, i was just thinking,

if we use the original tap tempo sketch, and then just add a fading led to a pwm pin

so one is flashing on off/ and the other is fading on/off, it may be easier....just thinking aloud..

cheers rob .

https://www.youtube.com/user/100roberthenry
https://deadastronaut.wixsite.com/effects

chasm reverb/tremshifter/faze filter/abductor II delay/timestream reverb/dreamtime delay/skinwalker hi gain dist/black triangle OD/ nano drums/space patrol fuzz//