Button to start/stop program

I have been looking for a tutorial on how to make a program start and stop by the press of a button. So far the only things I can find are how to get an led to light up when you push the button. Can anyone point me in a direction to help me accomplish this task; is it even possible to have a program start and stop the loop by the press of a button?

?? Start loop. Check button status. Button not pressed? Chill. Button pressed? Do stuff. Loop. ??

bigred1212: ?? Start loop. Check button status. Button not pressed? Chill. Button pressed? Do stuff. Loop. ??

Sorry, I am new to this kind of programming. The lack of int main and return 0 throw me off. Is there a way to break out of the main loop where I have all my code at?

I think I figured it out... sorry.. seems like a silly question now that I know what to do.

You could write a conditional if statement around any code you only want to run while the program is functioning, and when you press the button you can simple toggle the state of the variable between true and false or 255 and 0. Alternatively you could use interrupts to toggle the variable (if you do this make sure the variable is declared as volatile).

Below is some demo code:

int run;
int buttonPin;

void setup()
{
   run = 0; //starts stopped
   buttonPin = 7; //whatever pin your button is plugged into

   pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
   //code you always run here; you can leave this section blank if you want the entire program to stop and start, or add code here if you want it to always run

   //check button press here and if it is pressed then toggle run variable between 0 and 255; REQUIRED!
   if(digitalRead(buttonPin) == LOW) //funcitons based off of button pulling input pin LOW
   {
      if(run == 0)
      {
          run = 255;
      }
      else
      {
          run = 0;
      }
   }

   if(run > 0)
   {
      //code you only run if button was pressed, stops running when button pressed again, so forth...
   }
}

wes000000: You could write a conditional if statement around any code you only want to run while the program is functioning, and when you press the button you can simple toggle the state of the variable between true and false or 255 and 0. Alternatively you could use interrupts to toggle the variable (if you do this make sure the variable is declared as volatile).

Below is some demo code:

int run;
int buttonPin;

void setup() {   run = 0; //starts stopped    buttonPin = 7; //whatever pin your button is plugged into

   pinMode(buttonPin, INPUT_PULLUP); }

void loop() {   //code you always run here; you can leave this section blank if you want the entire program to stop and start, or add code here if you want it to always run

  //check button press here and if it is pressed then toggle run variable between 0 and 255; REQUIRED!   if(digitalRead(buttonPin) == LOW) //funcitons based off of button pulling input pin LOW   {      if(run == 0)      {          run = 255;      }      else      {          run = 0;      }   }

  if(run > 0)   {      //code you only run if button was pressed, stops running when button pressed again, so forth...   } }

Thank you! This is what I love about the community.. you can ask a stupid question (because you honestly don't know the answer) and get a response from someone who does. Gotta start learning somewhere right?

This code does what I want to do with my program.. somewhat.

I'm trying to break it down and figure out exactly what is going on. Really, what I would like to happen is the following.

1) enter the main loop.. no code is here so nothing happens. 2) User pushes down the button - this makes the program enter another loop that will run my program. Once the program has finished, break; out of the loop back to the main where we wait for the button to be pushed again.

OK I think I am following what you want, try this:

It will run the code inside the if statement once when you hit the button and when the code is done executing, it will go to top of the loop() function and continue checking if the button has been pressed. If you need some kind continual code execution you can use a for loop or a while loop inside the if statement. In essence treat the inside of the if statement like a function. In fact if you wanted to you could write a separate function to do your task and just call that function from inside the if statement.

The reason this works, just to clarify is that the setup() function gets run once when you apply power/deploy code/reset device/etc and the loop() function gets run continually after that over and over again as fast as the micro controller can go, a few million times a second in fact. So by putting that if statement what happens is when you press the button down that condition becomes true and it runs all the code inside once then continues on and just starts over at the top of the loop() function checking if the button is pressed.

int buttonPin;

void setup()
{
   buttonPin = 7; //whatever pin your button is plugged into
   pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
   //check button pressed, if so enter program condition (inside if statement)
   if(digitalRead(buttonPin) == LOW) //functions based off of button pulling input pin LOW
   {
      //put code you want to run on button press here.
      //if will run once and then when it's done it will exit the if statement and return to the top of the loop function and continually checking to see if the button has been pressed, if it hasn't it will keep checking, if it has it will run the program again and then once done continue to check after
   }
}

wes000000:
OK I think I am following what you want, try this:

It will run the code inside the if statement once when you hit the button and when the code is done executing, it will go to top of the loop() function and continue checking if the button has been pressed. If you need some kind continual code execution you can use a for loop or a while loop inside the if statement. In essence treat the inside of the if statement like a function. In fact if you wanted to you could write a separate function to do your task and just call that function from inside the if statement.

The reason this works, just to clarify is that the setup() function gets run once when you apply power/deploy code/reset device/etc and the loop() function gets run continually after that over and over again as fast as the micro controller can go, a few million times a second in fact. So by putting that if statement what happens is when you press the button down that condition becomes true and it runs all the code inside once then continues on and just starts over at the top of the loop() function checking if the button is pressed.

int buttonPin;

void setup()
{
  buttonPin = 7; //whatever pin your button is plugged into
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
  //check button pressed, if so enter program condition (inside if statement)
  if(digitalRead(buttonPin) == LOW) //functions based off of button pulling input pin LOW
  {
     //put code you want to run on button press here.
     //if will run once and then when it’s done it will exit the if statement and return to the top of the loop function and continually checking to see if the button has been pressed, if it hasn’t it will keep checking, if it has it will run the program again and then once done continue to check after
  }
}

Hey buddy, thanks for explaining all of that. I tried the new code and it doesn’t seem to do anything different then the other one you posted above. Logically, it seems like it should run through my loop as soon as I push the button down. However, as soon as I take my finger off the button, my program stops… well my motor spots moving.

Here is my code in case you want to take a look at it.

#include <AFMotor.h>

AF_Stepper motor1(200, 1); // set motor stpes per revolution and port connected to (M1 & M2)

// ******** Variables Here *******

int run;
int buttonPin;

// ******** Setup Here ********

void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println(“Stepper test!”);

buttonPin = 7; // setting button to pin 7

pinMode(buttonPin, INPUT_PULLUP); // not sure what this does…

motor1.setSpeed(50); // Set speed of motor
}

// *********** Main Program Here ***********

void loop() {

Serial.println(“Single coil steps”);

int steps = 0, full = 200;
int rate = 2000;

if(digitalRead(buttonPin) == LOW) // If button is pushed enter this loop
{

for (int x = 0; x < 1670; x++)
{
motor1.step(1, FORWARD, SINGLE); // 1670 moves 1 ft on rail
steps++;
Serial.println(steps);
Serial.println(" ");
//delay(100);
}

delay(4000);

//motor1.step(full, FORWARD, SINGLE);

// delay(rate);
}

}

Thank you for including you code as well. I think the issue at hand is not that the code isn't working, but rather that it takes the MCU less time to run through 1670 loops then it does for you to take your finger off the button. I could be wrong but I believe it is doing exactly what it is supposed to but human reaction time may be just about the same speed it takes for the MCU to complete all the motor.step command. You have a delay in there but that is after all the steps stop so no way to know if the codes still going.

Maybe try after the delay also putting a serial.print("waited") and watch your serial output close. if you see the "waited" still come across after releasing the button the codes is working.

Alterantively, to try another experiment, can you make the motor drive more like a few thousand steps, not sure you hardware setup and if that's possible. If not then maybe if you have an LED and resistor laying around, if so hook that up to a pin and inside the if statement turn on the LED wait a few seconds, then turn if off to see if indeed the LED code continues to execute after you remove your hand.

Do all the steps get printed to the serial?

1,670 steps makes my rail system travel 1 foot. I just used the serial (should have been paying attention to it earlier) and once I pushed the button down it entered the loop. It prints out each step as it moves down the rail. As soon as I took my finger off the button, prior to it getting to the end of the for loop, the rail system stopped. However, it was still in the loop because it kept printing out each step even though it wasn't moving.

Once it got to the end of the for loop it stopped printing the steps and went back to printing out Single Coil Steps. So, it looks like the code is working but for some reason the movement of my motors stop as soon as I take my finger off the button.

I have my motor shield hooked up and the motors work fine. I have the button on a breadboard with one wire coming from the grnd and one to pin 7.

And if you keep the button pressed the whole time it goes the full distance?

I will have to look at the library more to see how that is functioning because the code looks good and it sounds as though your hardare setup is fine.

wes000000:
And if you keep the button pressed the whole time it goes the full distance?

I will have to look at the library more to see how that is functioning because the code looks good and it sounds as though your hardare setup is fine.

Yep, as soon as it gets to the end of the for statement motion stops. I then have to let go of the button and hold it down again to get movement to happen.

What’s curious though is when I comment out the // if(digitalRead(buttonPin) == LOW) { } but still have my for loop going, the motion still requires me to push and hold the button in order to achieve movement.

Could you elaborate on the pinMode(buttonPin, INPUT_PULLUP); in the void setup (), what exactly does this call/do? When I comment this out as well it allows my program to move without pushing down the button. Could this be where my issue is?

I am still looking over the AF_Stepper library and will continue to.

The first condition you mentioned about commenting out the if line is odd. Without the line it should continually step with 4 second delays. I will look at that section of code in a minute, maybe there is an issue there.

The line: "pinMode(buttonPin, INPUT_PULLUP);" is turning on internal pull up resistors and also setting pin 7 (or whatever buttonPin is) as an input. You have to call pinMode of some sort or another (output, input, or inpout_pullup) otherwise your pin will be in whats called tri state and it can be any voltage between gnd and 5volts. Setting it to input allows the code to recognize the pin as input (there is more to it but suffice to say it should be input when reading whether its high or low). As far as the pull up portion that turns on internal MCU resistors so that the pin is not floating in la-la land and it defaults to 5V. When pressing teh button tied to ground it overrides the 5V and when you read the pin you will get a low if button is pressed and tied to ground.

More: http://arduino.cc/en/Reference/pinMode

it just dawned on me INPUT_PULLUP is only an option with arduino 1.0.1 and up. If you are running an older version you will need two lines.

pinMode(buttonPin, INPUT); //sets as input
digitalWrite(buttonPin, HIGH); //turn on internal pull up resistors

wes000000: it just dawned on me INPUT_PULLUP is only an option with arduino 1.0.1 and up. If you are running an older version you will need two lines.

pinMode(buttonPin, INPUT); //sets as input
digitalWrite(buttonPin, HIGH); //turn on internal pull up resistors

I put those two lines in my void setup, correct? Unfortunately, I am still stuck with it only running when I hold down the button. I am running 1.0.5 by the way. You're awesome for trying to help me with this. If you can't figure it out no worries, you don't need to waste your entire day/night helping me.

Correct both of those would go in setup(). And if you have 1.0.5 the single command will work just as good.

Do you think you could take a picture of wiring/setup? Not sure if you have a camera phone available. Also not sure if its feasible depending on how large setup is. If so please do post it here so I can take a look.

And no worries, it 's my pleasure to help.

That code will only execute inside the if statement when the button is pressed down, so of course it stops as soon as you let go.

Here is what you need, it even includes software debounce WITHOUT using delay():

http://arduino.cc/en/Tutorial/Switch

I'm not fond of the stepper library, but use what you need to. I actively hate the delay() command.

Is this the motor shield you are using? http://learn.adafruit.com/adafruit-motor-shield

If so how are you connecting to pin 7, because it looks to me like its inaccessible.

@polymorh: if the content inside the if statement takes 3 seconds though and you let go of the buton in 200 ms it will keep going for the full 3 secs then return to checking if button is pressed, correct? And I don’t think he was using delay for debouncing but rather for testing and debugging purposes, i could be wrong though.

Absolutely, I followed a tutorial on how to wire the button from a different thread on here. I know you mentioned the resistors earlier; do I need one on my breadboard? I was under the impression that these were built into the board already and I do not need them.

polymorph: That code will only execute inside the if statement when the button is pressed down, so of course it stops as soon as you let go.

Here is what you need, it even includes software debounce WITHOUT using delay():

http://arduino.cc/en/Tutorial/Switch

I'm not fond of the stepper library, but use what you need to. I actively hate the delay() command.

I'm only using the delay command so I can count/see whats happening as the steps happen so fast. As far as the stepper library, I couldn't get my program to run without it. If you have any suggestions feel free to let me know. Coming in and saying you hate this and that isn't helping.

wes000000: Is this the motor shield you are using? http://learn.adafruit.com/adafruit-motor-shield

If so how are you connecting to pin 7, because it looks to me like its inaccessible.

Uhm, the one I am using is similar to that yes. It's a knock off by sainsmart.. pretty much identical. Since I am using the motorshield I do not have easy access to the pins. So what I did (and you can see by the picture) is wrapped a wire around the pins coming out of the motorshield and then put it into the board. That way I can test without having to solder things. I'll try changing the pin and see if that resolves the issue... although it moves when I push the button down so it has to be working somehow.