Guitar Rhythm Taper

Hi all,

I was trying out the following code on my arduino and getting an error with the following code. The idea is that is plays the rythm you input via an array in a loop. When you push the program button it goes into record mode and exits the loop to record a series of delays which creates a rythm for the loop phase of the program.

So my two questions are I get one main error with it. And also when I solve this error I imagine I will need a way to code it so the program goes back to the loop after recording. But I though first things first why does it error on me.

Any ideas?

#include <Servo.h>

Servo servo1; // create first servo object to control first servo

int FSR = 0; // FSR on pin 0. CHange this to an FSR

int programSwitch = 2; // If this is high we program a new code.

int tapReadings[20]; // When someone knocks this array fills with delays between knocks.

int programButtonPressed = false; // Flag so we remember the programming button setting at the end of the cycle.

int i = 0;

int totaltaps=0;

int currentTapNumber=0;

void setup()

{

pinMode(programSwitch, INPUT);

servo1.attach(6); // attaches the first servo on pin 6 to the first servo object

}

void loop()

{

if (programSwitch==false)// will repeat what was enterred while unit is not in enterring mode.

//Section where pattern is replayed

{

for (i = 0; i!= currentTapNumber; i = i + 1)

{servo1.write(170);

servo1.write(0);

delay(tapReadings*); // pauses between rythm*
if (i = currentTapNumber)
{i=0;}

}

if (programSwitch==true)
{
taprecording();
{

void taprecording(){

Serial.println(“Start tapping”);
// First lets reset the listening array.

int i = 0;

for (i=0;i<20;i=i+1)
{
tapReadings=0;
tapReadings = analogRead(FSR);
}
{
int currenttapNumber=0; // Incrementer for the array.
int startTime=millis(); // Reference for when this knock started.
int now=millis();
}

do
{
now=millis();
tapReadings[currentTapNumber] = now-startTime;
currentTapNumber ++; //increment the counter
startTime=now;
now=millis();
}
while (programSwitch==true); //I don’t know if this is needed due to what is up top.

}

Sorry if this has been already posted but it seemed like my last attemp got lost in the ethers so will try again.

I am working on this code for it where the proegram plays a ryhthm within the loop section of the program. When a button is pressed it exits that loop to record the new ryhthm via an FSR. I get an error which I can seem to solve. Also am worried even if I solve that what code I need to write to make the program reenter the loop after recoring so it can continually reproduc the rhythm. Here’s the code. Any ideas anybody?

#include <Servo.h>

Servo servo1; // create first servo object to control first servo

int FSR = 0; // FSR on pin 0. CHange this to an FSR

int programSwitch = 2; // If this is high we program a new code.

int tapReadings[20]; // When someone knocks this array fills with delays between knocks.

int programButtonPressed = false; // Flag so we remember the programming button setting at the end of the cycle.

int i = 0;

int totaltaps=0;

int currentTapNumber=0;

void setup()

{

pinMode(programSwitch, INPUT);

servo1.attach(6); // attaches the first servo on pin 6 to the first servo object

}

void loop()

{

if (programSwitch==false)// will repeat what was enterred while unit is not in enterring mode.

//Section where pattern is replayed

{

for (i = 0; i!= currentTapNumber; i = i + 1)

{servo1.write(170);

servo1.write(0);

delay(tapReadings*); // pauses between rythm*
if (i = currentTapNumber)
{i=0;}

}

if (programSwitch==true)
{
taprecording();
{

void taprecording(){

Serial.println(“Start tapping”);
// First lets reset the listening array.

int i = 0;

for (i=0;i<20;i=i+1)
{
tapReadings=0;
tapReadings = analogRead(FSR);
}
{
int currenttapNumber=0; // Incrementer for the array.
int startTime=millis(); // Reference for when this knock started.
int now=millis();
}

do
{
now=millis();
tapReadings[currentTapNumber] = now-startTime;
currentTapNumber ++; //increment the counter
startTime=now;
now=millis();
}
while (programSwitch==true); //I don’t know if this is needed due to what is up top.

}

Without code tags, all indentation is lost. I have added the code tags and attempted to format the code.

#include <Servo.h>

Servo servo1; // create first servo object to control first servo
int FSR = 0; // FSR on pin 0. CHange this to an FSR
int programSwitch = 2; // If this is high we program a new code.
int tapReadings[20]; // When someone knocks this array fills with delays between knocks.
int programButtonPressed = false; // Flag so we remember the programming button setting at the end of the cycle.
int i = 0;
int totaltaps=0;
int currentTapNumber=0;

void setup()
{
  pinMode(programSwitch, INPUT);
  servo1.attach(6); // attaches the first servo on pin 6 to the first servo object
}

void loop()
{

  if (programSwitch==false) // will repeat what was enterred while unit is not in enterring mode.
  {

    //Section where pattern is replayed

    for (i = 0; i!= currentTapNumber; i = i + 1)
    {
      servo1.write(170);
      servo1.write(0);
      delay(tapReadings[i]); // pauses between rythm
      if (i = currentTapNumber)
      {
        i=0;
      }

  }

  if (programSwitch==true)
  {
    taprecording();
  {


  void taprecording(){

    Serial.println("Start tapping");
    // First lets reset the listening array.

    int i = 0;

    for (i=0;i<20;i=i+1)
    {
      tapReadings[i]=0;
      tapReadings = analogRead(FSR);
    }

    {
      int currenttapNumber=0; // Incrementer for the array.
      int startTime=millis(); // Reference for when this knock started.
      int now=millis();
    }

    do
    {
      now=millis();
      tapReadings[currentTapNumber] = now-startTime;
      currentTapNumber ++; //increment the counter
      startTime=now;
      now=millis();
    }
    while (programSwitch==true); //I don't know if this is needed due to what is up top.

}

I am not surprised you have compile errors!I will assume you are not experienced writing C code. For every curly open brace “{” there must be a close curly brace “}”. You are missing braces in some pretty critical places.

Someplace before the taprecording function you need to close the curly brace that defines the guts of the loop function.

I also think that you misunderstand the purpose of the loop function. Loop gets called again as soon as you leave the function. Arduino provides the following hidden code:

void main() {
  setup();
  for (;;) {
    loop();
  }
}

This calls your setup function then calls your loop as fast as it can. Your code would benefit from a significant redesign with these concepts in mind. It might also benefit from a finite state machine implementation. I do not have time at the moment to re-write this, but I might be able to give you suggestions in a few days.

Deleted as it makes no sense after the two threads were combined.

First you might get a mod to move this to the correct forum (Arduino). You’ll get more response there.

Second the number of braces {} don’t match. I’ved tried to correct that but there’s a mess in the taprecording() function I don’t understand.

Third the types declared for the start time and now variables is wrong. Millis() returns an unsigned log. Also when you

locally declare them, that declaration is only valid inside that particular for or do loop. Once outside of that loop the variable is no longer known. This happens in the taprecording() function. You need to make them global variables or/and redo the function. More importantly I don’t understand your coding intent in the taprecording() function. You run through the for loop, reading the FSR as quick as you can, 20 times. You zero out the tap number each time through the loop. In the completely separate do loop you try to compute the some time difference. My guess is you’re trying to record the time between taps and store those away but that function isn’t doing that.

Fourth if you’re going to “print” something to the PC/terminal window, you need a serial.begin in setup(). The PC needs to be setup to agree with the baud rate chosen.

Lastly if you use the code tags (see the “code” button above the full editor text entry box) you’ll get a nicely formatted text box to put your code into, indexing preserved. It sure is easier to read this way. The below uses the code tags and has a sorta-fixed version of your code. Sorta as in the taprecording() function is still AFU but it compiles w/o error.

#include <Servo.h>

Servo servo1; // create first servo object to control first servo
int FSR = 0; // FSR on pin 0. CHange this to an FSR
int programSwitch = 2; // If this is high we program a new code.
int tapReadings[20]; // When someone knocks this array fills with delays between knocks.
int programButtonPressed = false; // Flag so we remember the programming button setting at the end of the cycle.
int i = 0;
int totaltaps=0;
int currentTapNumber=0;
unsigned long now = 0;  // since now is used in 2 places, declare and init here
unsigned long startTime = 0;
int currenttapNumber=0;


void setup()
{
  pinMode(programSwitch, INPUT);
  Serial.begin(9600);
  servo1.attach(6); // attaches the first servo on pin 6 to the first servo object
}

void loop()
{
  if (programSwitch==false)// will repeat what was enterred while unit is not in enterring mode.
    //Section where pattern is replayed
  {
    for (i = 0; i!= currentTapNumber; i = i + 1)
    {
      servo1.write(170);
      servo1.write(0);
      delay(tapReadings[i]); // pauses between rythm
      if (i = currentTapNumber)
      {
          i=0;
      }

      if (programSwitch==true)
      {
        taprecording();
      }
    }
  }
}

void taprecording(){

  Serial.println("Start tapping");
  // First lets reset the listening array.
  int i = 0;

  for (i=0;i<20;i=i+1)
  {
    //tapReadings[i]=0; // you don't need to zero the tapReading if you're setting it below
    tapReadings[i] = analogRead(FSR);
    //int currenttapNumber=0; // Incrementer for the array.
    startTime=millis(); // Reference for when this knock started.
    //int now=millis(); 
    now = millis();
  }

  do
  {
    now=millis();
    tapReadings[currentTapNumber] = now-startTime;
    currentTapNumber ++; //increment the counter
    startTime=now;
    now=millis();
  }while (programSwitch==true); //I don't know if this is needed due to what is up top.

}

deleted - mod merged threads

I am thinking something like:

#include <Servo.h>

const int programSwitch = 2;
const int tapSwitch     = 3;
const int servoPin      = 6;
Servo servo1; // create first servo object to control first servo

unsigned long now;
unsigned long then;
unsigned long target;
int           tap;
int           numTaps;
int           state = 0;
const int     maxTaps = 20;
unsigned long tapDelays[maxTaps];


void setup()
{
  int i;
  pinMode(programSwitch, INPUT);
  pinMode(tapSwitch, INPUT);

  servo1.attach(servoPin); // attaches the first servo on pin 6 to the first servo object

  for (i=0; i<20; i++) {
    tapDelays[20] = 0xffffffff;
  }
  numTaps   = 0;
  tap       = 0;
  firstPass = 0;

  // Move servo away from body 
  servo1.write(170);
  state = 0;

}


void loop()
{

  now = millis();

  // If program switch is in run mode 
  if (!digitalRead(programSwitch))
  {

    switch(state) {

      // Not hitting
      case 0:

        if (now >= target) {
          servo1.write(170);
          target = now + 100;
          state = 1;
        }
        break;

      // Hitting
      case 1:

        if (now >= target) {
          servo1.write(0);
          target = now + tapDelays[tap];
          tap++;
          if (tap >= numTaps) tap = 0;
          state = 0;
 
        }
        break;

      default:
        state = 0;
        break;

    } /* end switch */

    firstPass = 1;


  // If program switch is in record mode 
  } else {

    // If the tap button is pressed (may need to be debounced)
    if (digitalRead(tapSwitch)) {

      if (firstPass) {
        then = now;
        tap = 0;
        numTaps = 0;
        firstPass = 0;

      } else {
        if (tap < maxTaps) {
        tapDelays[numTaps] = now - then;
        numTaps++;
    }

  }

}

Thanks fil-freak. I look forward to it. Yeah quite new at this. Somehow I am not seeing where the curly braces are missing. I will try and tinker with it more too. Another version has all the functions written within the loop.

fll-freak:
Without code tags, all indentation is lost. I have added the code tags and attempted to format the code.

#include <Servo.h>

Servo servo1; // create first servo object to control first servo
int FSR = 0; // FSR on pin 0. CHange this to an FSR
int programSwitch = 2; // If this is high we program a new code.
int tapReadings[20]; // When someone knocks this array fills with delays between knocks.
int programButtonPressed = false; // Flag so we remember the programming button setting at the end of the cycle.
int i = 0;
int totaltaps=0;
int currentTapNumber=0;

void setup()
{
pinMode(programSwitch, INPUT);
servo1.attach(6); // attaches the first servo on pin 6 to the first servo object
}

void loop()
{

if (programSwitch==false) // will repeat what was enterred while unit is not in enterring mode.
{

//Section where pattern is replayed

for (i = 0; i!= currentTapNumber; i = i + 1)
{
  servo1.write(170);
  servo1.write(0);
  delay(tapReadings[i]); // pauses between rythm
  if (i = currentTapNumber)
  {
    i=0;
  }

}

if (programSwitch==true)
{
taprecording();
{

void taprecording(){

Serial.println("Start tapping");
// First lets reset the listening array.

int i = 0;

for (i=0;i<20;i=i+1)
{
  tapReadings[i]=0;
  tapReadings = analogRead(FSR);
}

{
  int currenttapNumber=0; // Incrementer for the array.
  int startTime=millis(); // Reference for when this knock started.
  int now=millis();
}

do
{
  now=millis();
  tapReadings[currentTapNumber] = now-startTime;
  currentTapNumber ++; //increment the counter
  startTime=now;
  now=millis();
}
while (programSwitch==true); //I don't know if this is needed due to what is up top.

}




I am not surprised you have compile errors!I will assume you are not experienced writing C code. For every curly open brace "{" there must be a close curly brace "}". You are missing braces in some pretty critical places.



Someplace before the taprecording function you need to close the curly brace that defines the guts of the loop function. 



I also think that you misunderstand the purpose of the loop function. Loop gets called again as soon as you leave the function. Arduino provides the following hidden code:


void main() {
setup();
for (;:wink: {
loop();
}
}




This calls your setup function then calls your loop as fast as it can. Your code would benefit from a significant redesign with these concepts in mind. It might also benefit from a finite state machine implementation. I do not have time at the moment to re-write this, but I might be able to give you suggestions in a few days.

Yea I did repost it into the Arduino forum after realizing where I put it. Sorry about that and thanks for the code. Lots of new terms you are using in it that I will need to lookup and understand. Thanks for your input. I appreciate it.

hmmm, did a quick study on the code you wrote. I can see more what you mean about the { needed. I think what I need to still input on the code you wrote it a delay function that is managed by an array which was more this part of the original code

{

for (i = 0; i!= currentTapNumber; i = i + 1)

{servo1.write(170);

servo1.write(0);

delay(tapReadings*); // pauses between rythm*
if (i = currentTapNumber)
{i=0;}
i.e. the delays between the strikes is what creates the rhythm. Very Zen actually:-).

Ok I tried to clean it up a bit and restructure it so it may make more sense hopefully. Only getting one error now on asking it to read the FSR.

Here it is.

#include <Servo.h>

Servo servo1; // create first servo object to control first servo

int FSR = 0; // FSR on pin 0. CHange this to an FSR

int programSwitch = 2; // If this is high we program a new code.

int tapReadings[20]; // When someone knocks this array fills with delays between knocks.

int programButtonPressed = false; // Flag so we remember the programming button setting at the end of the cycle.

int i = 0;

int totaltaps=0;

int currentTapNumber=0;

int currenttapNumber=0; // Incrementer for the array.

int startTime=millis(); // Reference for when this knock started.

int now=millis();

void setup()

{

pinMode(programSwitch, INPUT);

servo1.attach(6); // attaches the first servo on pin 6 to the first servo object

}

void loop()

{

if (programSwitch==false)// will repeat what was enterred while unit is not in enterring mode.

//Section where pattern is replayed

{

for (i = 0; i!= currentTapNumber; i = i + 1)

{servo1.write(170);

servo1.write(0);

delay(tapReadings*); // pauses between rythm*
if (i = currentTapNumber)
{i=0;}}

}

else
{
Serial.println(“Start tapping”);
// First lets reset the listening array.
tapReadings = analogRead(FSR);

int i = 0;
for (i=0;i<20;i=i+1)
{
tapReadings=0;
}

}
do
{
now=millis();
tapReadings[currentTapNumber] = now-startTime;
currentTapNumber ++; //increment the counter
startTime=now;
now=millis();
}
while (programSwitch==true); //I don’t know if this is needed due to what is up top.
}

Ok I tried to clean it up a bit and restructure it so it may make more sense hopefully. Only getting one error now where I ask it to read the FSR so it can fill the array.

Here it is.

#include <Servo.h>

Servo servo1; // create first servo object to control first servo

int FSR = 0; // FSR on pin 0. CHange this to an FSR

int programSwitch = 2; // If this is high we program a new code.

int tapReadings[20]; // When someone knocks this array fills with delays between knocks.

int programButtonPressed = false; // Flag so we remember the programming button setting at the end of the cycle.

int i = 0;

int totaltaps=0;

int currentTapNumber=0;

int currenttapNumber=0; // Incrementer for the array.

int startTime=millis(); // Reference for when this knock started.

int now=millis();

void setup()

{

pinMode(programSwitch, INPUT);

servo1.attach(6); // attaches the first servo on pin 6 to the first servo object

}

void loop()

{

if (programSwitch==false)// will repeat what was enterred while unit is not in enterring mode.

//Section where pattern is replayed

{

for (i = 0; i!= currentTapNumber; i = i + 1)

{servo1.write(170);

servo1.write(0);

delay(tapReadings*); // pauses between rythm*
if (i = currentTapNumber)
{i=0;}}
}
else
{
Serial.println(“Start tapping”);
// First lets reset the listening array.
tapReadings = analogRead(FSR);
int i = 0;
for (i=0;i<20;i=i+1)
{
tapReadings=0;
}
}
do
{
now=millis();
tapReadings[currentTapNumber] = now-startTime;
currentTapNumber ++; //increment the counter
startTime=now;
now=millis();
}
while (programSwitch==true); //I don’t know if this is needed due to what is up top.
}

I think I now understand what you’re trying to do. Let’s see if I have it correct. Your Arduino tap machine will have have 2 modes or states; let’s call them recording and playback. When in recording mode it detects taps (on a force sensitive resistor ?) and stores the time between up to 21 taps (20 intervals). It enters recording mode by push of a button and exits back to playback mode by a repress of the same button (or is it a switch ??) or after 21 taps ??

When in playback mode it loops continuously, commanding a servo to go between 2 positions, a strike and a retract, like a drumstick hitting a drumhead. The time between the strikes are the intervals recorded above. I wonder if you might want a run/stop switch to control the striking as well. Lastly I call your attention to a servo’s timing. The position is sent as a pulsewidth in a series of pulses that happen every 20 msec. It takes some time for a servo to go from A to B positions so you need to have some finite (setable) time between commanding a strike and commanding a retract to allow for the pulses to go out plus the servo to react.

ps - I note you’ve posted while I’ve been typing this. I’ve yet to read that post.

pps - Learn to use the code button/tags to post code.

shakamuni01:
Ok I tried to clean it up a bit and restructure it so it may make more sense hopefully. Only getting one error now on asking it to read the FSR.

Still not good. Let’s concentrate on the recording part for the moment. Let me also suggest you read my response to your post in the other forum, especially wrg to declaring variable types and initializing the serial print function.

Right now you aren’t detecting a tap so far as I can see. You’re reading an analog voltage. How does the code “know” when a tap occurs ? I think your intent is to use a FSR to sense the taps. If so you need to set up the FSR with another resistor to create a voltage divider. A change in the resistance of the FSR then results in a change in voltage. A simple threshold check (is the voltage above or below some preset number) can then be used to detect a tap. Because a tap on the FSR lasts for a “long” time when measured by an Arduino you need to allow for the tap to be released. Either wait for a set time after detecting a tap before looking for another or also detect the release of the tap before looking for another.

I think you want to be in a tight loop running the tap detect algorithm and every time a tap is detected, then and only then, record a time, compute an interval (when the tap detected isn’t the 1’st such tap) and increment the tap detected counter. Also check for the number of taps and/or switch position.

http://learn.adafruit.com/force-sensiti … ing-an-fsr

ps - Let’s have all future posts on this topic go here only.

Here’s a snippet of code that fits where you had the tap recording portion. See if it makes sense to you.

  else
  {
    Serial.println("Start tapping");
    // First let's reset the entire possible listening array 
    for (int i=0; i<20; i++)
    {
      tapReadings[i]=0;
    }
    // Second run the tap detection routine
    TapCount = 0;
    while((TapCount <= 20) && (digitalRead(programSwitch)==true))
    {
      if(analogRead(FSR) > thresh)
      {
        if(TapCount == 0)
        {
          StartTime = millis();
          Serial.println("Detected 1'st tap");
        }
        else
        {
          tapReadings[TapCount-1] = millis() - StartTime;
          Serial.print("Recorded interval #   ");
          Serial.println(TapCount);
        }
        TapCount++;   // tap count = 21 after 20 intervals
        // wait for 100 msec before looking for next tap
        delay(100);
      }
    }
    // Done recording taps
    // now recompute tap intervals relative to prior tap
    // not relative to StartTime
    for(int i=1; i<=TapCount; i++)
    {
      tapReadings[i] = tapReadings[i] - tapReadings[i-1];
    }
    Serial.println("Finished recording tap data");
  }
}

I would add a visual indicator (an LED) to show when in record mode and still recording taps.

btw : you may note I calculated the tapReadings a different way than you did. Both are valid, I just wanted to give you a different look as how things can be done. I saved 4 bytes of SRAM by eliminating the variable “now”. But setting now = millis() after the 1’st tap and calculating the intervals by subtracting now - StartTime and then resetting StartTime = now should also work. One potential gotcha in both codings is the possibility of a rollover of millis() during the tap recording. I suspect you won’t ever have the Arduino running long enough for this to be a concern but there you go.

The two topic are now merged together here. If some things look a little out of order, that’s the reason.

-Bill

deleted … I found a switch bounce bug I need to solve.

OK, I think I fixed a bug I found earlier and also took the opportunity to make it more user friendly. Right now if it’s in playback mode but you haven’t got any recorded data, the servo won’t be commanded to move to potentially junk positions. Instead it’ll wait for you, the user, to go to record mode and record data. When you flip the switch to go to record mode, the onboard LED will come on to show it’s in record more. The LED will stay on except for 3 conditions;

  • You flip the switch to go back to playback mode, with or w/o any data recorded

  • It’s reached it’s user specified limit on the number of inter-tap intervals to be recorded. The unit stays in record mode (until you flip the switch) but it won’t record any more and the LED is out.

  • The LED will blink off for a short time each time a tap is detected.

If you have recorded tap data and are in playback mode and decide to go to record mode again, that prior data does not get erased until the 1’st tap is detected. This way you can change your mind and go back to playback and retain the old data. But if you tap once, the old data is gone ! You will no doubt need to tweak the TapThresh constant to get a good value that doesn’t detect non-taps but always detects good taps. If you find odd things occasionally happening when you flip the record/playback switch, you might need to increase the debounce delay constant. I’m expecting that switch to be a 2 position switch, with one position shorting pin 2 to ground to get you into playback mode. The other position should connect pin 2 to a pull-up resistor, with the other end of that resistor tied to Vcc (5V). I didn’t know what version of Arduino you have I didn’t enable the internal pull-up. That’s something you can add.

So see if this works for you and if you have any questions about why something is the way it is ask. No doubt a good code writer could do this better but there you go.

#include <Servo.h>

Servo servo1;                    // create first servo object to control first servo

// declare the constants
const int FSR = 0;               // FSR on pin 0
const int programSwitch = 2;     // Record playback switch on pin 2
const int servoPin = 6;          // servo is on pin 6
const int LEDpin = 13;           // use onboard LED on pin 13
const int MaxNumIntervals = 20;  // the max number of intervals to be recorded
const int Tapthresh = 511;       // threshold for FSR tap detection
const int strikePos = 170;       // servo command for strike position
const int retractPos = 0;        // servo command for retract position
const unsigned long strikeTime = 100;      // time, in msec, btw the servo striking and retracting
const unsigned long dbDelay = 150;         // debounce wait time in msecs
const unsigned long minTapInterval = 100;  // min time between taps in msecs

// declare the variables
int TapCount = 0;                // Incrementer for the array
int TapCntCopy = 0;              // Copy of tap count
int mode = 0;                    // mode is record (1) or playback (0)
unsigned long TapTime=millis();  // Reference for when this tap started.
unsigned long tapReadings[MaxNumIntervals]; // set aside memory for interval times

void setup()
{
  pinMode(programSwitch, INPUT); // define record playback pin as an input
  pinMode(LEDpin, OUTPUT);       // define LED pin as an output
  digitalWrite(LEDpin, LOW);     // set the LED off
  servo1.attach(servoPin);       // attaches the first servo
  Serial.begin(9600);            // init the serial port to 9600 baud, 8N1
}


void loop()
{
  if(digitalRead(programSwitch)==false)  // initial check of record playback mode switch
  {
    delay(dbDelay);                      // wait a bit and check switch again
    // read sw again, also verify data exists via tap count not = 0
    while((digitalRead(programSwitch)==false) && (TapCount > 0))
    {
      // now in playback mode
      mode = 0; // set mode = playback
      // command the servo to strike and retract using recorded interval times
      // the beat goes on forever or until commanded into record mode
      for (int i=0; i<(TapCount-1); i++)
      {
        servo1.write(strikePos);  // command servo to strike
        delay(strikeTime);        // wait just long enough for servo to get there
        servo1.write(retractPos); // command servo back to zero position
        delay(tapReadings[i]);    // pauses between beats
      }
    }
  }
  else
  {
    // now in record mode
    mode = 1;
    digitalWrite(LEDpin, HIGH);
    Serial.println("Start tapping");
    // zero out tap count but leave other data intact until 1'st tap is detected
    TapCount = 0;
    // now run the tap detection routine over and over and oever
    while(mode == 1) //now stuck in loop below until mode changes to 0
    {
      if(TapCount <= MaxNumIntervals)
      {
        if(analogRead(FSR) > Tapthresh)
        {
          // a tap has been detected !
          digitalWrite(LEDpin, LOW);  // blink LED off to show tap detected
          if(TapCount == 0) // 1st tap detected
          {
            TapTime = millis();
            Serial.println("Detected 1'st tap");
            
            //now reset the entire possible listening array
            for (int i=0; i<MaxNumIntervals; i++)
            {
              tapReadings[i]=0;
            }
            TapCntCopy = 0;  // also reset the count copy
          }
          else
          {
            // record interval btw this tap and prior tap
            tapReadings[TapCount-1] = int(millis() - TapTime);
            TapTime = millis();
            //send interval count to PC
            Serial.print("Recorded interval #   ");
            Serial.println(TapCount);
          }
          TapCount++;   // tap count = 21 after 20 intervals
          TapCntCopy = TapCount; // make a copy for restore if needed 
          
          // now wait for tap to be released, FSR to go back to normal
          delay(minTapInterval);
          digitalWrite(LEDpin, HIGH); // turn LED back on
        }
      }
      else
      {
        //have recorded max number of intervals
        digitalWrite(LEDpin, LOW); //tell user all done recording
        Serial.println("Recorded max number of taps");
      }
      if(digitalRead(programSwitch)==false) //read switch to see if user commands playback mode
      {
        mode = 0; //go to playback mode
        digitalWrite(LEDpin, LOW); //tell user all done recording
        if(TapCount == 0) // user has decided to keep prior data
        {
          TapCount = TapCntCopy;  // restore tap count to prior value
        }
        Serial.println("Finished recording tap data");
      }
    }
  }
}

Thanks mee-n-mac. Been a bit busy at work so haven’t got around to this but will study it in the next couple days.

shakamuni01:
Thanks mee-n-mac. Been a bit busy at work so haven’t got around to this but will study it in the next couple days.

No problem. As it happens I dug out my Arduino and semi-tested the code I posted. I say semi because I don't have the FSR I think you're using and I didn't have a servo handy but, with some mods to that code to account for those differences, I did see the code record and playback my taps (button pushes). So I have high hopes that it'll work for you. It might need some tweaks to get the taps detected and will certainly need tweaking to get any servo motion perfect, but the code should basically be good.

One thing that does need changing is this line.

pinMode(programSwitch, INPUT); // define record playback pin as an input

It should be.

pinMode(programSwitch, INPUT_PULLUP); // define record playback pin as an input