Tap-time sequencer

Hello Guys

I'm new with arduino and i have no experience with programming C++.
I have a few problems with my new project.

I want to make a tap-time sequencer.
If i push the first button on input 1 the arduino have to put output 1 high and starts counting the time till i push the button again and then he send signals to output 1 again and over again with the time he had counted as sequence.

I have also a Second button on input 2 that stops the output signals but the time stay the same en starts again when i push the first button 1 time.

And last but not least there is a third button on input 3 that stops sending output signals and release the time thats recorded

I hope somebody can help me with my project because i'm stuck on it.

Kind regards
Lustige_Leon

i'm stuck on it

What class is this for?

What have you done so far?
.

"push the button again and then he send signals to output 1 again and over again with the time he had counted as sequence."

Do you mean toggle a led like in the blink with out delay example?

Thank you for the reply.

At this moment i have just the basic things. As i said before i never pade an arduino project before.

You know how an audio tap delay works? I tap the button a few times on the beat of the music. Then the arduino has to count the time between 2 taps en then he sends the the beat to the output with a LED and it blinks On the beat just as i tapped. And everytime i change the beat with a few taps On the button, the arduino has to change the blinking speed of the LED.

Thank you
Leander

At this moment i have just the basic things. As i said before i never pade an arduino project before.

We are happy to help but won't do the work for you.
When you run into a problem ask for a solution or explanation.

At this point, you must have some software you have written show it to us.

ok so lets see what we can do to help you.

first you need to open the program and look at examples, digital, blink with out delay.

The you need to look at the top of this page. Follow learning, refrences

you will need to read "if" "switch" "digitial read" "digital write"

Now lets look at the problem. Most of the code is going to be based around button1 as that's the most complicated.

Button1 has 3 different uses

1/ record start time
2/ record stop time
3/ start program / restart program

so we need 4 states (3 states that do something and a state that does nothing on boot-up)

so lets start with a simple button read

 if (buttonState1 != prevButtonState1 && buttonState1 == LOW) {
    buttonUse++;
}
 prevButtonState1 = buttonState1;

ok the above code says if button state does not equal prevButtonState1 and button is low add one to a counter we have called buttonUse.

You may be wondering why we are saying when button is low. If you read digital read input_pullup you will understand that the button is wired between the input pin and dc ground rail.

So when I press button1 the state will be low. The if will be satisfied because prevButtonState1 will not equal the same as buttonstate. The button use will change from 0 to 1. The next line will make prevButtonState1 = buttonState1 so when the program loop the if will fail and nothing more will be added to buttonuse.

when I release the button the if will fail as buttonState1 will now be high.

next press the if will be satisfied and another 1 will be added to button use so it will change from 1 to 2

continued on next post

ok so we have a counter based on pushbutton1. we know there are 3 states so we now need to restrict the states to a max of 3 (4 really but state 0 does nothing)

if (buttonUse >= 3) {
      buttonUse = 3;
    }

added to the first code we get

if (buttonState1 != prevButtonState1 && buttonState1 == LOW) {
    buttonUse++;
    if (buttonUse >= 3) {
      buttonUse = 3;
    }

once buttonUse=3 it will stay at 3 (this will be my start / reset state) I need to stay at 3 due to the logic of button 2 stops the blinking but button one restarts it.

if you have read about switchs you will understand the next part

 if (buttonState1 != prevButtonState1 && buttonState1 == LOW) {
    buttonUse++;
    if (buttonUse >= 3) {
      buttonUse = 3;
    }

    switch (buttonUse) {
      case 0:
        break;
      case 1:
        if (oneTime1 == 0) {
          startTime = millis();
          oneTime1 = 1;
        }
        break;
      case 2:
        if (oneTime2 == 0) {
          stopTime = millis();
          oneTime2 = 1;
        }
        break;
      case 3:
        pause = 0;
        break;
    }
  }
  prevButtonState1 = buttonState1;

when buttonUse equals

0/ do nothing except exit as this a place to start
1/ record the start time by recording what millis is when you press the button
use a flag called onetime1 to only do this action once
2/ record the stop time by recording what millis is when you press the button
use a flag called onetime2 to only do this action once
3/ set a flag called pause to 0

continued on next post

now its time to work out how long between the button presses

if (stopTime != 0 && stopTime != 0) {
interval = stopTime - startTime;
}

millis is only zero during boot-up so to stop interval being calculated before we have both start and stop we are using a simple if.

If start and stop not equal zero (neither equals 0) then do the calculation to work out what interval is

next we are going to cut and paste code from blink with out delay. I added the extra flag pause on to this code.
If the flag is set to 1 then the blink with out delay code will not be executed (the led will not blink)
If the flag is set to 0 then the blink with out delay code will not be executed (the led will blink at the timing entered by interval)

unsigned long currentMillis = millis();
 if (pause == 0) {
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;

      if (ledState == LOW)
      {
        ledState = HIGH;
      }
      else
      {
        ledState = LOW;
      }
    }
  } else {
    ledState = LOW;
  }

you will have to add this line to make it blink

 digitalWrite(ledPin, ledState);

so that's button one taken care off

now for button two

we want it to pause the code but not to reset interval. we already have the flag to start the code so to pause the code we set pause to 1

 if (buttonState2 == LOW) {
    ledState = LOW;
    pause = 1;
  }

you will notice we only look at button2 if its pressed (low) and we don't need to remember we pushed it

ledState = LOW was added as we have no idea what state the ledState will be in when we stop the bwod code so we are just saying turn the led off when paused

button 3 we want to pause the bwod code then reset all the flags to 0. we also need to clear the timestamps (start/stop) and interval. Last but not least we need to reset buttonUse to zero (same place it starts at after a reboot)

 if (buttonState3 == LOW) {
    pause = 1;
    buttonUse = 0;
    interval = 0;
    startTime = 0;
    stopTime = 0;
    oneTime1 = 0;
    oneTime2 = 0;
  }

so that's the basic code. Its not pretty as I wrote something you should understand.

I will give you the globals to help you get started

const byte ledPin =  13;//led onboard
const byte button1 = 10;//pin number input 1
const byte button2 = 9;//pin number input 2
const byte button3 = 8;//pin number input 3
byte pause = 1;
byte ledState = 0;
unsigned long  previousMillis = 0;
unsigned long startTime;
unsigned long  stopTime;
unsigned long  interval;
byte buttonUse = 0;
byte prevButtonState1 = 0;
byte oneTime1 = 0;
byte oneTime2 = 0;

you will have to do the setup of the pins

  pinMode (ledPin, OUTPUT);
  pinMode (button1, INPUT_PULLUP);//set as a pullup
  pinMode (button2, INPUT_PULLUP);
  pinMode (button3, INPUT_PULLUP);

and add this code to read the button presses in the main loop

byte buttonState1 = digitalRead (button1);//read the button
  byte buttonState2 = digitalRead (button2);
  byte buttonState3 = digitalRead (button3);

Hi gpop1

Thank you very much for the whole explanation.
I made something with al your information.
Can you check if it's OK?

const byte ledPin =  13;//led onboard
const byte button1 = 10;//pin number input 1
const byte button2 = 9;//pin number input 2
const byte button3 = 8;//pin number input 3
byte pause = 1;
byte ledState = 0;
unsigned long  previousMillis = 0;
unsigned long startTime;
unsigned long  stopTime;
unsigned long  interval;
byte buttonUse = 0;
byte prevButtonState1 = 0;
byte oneTime1 = 0;
byte oneTime2 = 0;

void setup() {
  
  pinMode (ledPin, OUTPUT);
  pinMode (button1, INPUT_PULLUP);
  pinMode (button2, INPUT_PULLUP);
  pinMode (button3, INPUT_PULLUP);
  
}

void loop() {

  byte buttonState1 = digitalRead (button1);
  byte buttonState2 = digitalRead (button2);
  byte buttonState3 = digitalRead (button3);

if (buttonState1 != prevButtonState1 && buttonState1 == LOW) {
    buttonUse++;
    if (buttonUse >= 3) {
      buttonUse = 3;
    }

    switch (buttonUse) {
      case 0:
        break;
      case 1:
        if (oneTime1 == 0) {
          startTime = millis();
          oneTime1 = 1;
        }
        break;
      case 2:
        if (oneTime2 == 0) {
          stopTime = millis();
          oneTime2 = 1;
        }
        break;
      case 3:
        pause = 0;
        break;
    }
  }
  prevButtonState1 = buttonState1;

unsigned long currentMillis = millis();
 if (pause == 0) {
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;

      if (ledState == LOW)
      {
        ledState = HIGH;
      }
      else
      {
        ledState = LOW;
      }
    }
  } else {
    ledState = LOW;
  }

digitalWrite(ledPin, ledState);

if (buttonState2 == LOW) {
    ledState = LOW;
    pause = 1;
  }

if (buttonState3 == LOW) {
    pause = 1;
    buttonUse = 0;
    interval = 0;
    startTime = 0;
    stopTime = 0;
    oneTime1 = 0;
    oneTime2 = 0;
}

}

Thanks in advance

Kind regards
Lustige_Leon

you reassembled 95% of the code.
The question is do you understand how it works or did you just cut and paste and hoped it worked.

add these lines in the open loop and see if you can spot the error

  Serial.print("start ");
  Serial.print(startTime);
  Serial.print(" stop ");
  Serial.print(stopTime);
  Serial.print(" interval ");
  Serial.println(interval);

also add this line to setup

 Serial.begin(9600);

if you don't know how to use serial monitor google it.

I understand the basic part of the code but i'm working on it everyday.
I know how to use the serial monitor, I'm gonna check it out tonight.
Are there a lot of problems in the code or should it work like this?

Thanks in advance
Lustige_Leon

Hi gpop1

I made my project on the arduino test board.
On the serial monitor i get this:

start 0 stop 0 interval 0
start 0 stop 0 interval 0
start 0 stop 0 interval 0
start 0 stop 0 interval 0
start 0 stop 0 interval 0
start 0 stop 0 interval 0

This was the code i used.

const byte ledPin =  13;//led onboard
const byte button1 = 10;//pin number input 1
const byte button2 = 9;//pin number input 2
const byte button3 = 8;//pin number input 3
byte pause = 1;
byte ledState = 0;
unsigned long  previousMillis = 0;
unsigned long startTime;
unsigned long  stopTime;
unsigned long  interval;
byte buttonUse = 0;
byte prevButtonState1 = 0;
byte oneTime1 = 0;
byte oneTime2 = 0;

void setup() {

  Serial.begin(9600);
  
  pinMode (ledPin, OUTPUT);
  pinMode (button1, INPUT_PULLUP);
  pinMode (button2, INPUT_PULLUP);
  pinMode (button3, INPUT_PULLUP);
  
}

void loop() {

  Serial.print("start ");
  Serial.print(startTime);
  Serial.print(" stop ");
  Serial.print(stopTime);
  Serial.print(" interval ");
  Serial.println(interval);

  byte buttonState1 = digitalRead (button1);
  byte buttonState2 = digitalRead (button2);
  byte buttonState3 = digitalRead (button3);

if (buttonState1 != prevButtonState1 && buttonState1 == LOW) {
    buttonUse++;
    if (buttonUse >= 3) {
      buttonUse = 3;
    }

    switch (buttonUse) {
      case 0:
        break;
      case 1:
        if (oneTime1 == 0) {
          startTime = millis();
          oneTime1 = 1;
        }
        break;
      case 2:
        if (oneTime2 == 0) {
          stopTime = millis();
          oneTime2 = 1;
        }
        break;
      case 3:
        pause = 0;
        break;
    }
  }
  prevButtonState1 = buttonState1;

unsigned long currentMillis = millis();
 if (pause == 0) {
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;

      if (ledState == LOW)
      {
        ledState = HIGH;
      }
      else
      {
        ledState = LOW;
      }
    }
  } else {
    ledState = LOW;
  }

digitalWrite(ledPin, ledState);

if (buttonState2 == LOW) {
    ledState = LOW;
    pause = 1;
  }

if (buttonState3 == LOW) {
    pause = 1;
    buttonUse = 0;
    interval = 0;
    startTime = 0;
    stopTime = 0;
    oneTime1 = 0;
    oneTime2 = 0;
}

}

Can you help me further?
Because i can't find what's wrong.

Many thanks in advance
Lustige Leon

you forgot the part that calculates interval.

posted code is something I was playing with using the logic you posted

press 1 to set start time
press 1 to set stop time
press 1 to flash the led at the rate between start and stop
press 2 and flashing will stop
press 1 and flashing will restart at the same rate
press 3 and flashing will stop and timer will be reset.(back to beginning).

const int ledPin =  13;
const int button1 = 10;
const int button2 = 9;
const int button3 = 8;
byte pause = 1;
byte ledState = 0;
unsigned long  previousMillis = 0;
unsigned long  bounce = 0;
unsigned long startTime;
unsigned long  stopTime;
unsigned long  interval;
byte buttonUse = 0;
byte prevButtonState1 = 0;
byte oneTime1 = 0;
byte oneTime2 = 0;


void setup() {
  // Serial.begin(9600);
  pinMode (ledPin, OUTPUT);
  pinMode (button1, INPUT_PULLUP);
  pinMode (button2, INPUT_PULLUP);
  pinMode (button3, INPUT_PULLUP);
}
void loop() {

  unsigned long currentMillis = millis();
  byte buttonState1 = digitalRead (button1);
  byte buttonState2 = digitalRead (button2);
  byte buttonState3 = digitalRead (button3);



  if ((buttonState1 == LOW) && (currentMillis - bounce >= 25)) {
    if (buttonState1 != prevButtonState1) {
      buttonUse++;

      buttonUse = constrain(buttonUse, 0, 3);

      switch (buttonUse) {
        case 0:
          break;
        case 1:
          if (oneTime1 == 0) {
            startTime = millis();
            oneTime1 = 1;
          }
          break;
        case 2:
          if (oneTime2 == 0) {
            stopTime = millis();
            oneTime2 = 1;
          }
          break;
        case 3:
          pause = 0;
          break;
      }
    } else {
      bounce = currentMillis;
    }
  }
  prevButtonState1 = buttonState1;

  if (buttonState2 == LOW) {
    pause = 1;
  }

  if (buttonState3 == LOW) {
    pause = 1;
    buttonUse = 0;
    interval = 0;
    startTime = 0;
    stopTime = 0;
    oneTime1 = 0;
    oneTime2 = 0;
  }


  if (stopTime != 0 && stopTime != 0) {
    interval = stopTime - startTime;
  }
  //Serial.print("start ");
  // Serial.print(startTime);
  // Serial.print(" stop ");
  // Serial.print(stopTime);
  // Serial.print(" interval ");
  // Serial.println(interval);



  if (pause == 0) {
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      ledState = !ledState;
    }
  } else {
    ledState = LOW;
  }
  
 digitalWrite(ledPin, ledState);

}

Hi gpop1,

The code you last posted, should it work?
I don't know how to calculate the interval.
Can you help me to find the last code i need?

Many thanks in advance!
Lustige Leon

Lustige_Leon:
Hi gpop1,

The code you last posted, should it work?
I don't know how to calculate the interval.
Can you help me to find the last code i need?

Many thanks in advance!
Lustige Leon

beginning of post 7 shows how to calculate the interval and explains how and why. The code in post 12 works

I tested the code on my test board and it doesn't work.

Lustige_Leon:
I tested the code on my test board and it doesn't work.

so what would you like me to do about it?

do I know what type of board, how you wired it or how you copyed the code. Guess you are going to have learn how to code so you can figure out why its not working.

Hi gpop1

I can't find the problem in the code.
Is it possible to help me to find out the problem or give me the working code without faults.

The board is a arduino uno with an arduino starter kit. The wiring is working perfect i already tested it with basic codes like space-invader that's explained in the arduino book in the starter kit.

Many thanks in advance!
Lustige Leon

so the buttons are wired from the negative to one side of the button and the other side of the button is wired to the input pin number.

There is no fault with the code posted in reply #12. Sounds like you didn't follow the instructions and read about INPUT_PULLUP
or you have wired it incorrectly.

Hi gpop1

I found the wiring problem and now the project is working. What's the difference between een normal button and a pullup button?
The stop and release button works perfect as it should.
The start button has a few problems. When i push the first time On the button nothing happens normally every time i push button 1 the led has to go On. Also when de led is blinking i can't change the blinking time by tapping button 1, every time i tap 2 times On button 1 he has to recount the blinking time to the same time between the 2 last taps.
At this moment i can also change the time the led in On. Thats not what i need. When i push the button the led is On, when i leave the button the led is Off.

Do you know how to fix it?

Many thanks in advance
Lustige_Leon