Push button that doesn't toggle states?

Hello everyone,

As I was trying to finish a project, a question came up and I couldn't find it online.

Is there any way to make a push-button toggle state with every push?

For example, knowing that the buttons are declared like so:

pinMode(motor1ButtonStarting, INPUT_PULLUP);

when are pushed are equal to LOW like so:

digitalRead(motor1ButtonStarting) == LOW

Is there any way to hold that state even if we remove our finger from the button?

What I want basically, is that when I push once the push-button, the code runs a loop until I push it again. I have a code that runs the way it has to, but the problem is that I have to hold the push-button down for the time that I want it to run.

The code is :

//////////////////////////////////////////////////////////// Starting State ///////////////////////////////////////////////////////////
  
  if (digitalRead(motor1ButtonStarting) == LOW && digitalRead(motor1PushButtonStop) == HIGH ){

  
  currentMillis1 = millis();// starting counting.
  motor1StopState = LOW; // motor shall move
  motor1Direction = CW;  // clockwise.
  
 LastTime_Period_Elapsed1 = currentMillis1; // take a snapshot of time.
  
    }

   if ( digitalRead(motor1PushButtonStop) == LOW && digitalRead(motor1ButtonStarting) == LOW  ){

    currentMillis1 = millis(); // start counting again.

    motor1StopState = LOW; // motor shall move
    motor1Direction = CCW; // counter clockwise 
      
    if ( currentMillis1 - LastTime_Period_Elapsed1  >= DEL3){ // until the value of the subtraction is greater or equal to delay time given by the user.
      SUM1 = currentMillis1 - LastTime_Period_Elapsed1; // the  value of the subrtaction.
      motor1StopState = HIGH; // motor shall stop.
      motor.brake(motor1);  //motor brake.
 
    }
  }

Thank you in advance,

electp

The Debounce example built in to the IDE (also available here) toggles a state just the way you need.

Is there any way to make a push-button toggle state with every push?

See the StateChangeDectection example in the IDE

I couldn't find it online

https://www.google.com/search?q=arduino+toggle+state+with+every+push

Based on the edge detection code I came up to that...

 button_state = digitalRead(motor1PushButtonStop);
//  Serial.println();
//  Serial.println ("Button_State outside of the loop = ");
//  Serial.print(button_state);
//  Serial.println();
  
  if (digitalRead(motor1ButtonStarting) == LOW){

  
  currentMillis1 = millis();// starting counting.
  motor1StopState = LOW; // motor shall move
  motor1Direction = CW;  // clockwise.
  
 LastTime_Period_Elapsed1 = currentMillis1; // take a snapshot of time.
//   Serial.println();
//  Serial.println ("LastTime_Period_Elapse1 inside the Second loop = ");
//  Serial.print(LastTime_Period_Elapsed1);
//  Serial.println();
  
    }

   if ( button_state != previous_button_state && digitalRead(motor1ButtonStarting) == LOW ){
//  Serial.println();
//  Serial.println ("Previous_Button_State inside the Second LOOP = ");
//  Serial.print(previous_button_state);
//  Serial.println();
  Serial.println();
  Serial.println ("Button_State inside the Second LOOP = ");
  Serial.print(button_state);
  Serial.println();
  
    if (button_state == 0){
      if (move_on == 0){
        currentMillis1 = millis(); // start counting again.
        move_on = 1;
      }
      else{
        currentMillis1 = millis(); // start counting again.
        move_on = 0;
      }
  Serial.println();
  Serial.println ("Button_State inside the Third loop = ");
  Serial.print(button_state);
  Serial.println();
  Serial.println();
  Serial.println ("CurrentMillis1 inside the Third loop = ");
  Serial.print(currentMillis1);
  Serial.println();
  

    motor1StopState = LOW; // motor shall move
    motor1Direction = CCW; // counter clockwise 
    if(move_on == 1){
      
    if ( currentMillis1 - LastTime_Period_Elapsed1  >= DEL3){ // until the value of the subtraction is greater or equal to delay time given by the user.
      SUM1 = currentMillis1 - LastTime_Period_Elapsed1; // the  value of the subrtaction.
  Serial.println();      
  Serial.println ("SUM inside the Fourth loop = ");      
  Serial.print(SUM1);
  Serial.println();
      
      motor1StopState = HIGH; // motor shall stop.
      motor.brake(motor1);  //motor brake.

       previous_button_state = button_state;
         Serial.println();
  Serial.println ("Previous_Button_State inside the Fourth loop = ");
  Serial.print(previous_button_state);
  Serial.println();
       
        }
      }
    }
  }

The push-button doesn't work as it has to. (on/off)

Any suggestions?

What debug output are you getting?
What did you expect to happen?
What actually happened?

The debug output is imported in the attachments area.

What I want for the code to do is :
1) When a switch(motor1ButtonStarting) is ON, the motor moves CW.
2) As soon as the switch is on and we push ONCE the push button(motor1PushButtonStop), the motor should run CCW for the delay time that is given by the user (DEL3) and then stop.

This should be used every time that:

motor1ButtonStarting == LOW && motor1PushButtonStop == LOW

The problem that I was dealing with from the start was that in order to make this movement the push button should be pushed prolonged not only once. Which doesn't work for me.

Now :

As you can see at the serial monitor, the code should be working correctly, meaning that jumps from the second loop to the third, from the third to the fourth, but then nothing happens.

No CCW movement for the motor and no stop.

I would be grateful if you can give me a solution to that.

Should I use the push button as an external interrupt instead of trying that type of coding?

Ok I tried to use the button as an external interrupt but when the delay is given, the interrupt function doesn't work correctly. Below you will find the code and a snapshot of the serial monitor.

The button is :

const int motor1PushButtonStop = 18;// outside of the setup()
 pinMode(motor1PushButtonStop, INPUT_PULLUP);//inside the setup()

And the interrupt inside the setup is :

  attachInterrupt(digitalPinToInterrupt(18),InterruptFunction,RISING);

The loop is :

  //////////////////////////////////////////////////////////// Starting State ///////////////////////////////////////////////////////////
  
  if (digitalRead(motor1ButtonStarting) == LOW){

  
  currentMillis1 = millis();// starting counting.
  //motor1StopState = LOW; // motor shall move
  motor1Direction = CW;  // clockwise.
  
 LastTime_Period_Elapsed1 = currentMillis1; // take a snapshot of time.
//  Serial.println();
//  Serial.println ("LastTime_Period_Elapse1 inside the Second loop = ");
//  Serial.print(LastTime_Period_Elapsed1);
//  Serial.println();
  }
}



void InterruptFunction(){

    currentMillis1 = millis(); // start counting again.
    //motor1StopState = LOW; // motor shall move
    motor1Direction = CCW; // counter clockwise 
  Serial.println();
  Serial.println (" motor1DIRECTION= ");
  Serial.print(motor1Direction);
  Serial.println();
   Serial.println();
  Serial.println (" motor1StopState= ");
  Serial.print(motor1StopState);
  Serial.println();
      
    if ( currentMillis1 - LastTime_Period_Elapsed1  >= DEL3){ // until the value of the subtraction is greater or equal to delay time given by the user.
      SUM1 = currentMillis1 - LastTime_Period_Elapsed1; // the  value of the subrtaction.
  Serial.println();
  Serial.println (" SUM= ");
  Serial.print(SUM1);
  Serial.println();
      

   motor1StopState = HIGH; // motor shall stop.
   motor.brake(motor1);  //motor brake.
       
   }
}

electp:
Should I use the push button as an external interrupt instead of trying that type of coding?

Emphatically no

Do not try to make what should be a simple sketch work by implementing a complicated solution. Please post the whole of your attempt to use the StateChangeDetection principle

(deleted)

smarts-jb:
But here's what I don't get. The switch that started it running in the first place is (presumably) still on. So what's supposed to happen then:

  • When the code loops, should it see the switch is still on and re-start cw immediately after the ccw has stopped?
  • Or does the switch need to be off'd first and then you look for a new on?
  • Or once the cw/ccw thing has gone once, is that it until an Arduino reset
  • Or what?

Good morning,

To understand what I'm doing, imagine that the motor is attached on a rail which is moving up and down. Up is CCW and Down is CW. So when the motor runs CW and the rail move down, a button is pressed at the finish of the rail, in order to not break anything. Something like a limit button. That's why when the button is pressed, the motor should move CCW for a bit and then Stop.

What it should do? When the motor moves CCW after the button press for some time, which is maximum 1 sec, the motor should stop. From then and so on, the switch turns to OFF condition and the motor moves manually.

But, if sometime after the user wants to do again the above loop, if the switch is ON and the push button is pressed, the motor should run again CCW and then stop.

I'm really happy for your answers,
electp.

The whole code can be found in the attachments. The thing that we are talking about is a part of a bigger project so sorry for the inconvenience. The part of the code that we are talking about is at the very bottom of the sketch. :slight_smile:

Project.ino (23.3 KB)

(deleted)

smarts-jb:
What turns that switch off?

Or should it stop regardless of that switch's position, and only start a new "up" after the switch is off'd and on'ed anew?

THAT'S IT!

(deleted)

smarts-jb:
But I don't really "like" the fact it runs up for a timed second. Why don't you just run it up until the button goes to off, then you know it's actually clear of the base.

Because I want this to work with a push of a button and not pushing it as soon as the loop works. I think that I'm not using correctly the state detection routine. Is there any chance to see my code and try to fix it, or give me hints? :slight_smile:

(deleted)

smarts-jb:
I'm just back in from my weekly 5km and just about to have breakfast and do a few chores.

But after that I'll do a quick sketch to show the principle.

Thank's a lot!

(deleted)