Help with programming 1 action after 2 digitalWrites with millis()

Hi,
I am trying to make a circuit that basically includes 2 pushbuttons and makes the following:
When I press the first button, the arduino starts counting in miliseconds.
If I press the second button within a specific, pre-written number of seconds (let's say 5), the arduino counts and prints the number of correct presses on the serial monitor.
If I didn't press the second button within 5 seconds, the arduino will stop counting and delete the counted time (very important)
I was hoping you could help me with this, I am really struggling :stuck_out_tongue:
Thanks!

gfh_gfh1:
When I press the first button, the arduino starts counting in miliseconds.

Using the concepts of the StateChangeDetection example, you can set a variable to millis().

If I press the second button within a specific, pre-written number of seconds (let's say 5), the arduino counts and prints the number of correct presses on the serial monitor.

Again with the same state change concepts, you can determine the amount time time between switch presses by subtracting the time you saved earlier by the current value of millis().

At this point, you can determine whether it's less than 5 seconds or greater than, and perform your action based on that.

Hi,
Thanks for your help,
I tried what you said and connected an LCD to display the number of countings,
Unfortunately it doesn’t work…
Can you help me?
Here is the code:

#include <LiquidCrystal.h>
long previousMillis = 0;
long interval = 1000;
const int button1Pin = 23;
const int button2Pin = 24;
int button1State = 0;
int button2State = 0; // current state of the button
int lastButton1State = 0;
int lastButton2State = 0;
int Counter = 0;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup(){
pinMode(button1Pin, INPUT);
pinMode(button2Pin, INPUT);
lcd.begin(16,1);
}

void loop(){
button1State = digitalRead(button1Pin);
button2State = digitalRead(button2Pin);

if (button1State != lastButton1State) {
if(button1State == HIGH){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis < interval && button2State == HIGH) {
Counter++;
}
}
}
lcd.setCursor(0, 0);
lcd.print("Count: ");
lcd.print(Counter);
}

First off, use code tags when posting code.

Now let’s look at your code:

long previousMillis = 0;
...
void loop(){
...
        if(currentMillis - previousMillis < interval && button2State == HIGH) {
          Counter++;
        }
...

You’re never setting previousMillis aside from it’s initialization to 0, so subtracting zero from currentMillis is pointless; certainly not what you intended.

if (button1State != lastButton1State) {
      if(button1State == HIGH){
        ...
        if(currentMillis - previousMillis < interval && button2State == HIGH) {

button1 and button2 should be independent from each other. Different actions should be taken for each transition separately from another. As you have it written now, Counter will only be incremented when button1 is pushed down while button 2 is pushed down, which certainly isn’t what you’re trying to do.

You need to scale it back and get a little bit of it working at a time. Start by getting switch 1 to simple print “Switch 1 pressed down1” whenever it’s pressed down. Then, get switch 2 to do the same. Again, they should work INDEPENDENTLY from each other.

You’re also missing a key line from the StateChangeDetection example in which lastButton1State is updated. Whenever you have a variable that is used in some calculation (like lastButton1State and previousMillis) somewhere in your code but never updated, ask yourself if it makes sense to make those variables constant. Often times that is not the case, unless they are pin number (which rarely change during runtime).

gfh_gfh1:
Can you help me?

Try this (untested):

#include <LiquidCrystal.h>
unsigned long startTime;
unsigned long interval = 1000;
boolean button1Pressed = false;
const int  button1Pin = 23;
const int  button2Pin = 24;
int Counter = 0;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup(){
  pinMode(button1Pin, INPUT);
  pinMode(button2Pin, INPUT);
  lcd.begin(16,1);
}

void loop(){
  if(button1Pressed == false && digitalRead(button1Pin)==HIGH){ 
       // if this is the first time button1 has been pressed
      startTime = millis();
      button1Pressed = true; 
         // next time round the loop startTime won't be reset
      }
   if(button1Pressed == true && digitalRead(button2Pin) == HIGH){
            //do nothing until button2 pressed
      if(millis() - startTime < interval) {  //button2 pressed in time
          Counter++;
          button1Pressed = false;  //reset for next time
          }
      else{ //button2 pressed outside time
          Counter = 0;
          button1Pressed = false;  //reset for next time
          }
     }
  lcd.setCursor(0, 0);  //this will happen each time round the loop
  lcd.print("Count: ");  //you may, therefore, want to move these lcd 
  lcd.print(Counter); //instructions above the last curly brace, to only 
      //print when button2 has been pressed and counter has been updated
}

Henry_Best:

gfh_gfh1:
Can you help me?

Try this (untested):

#include <LiquidCrystal.h>

unsigned long startTime;
unsigned long interval = 1000;
boolean button1Pressed = false;
const int  button1Pin = 23;
const int  button2Pin = 24;
int Counter = 0;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup(){
  pinMode(button1Pin, INPUT);
  pinMode(button2Pin, INPUT);
  lcd.begin(16,1);
}

void loop(){
  if(button1Pressed == false && digitalRead(button1Pin)==HIGH){
       // if this is the first time button1 has been pressed
      startTime = millis();
      button1Pressed = true;
         // next time round the loop startTime won’t be reset
      }
   if(button1Pressed == true && digitalRead(button2Pin) == HIGH){
            //do nothing until button2 pressed
      if(millis() - startTime < interval) {  //button2 pressed in time
          Counter++;
          button1Pressed = false;  //reset for next time
          }
      else{ //button2 pressed outside time
          Counter = 0;
          button1Pressed = false;  //reset for next time
          }
     }
  lcd.setCursor(0, 0);  //this will happen each time round the loop
  lcd.print("Count: ");  //you may, therefore, want to move these lcd
  lcd.print(Counter); //instructions above the last curly brace, to only
      //print when button2 has been pressed and counter has been updated
}

Thank you!! works great, but if I press the buttons too quick the number of counts increases in dozens…why is that?
Thanks

gfh_gfh1:

Henry_Best:

gfh_gfh1:
Can you help me?

Try this (untested):

#include <LiquidCrystal.h>

unsigned long startTime;
unsigned long interval = 1000;
boolean button1Pressed = false;
const int  button1Pin = 23;
const int  button2Pin = 24;
int Counter = 0;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup(){
  pinMode(button1Pin, INPUT);
  pinMode(button2Pin, INPUT);
  lcd.begin(16,1);
}

void loop(){
  if(button1Pressed == false && digitalRead(button1Pin)==HIGH){
       // if this is the first time button1 has been pressed
      startTime = millis();
      button1Pressed = true;
         // next time round the loop startTime won’t be reset
      }
   if(button1Pressed == true && digitalRead(button2Pin) == HIGH){
            //do nothing until button2 pressed
      if(millis() - startTime < interval) {  //button2 pressed in time
          Counter++;
          button1Pressed = false;  //reset for next time
          }
      else{ //button2 pressed outside time
          Counter = 0;
          button1Pressed = false;  //reset for next time
          }
     }
  lcd.setCursor(0, 0);  //this will happen each time round the loop
  lcd.print("Count: ");  //you may, therefore, want to move these lcd
  lcd.print(Counter); //instructions above the last curly brace, to only
      //print when button2 has been pressed and counter has been updated
}

Thank you!! works great, but if I press the buttons too quick the number of counts increases in dozens…why is that?
Thanks

You aren’t debouncing your input and every time your loop runs, it will detect.
Try adding a delay(100) or delay(200) to the end of the loop. Or a better way is to encapsulate all of your code in the loop into something like:

if(millis()%100 == 0){
... //All of your loop code
}

Which will only let the code execute once every 100ms.
You can also Try: http://playground.arduino.cc/Code/Debounce for your inputs.