Multi Tasking with Button Press

Hello There,

Newbie/Non-programmer - Please Be Gentle :slight_smile:

So I have two Push Buttons that help me go up/down in a switch case schema (see code below). I also have a small vibration motor I’m driving, and the idea is to use the buttons to switch between 4 different vibration patterns. Here’s the issue:

One of the vibration patterns is a simple for loop where I PWM the energy to the motor from 130 to 255. The thing is, I am NOT able to push either of the buttons to switch out of this case. In other words, I have to wait for the exact moment that the for loop finishes at 255 - when the program returns from the motor sub routine - to push the button.

Any idea how I can avoid this? That while the for loop is running, I can interrupt the loop and pay attention to the button press (preferably without using a physical interrupt)?

/*
 * Push ear buttons to change states
 * Each state has a different vibration
 */


int mPin = 6;     // Motor Pin

int inPin = 7;    // input pin for PBA
int inPin2 = 8;   // input pin for PBB
int val = 0;      // variable for reading PBA
int val2 = 0;     // variable for reading PBB

int xCount = 0;   // variable for State Machine


void setup() {

  pinMode(inPin, INPUT);    // declare pushbutton as input
  pinMode(inPin2, INPUT);   // declare 2nd PB as input
  digitalWrite(inPin, HIGH);  // PBA High by default
  digitalWrite(inPin2, HIGH);  // PBB High by default

  
  Serial.begin(9600);      // start the Serial monitor 

}


void loop() {


  val = digitalRead(inPin);  // read input value
  val2 = digitalRead(inPin2);  // read input value

  if (val == HIGH) {         // check if the input is HIGH (button pushed)
    // DO NOTHING HERE
  } else if (val == LOW) {
    xCount = xCount + 1;
    // Serial.print("Val1 = ");    // debug xCount
    // Serial.println(xCount);       // debug xCount
  }

  if (val2 == HIGH) {
    // DO NOTHING HERE
  } else if (val2 == LOW) {
    xCount = xCount - 1;
    // Serial.print("Val2 = ");
    // Serial.println(yCount);
  }

  delay(250);                 // slow the PBs down for sensitivity

  //////////////////////
  //  STATE MACHINE   //
  //////////////////////

  switch (xCount) {

      case 0:
        Serial.print("State: ");
        Serial.println(xCount);
        Serial.println("DO NOTHING");
        return;
      case 1:
        Serial.print("State: ");
        Serial.println(xCount);   
        buzz1();
        return;   
      case 2:
        Serial.print("State: ");
        Serial.println(xCount);
        buzz2();
        return;
      case 3:
        Serial.print("State: ");
        Serial.println(xCount);  
        buzz3();
        return;
      case 4:
        Serial.print("State: ");
        Serial.println(xCount);  
        buzz4();
        return;      
            
  }


}



void buzz1(){     // First Motor Sub-Routine
  int thisPin;
  for (thisPin = 130; thisPin < 256; thisPin++){
      analogWrite(mPin, thisPin);   // turn the LED on (HIGH is the voltage level)
      Serial.println(thisPin);      // DEBUG
      delay(mOn);              // wait for a second 
  }

}

void buzz2(){     // Second Motor Sub-Routine

  digitalWrite(mPin, HIGH);   // turn motor On
  delay(1000);
  digitalWrite(mPin, LOW);    // turn motor Off
  delay(1000);
  
}

void buzz3(){     // Third Motor Sub-Routine

  digitalWrite(mPin, HIGH);   // turn motor On
  delay(50);
  digitalWrite(mPin, LOW);    // turn motor Off
  delay(50);
}


void buzz4(){     // Third Motor Sub-Routine

  digitalWrite(mPin, HIGH);   // turn motor On
  delay(250);
  digitalWrite(mPin, LOW);    // turn motor Off
  delay(1000);
}

Thank you,
RoboFred

Any idea how I can avoid this?

You need to look into using millis() for timing as in the BlinkWithoutDelay example and Several things at the same time
Save the time an event happens then each time through loop() check whether the required period has elapsed since the event. If not then go round loop() again reading inputs etc. If the period has elapsed then take the required action.