Help on a Do-While with OR function

Hello, I’m working with an analog joystick (well for this part of the code, using a tactile switch is the same), and I wanted to use it like “reading a digital input to set a password to access different type of patterns” (ie: i press 3 times the button of the joystick and say “Hello world”, if I press it 2 times turn on a led).

I’m not using analog input (X & Y coordinates to keep the code simple).

What I would like to do is:

  1. recording the times (that the button was pressed). The maximum times that the button can be pressed is 3 times.

  2. Set a timer of 5 seconds, where if the button is not pressed in these 5 seconds, it will store the password (eg the button was pressed 1 time). I used a variable (eventInterval) to create a gap with a millis function (currentTime). When eventInterval-currentTime <0 it should go out the DO-While (but it’s not happening).

So i need a Do-While with two ways to end: the first one with the button that has reached 3 times (the maximum value). The second one of ending this loop is that we do nothing in the last 5 seconds.

Every time the button is pressed the timer go to zero.

I used INPUT_PULLUP that has got a default with HIGH voltage and then changed to zero =!
I wrote the code in void setup because the password has to be entered one time

This below is the code:

#define JOYSTICK_X A1
#define JOYSTICK_Y A0
#define JOYSTICK_BUTTON 2


//variables for storing Pattern codes//
int buttoncount = 0;
int fin = 0;

//time variables
unsigned long eventInterval = 5000;
unsigned long previousTime = 0;
unsigned long gap = 0;



void setup() {
   Serial.begin(9600);
   pinMode(JOYSTICK_BUTTON, INPUT_PULLUP);

  
      
      do  {

      Serial.println("press the button");
      delay(1000);
      int button =! digitalRead(JOYSTICK_BUTTON);   //reading the value of the button
   
      Serial.println(button);
      
      
           
        unsigned long currentTime = millis(); // start counting
 
            if (button > 0) {      
            Serial.println("button PRESSED");             
            buttoncount = 1 + buttoncount;
            Serial.println("buttoncount");
            Serial.println(buttoncount);
            delay(1000);
            eventInterval = eventInterval + 2000;  //We push further the time interval, so that the "gap" condition(5 seconds= can't end the Do-While loop.
             
            } //press the button max 3 times//
        
            else {
            Serial.print("currentTime: ");
            Serial.println(currentTime);
            Serial.print("eventInterval - currentTime:  ");
            Serial.println(eventInterval - currentTime);
            Serial.println("");
            gap = eventInterval - currentTime;      //it gives me back a giant number
            Serial.println(gap);
        
        
          if(gap<=0 || gap>10000) {    //create a criteria for ending the while loop (when 5 seconds passed and button wasn't pressed anytime)//
            fin = 1;                    // so I can end do while// it is giving me back 4295487299 number so I setted gap<=0 || gap>10000
            Serial.println("we are inside if fin statement");
          }
            }
       
     }while (buttoncount<=3 || fin==1);//do while
        
        
}; //void setup
        
    




void loop ()  {
  Serial.println("Hello");
}

I’m stuck in this right now:

  1. The code “enters” all the if statement as you can see with the serial monitor, but i really don’t know why it can’t go out the Do-While loop, and performing void loop().

  2. When eventInterval-currentTime<0 it gives back a huge number.

PS: if you do not have a joystick you can simply apply a tactile switch to pin 2

How can I go forward with this project?
Thank You

I didn’t have much time to look at this but the code below compiles and should get you out of the loop if no buttons are pressed.

#define JOYSTICK_X A1
#define JOYSTICK_Y A0
#define JOYSTICK_BUTTON 2


//variables for storing Pattern codes//
int buttoncount = 0;

//time variables
unsigned long eventInterval = 5000;
unsigned long startTime = 0;

void setup() {
  unsigned long currentTime;
  Serial.begin(9600);
  pinMode(JOYSTICK_BUTTON, INPUT_PULLUP);

  startTime = millis();

  do  {

    Serial.println("press the button");
    delay(1000);
    int button = ! digitalRead(JOYSTICK_BUTTON);  //reading the value of the button

    Serial.println(button);

    currentTime = millis(); // start counting

    if (button) {
      Serial.println("button PRESSED");
      buttoncount = 1 + buttoncount;
      Serial.println("buttoncount");
      Serial.println(buttoncount);
      delay(1000);
      eventInterval = eventInterval + 2000;  //We push further the time interval, so that the "gap" condition(5 seconds= can't end the Do-While loop.

    } //press the button max 3 times//

    else {
      Serial.print("currentTime: ");
      Serial.println(currentTime);
      Serial.println("");

      if (currentTime - startTime >= eventInterval) { //create a criteria for ending the while loop (when 5 seconds passed and button wasn't pressed anytime)//
        break;
      }
    }

  } while (buttoncount <= 3); //do while


}; //void setup


void loop ()  {
  Serial.println("Hello");
}

I would, however, recommend that you not invert the digitalRead from the button and to also put code in to test for a button state change rather just testing the state of the button. That way you don’t have to hold the button down for more than a second to register a button press. Also I don’t know why you tested if (button > 0) rather than just testing if (button).

Add some debugging prints of strategic variables and send them to Serial monitor by Serial.print.
The do - while only have a few important variables….

Also, I forgot to mention one reason your timer would not work is you declared currentTime like this within the do-while loop code block:

unsigned long currentTime = millis(); // start counting

This resulted in currentTime only getting set to the value of millis() ONE time, not every loop iteration.

Here is a version of the code that will detect a button press based on button state change:

#define JOYSTICK_X A1
#define JOYSTICK_Y A0
#define JOYSTICK_BUTTON 2


//variables for storing Pattern codes//
int buttoncount = 0;

//time variables
unsigned long eventInterval = 5000;
unsigned long startTime = 0;

void setup() {
  byte buttonState;
  byte lastButtonState = HIGH;
  unsigned long currentTime;
  
  Serial.begin(9600);
  pinMode(JOYSTICK_BUTTON, INPUT_PULLUP);

  startTime = millis();

  Serial.println("press the button");
  do  {
    buttonState = digitalRead(JOYSTICK_BUTTON);  //reading the value of the button
    currentTime = millis(); // start counting
    if (buttonState == LOW && lastButtonState == HIGH) {
      delay(50); // debounce wait
      Serial.println("button PRESSED");
      buttoncount++;
      Serial.println("buttoncount");
      Serial.println(buttoncount);
      eventInterval = eventInterval + 2000;  //We push further the time interval, so that the "gap" condition(5 seconds= can't end the Do-While loop.

    } //press the button max 3 times//

    else if (currentTime - startTime >= eventInterval) { //create a criteria for ending the while loop (when 5 seconds passed and button wasn't pressed anytime)//
        break;
    }
    lastButtonState = buttonState;
  } while (buttoncount <= 3); //do while


}; //void setup


void loop ()  {
  Serial.println("Hello");
}

Well thank you so much ToddL. I got what you did.

I liked the part where you setted the if with the double condition. When we press the button, the value LOW (because of INPUT_PULLUP) can stay for 2 or more iterations, so to avoid that you set that if the buttonState is different from the previous iteration, it can’t enter the code the code and countint antother buttoncount with buttoncount++.

here’s your code with some comments to make it easier for anyone who will come here.

I also added an automatic reset to 5 seconds everytime the button is pressed,
in this way: eventInterval = currentTime + 5000

#define JOYSTICK_X A1
#define JOYSTICK_Y A0
#define JOYSTICK_BUTTON 2


//variables for storing Pattern codes//
int buttoncount = 0;


//time variables
unsigned long eventInterval = 5000;
unsigned long startTime = 0;

void setup() {
  byte buttonState;
  byte lastButtonState = HIGH;
  unsigned long currentTime;
 
  Serial.begin(9600);
  pinMode(JOYSTICK_BUTTON, INPUT_PULLUP);
  

  startTime = millis();

  Serial.println("press the button");
  do  {
    
    buttonState = digitalRead(JOYSTICK_BUTTON);  //reading the value of the button
    //Serial.print("buttonState starting Do-While:  ");
    //Serial.println(buttonState);
    //Serial.println("");
    currentTime = millis(); // start counting
    if (buttonState == LOW && lastButtonState == HIGH) {
      delay(50); // debounce wait
      Serial.println("button PRESSED");
      buttoncount++;
      Serial.print("buttoncount:  ");
      Serial.println(buttoncount);
      //Serial.println("");
      eventInterval = currentTime + 5000;  //We push further the time interval, so that the "gap" condition(5 seconds= can't end the Do-While loop.
      
      } //press the button max 3 times// we can't put anything between if() and else if()... why?
      
      
    else if (currentTime - startTime >= eventInterval) { //create a criteria for ending the while loop (when 5 seconds passed and button wasn't pressed anytime)//
        break;
    }
      Serial.print("currentTime - startTime:  ");
      Serial.println(currentTime - startTime);
      Serial.println("");
      Serial.print("eventInterval:  ");
      Serial.println(eventInterval);
      Serial.println("");
      Serial.print("Seconds Left to press the Button:");
      Serial.println(eventInterval - currentTime);
    
    lastButtonState = buttonState;
    //Serial.print("lastButtonState:  ");
    //Serial.println(lastButtonState);
    //Serial.println("");
  } while (buttoncount < 3); //do while //we set <3, because if it was <=3 button count would be 4 at his maximum (we don't want this)//


}; //void setup


void loop ()  {
  //Serial.println("Hello");
  Serial.print(buttoncount);
  
}

In the next days i will complete this void setup for the analogRead input for X and Y of the joystick.
Any advice is welcome

I’m going further with my project and I added another Do-While for keep record of the X-coordinates with analogRead function.

What I did here follows this idea:
if the Joystick goes left (X<400) one time, store in a variable called Xsxcount the time it went more left than X<400.
Xsxcount will count how many times Xvalue has gone before X<400.

The code compiles and the new part is doing well (it is going out with Xsxcount and with the 5 second option).

Now the problem is that when the first Do-While ends (the one for keeping record of the Xsxcounts), the code “doesn’t enter” the part of the Do-While of the button.

It seems that when he finishes the Do-While (by reaching Xsxcount =3 or by reaching 5 seconds is the same) he skip directly to the void loop.

Here’s the code:

#define JOYSTICK_X A1
#define JOYSTICK_Y A0
#define JOYSTICK_BUTTON 2
#define GREEN 3
#define BLUE 4
#define RED 5
#define YELLOW 6
#define WHITE 7

//variables for storing Pattern codes (digitalRead)//
int buttoncount = 0;
int Xsxcount = 0;
int Xdxcount = 0;

//variables for storing Pattern code (analogRead)//


//time variables
unsigned long eventInterval1 = 5000;
//unsigned long eventInterval2 = 5000; //this is for Y
unsigned long eventInterval3 = 5000;
unsigned long startTime = 0;


void setup() {
  //setup for keep "State variables"//
  byte buttonState;
  byte lastButtonState = HIGH;

  int X_value;
  int Xsx_condition;
  int last_Xsx_condition = 0 ;

  unsigned long currentTime1;
  //unsigned long currentTime2; //this is for Y
  unsigned long currentTime3;
  
  Serial.begin(9600);
  pinMode(JOYSTICK_BUTTON, INPUT_PULLUP);
  for(int i = 3; i <= 7; i++){
    pinMode(i, OUTPUT);
    }

 startTime = millis();



  
  Serial.println("Enter X combination");  
  do  {
    X_value = analogRead(JOYSTICK_X);  //reading the value of the button
    currentTime1 = millis(); // start counting
    Serial.print("X_value:  ");
    Serial.println(X_value);
    
    Xsx_condition = 0;
      
        if (X_value <400) {
          Xsx_condition = 1;

          Serial.println("we entered if(X_value<400)!");
          delay(1000);
          
          
              if (Xsx_condition == 1 && last_Xsx_condition == 0) {
                delay(50); // debounce wait
                Serial.println("Xsx counted");
                Xsxcount++;
                Serial.println("xsxcount");
                Serial.println(Xsxcount);
                eventInterval1 = currentTime1 + 5000;  //We push further the time interval, so that the "gap" condition(5 seconds= can't end the Do-While loop.
          
                } //Enter X combination max 3 times//
            } 
        else if (currentTime1 - startTime >= eventInterval1) {
          Serial.println("we break;");
          delay(1000);
          break;
          }
      
      last_Xsx_condition = Xsx_condition;

  } while (Xsxcount < 3);





  Serial.println("press the button");

  
  do  {
    buttonState = digitalRead(JOYSTICK_BUTTON);  //reading the value of the button
    currentTime3 = millis(); // start counting
    if (buttonState == LOW && lastButtonState == HIGH) {
      delay(50); // debounce wait
      Serial.println("button PRESSED");
      buttoncount++;
      Serial.println("buttoncount");
      Serial.println(buttoncount);
      eventInterval3 = currentTime3 + 5000;  //We push further the time interval, so that the "gap" condition(5 seconds= can't end the Do-While loop.

    } //press the button max 3 times//

    else if (currentTime3 - startTime >= eventInterval3) { //create a criteria for ending the while loop (when 5 seconds passed and button wasn't pressed anytime)//
        break;
    }
    lastButtonState = buttonState;
  } while (buttoncount < 3); //do while


}; //void setup


void loop ()  {
  //Serial.println("Hello");
  Serial.print("xsxcount: ");
  Serial.println(Xsxcount);

  Serial.print("buttoncount:  ");
  Serial.println(buttoncount);
}

Why is it happening this? Thank You :slight_smile:

The problem is you didn't reset startTime so it did enter the second do-while it just timed out on the first iteration.

Also eventInterval1, eventInterval3, currentTime1, currentTime3 could be combined to just eventInterval and currentTime variables since they are only temporary for loop control within the scope of the setup() function.