Help: programming push button to do multiple functions

Hi guys. I’m trying to program a push button to do multiple functions (specifically for a vibration motor to go from off, vibrating with delays in between (pulsing) and vibrating constantly and cycle from the start.

I have 2 codes right here that I’ve tested. Both are able to get to case 2, but then it is stuck there without being able to change to other cases.

// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  3;      // the number of the LED pin
int stateOfPin = 0;
int oldStateOfPin = 0;

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  digitalWrite(ledPin,LOW);
}

void loop() {
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);
  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == 1) {
    delay(50);
    buttonState=digitalRead(buttonPin);
      if(buttonState==0){
        stateOfPin=oldStateOfPin+1;
      }
  } 
  else {
    delay(100);
  }
  switch(stateOfPin){
    case 1:
      digitalWrite(ledPin,HIGH);
      delay(100);
      digitalWrite(ledPin,LOW);
      delay(100);
      oldStateOfPin = stateOfPin;
      break;
    case 2:
      digitalWrite(ledPin,HIGH);
      oldStateOfPin = stateOfPin;
    default:
      digitalWrite(ledPin,LOW);
      oldStateOfPin=0;
      break;
    }
}

This second code uses Button.h library from Arduino Playground - Button Library
Same problem as Code 1 that it is stuck on case 2, but this seems more stable and button seems to work constantly.

#include <Button.h>

/*
create a Button object at pin 2
connect button between pin 2 and GND
*/
Button button = Button(2,PULLDOWN);

int motorpin = 3;
byte pressCount = 0;

void setup() 
{
    Serial.begin(9600);

    pinMode(motorpin, OUTPUT);  
}

void loop()
{
  if(button.uniquePress())
     pressCount++;

  switch(pressCount)
  {
      case 1:
         // Turn on motor
    digitalWrite(motorpin,HIGH);
         break;
     case 2:
         // Turn on motor (pulsing)
    digitalWrite(motorpin,HIGH);
    delay(2000);
    digitalWrite(motorpin,LOW);
    delay(2000);
         break;
     case 3:
     // Turn off motor
     digitalWrite(motorpin,LOW);
         pressCount = 0;
         break;
   }
}

Appreciate all your inputs

Both are able to get to case 2, but then it is stuck there without being able to change to other cases

  if (buttonState == 1)
  {
    delay(50);
    buttonState = digitalRead(buttonPin);
    if (buttonState == 0)
    {
      stateOfPin = oldStateOfPin + 1;
    }
  }

This is a very unsatisfactory way to determine whether the state of a pin has changed because it depends on precise timing by the user. Take a look at the StateChangeDetection example in the IDE to see how to do it reliably

UKHeliBob:
This is a very unsatisfactory way to determine whether the state of a pin has changed because it depends on precise timing by the user. Take a look at the StateChangeDetection example in the IDE to see how to do it reliably

Hey thanks a lot man. I’ve edited the code to look like this:

// this constant won't change:
const int  buttonPin = 2;    // the pin that the pushbutton is attached to
const int ledPin = 3;       // the pin that the LED is attached to

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup() {
 // initialize the button pin as a input:
 pinMode(buttonPin, INPUT);
 // initialize the LED as an output:
 pinMode(ledPin, OUTPUT);
 // initialize serial communication:
 Serial.begin(9600);
}


void loop() {
 // read the pushbutton input pin:
 buttonState = digitalRead(buttonPin);

 // compare the buttonState to its previous state
 if (buttonState != lastButtonState) {
   // if the state has changed, increment the counter
   if (buttonState == HIGH) {
     // if the current state is HIGH then the button went from off to on:
     buttonPushCounter++;
     Serial.println("on");
     Serial.print("number of button pushes: ");
     Serial.println(buttonPushCounter);
   } else {
     // if the current state is LOW then the button went from on to off:
     Serial.println("off");
   }
   // Delay a little bit to avoid bouncing
   delay(50);
 }
 // save the current state as the last state, for next time through the loop
 lastButtonState = buttonState;


 // turns on the LED every four button pushes by checking the modulo of the
 // button push counter. the modulo function gives you the remainder of the
 // division of two numbers:
 if (buttonPushCounter == 0) {
   digitalWrite(ledPin, 0);
 }
 if (buttonPushCounter == 1) {
   digitalWrite(ledPin, 255);
 }
 else if (buttonPushCounter == 2) {
   digitalWrite(ledPin, 64);
   delay(1000);
   digitalWrite(ledPin, 0);
   delay(1000);
 } 
 else if (buttonPushCounter == 3) {
   digitalWrite(ledPin, 0);
   buttonPushCounter = 0;
    }
 else {
   buttonPushCounter = 0;
 }
 }


 }

Basically it starts from off, press once for mode 1, press twice for mode 2. However, I’m trying to make the 3rd press to return back to ‘off’ state. It does work but I have to press multiple times or hold it, anything I did wrongly here?

The first thing I notice is your use of digitalWrite() with values other than LOW/HIGH. What's with the strange values ? Did you mean to use analogWrite() ?

UKHeliBob:
The first thing I notice is your use of digitalWrite() with values other than LOW/HIGH. What’s with the strange values ? Did you mean to use analogWrite() ?

Sorry that was just for testing purposes and yeah supposed to try using analogWrite()

Ignoring that, even with LOW/HIGH i’m facing the problem

  else if (buttonPushCounter == 2)
  {
    analogWrite(ledPin, 64);
    delay(1000);
    analogWrite(ledPin, 0);
    delay(1000);
  }

Once the program is in state 2 there will be a 2 second delay each time through loop() because of the code above. No wonder it is hit and miss whether the button presses are recognised whilst in this state.

You need to reconsider how you do the timing for this 64/0 output value change. Using millis() for the timing is one solution. See Using millis() for timing. A beginners guide, Several things at the same time and look at the BlinkWithoutDelay example in the IDE.