Creating a program where servos and LEDs are activated by a single button press.

Hi Everyone,

I am doing a project where I am using servos to limit the extension of a drawer over a time period. I have attached an Order of Operation and the current code I have created which doesn’t work. The order says a linear actuator is used however for the prototype servos are being used. Some of the anotations in the OofO are not needed in the code at this stage.

Currently, the program runs, however, it doesn’t get further than the first IF Statement.

I’m new to Arduino so please go easy on me.

Thanks in advance.

Sketch_03.ino.ino (2.02 KB)

To make it easy for people to check your code please read this post and see how to put the code directly in your post- that means people don't have to download your file just to look at it.

Here is the code correctly, sorry.

#include <Servo.h>

//Constants
const int buttonPin01 = 31;
const int ledPin = 37;

//variables
int buttonState01 = 0;

Servo servo1; 
Servo servo2; 
Servo servo3; 

int pos01 = 80;    
int pos02 = 40;
int pos03 = 50;    
int pos04 = 100;
int pos05 = 100;    
int pos06 = 150;

void setup() {

  pinMode(buttonPin01, INPUT);
  pinMode(ledPin, OUTPUT);
  servo1.attach(30);  
  servo2.attach(34);  
  servo3.attach(36);  
  }

void loop() {

servo1.write(pos01);             
servo2.write(pos03);  
servo3.write(pos05); 

buttonState01 = digitalRead(buttonPin01);
 
if (buttonState01 == HIGH){
  digitalWrite(ledPin, HIGH);
  delay(1000);
  digitalWrite(ledPin, LOW);
  delay(6000); 
  servo3.write(pos06); 
  delay(500);
  digitalWrite(ledPin, HIGH);
  delay(300);
  digitalWrite(ledPin, LOW);  
  delay(300);
  digitalWrite(ledPin, HIGH); 
  buttonState01 = digitalRead(buttonPin01);
}
  if (buttonState01 == HIGH){
   digitalWrite(ledPin, LOW);
   delay(6000); 
   servo2.write(pos04); 
   delay(500);
   digitalWrite(ledPin, HIGH);
   delay(300);
   digitalWrite(ledPin, LOW);  
   delay(300);
   digitalWrite(ledPin, HIGH); 
   delay(300);
   digitalWrite(ledPin, LOW);  
   delay(300);
   digitalWrite(ledPin, HIGH);
   buttonState01 = digitalRead(buttonPin01);
  } 
   if (buttonState01 == HIGH){
     digitalWrite(ledPin, LOW);
     delay(6000);   
     servo1.write(pos02);
     delay(500);
     digitalWrite(ledPin, HIGH);
     delay(300);
     digitalWrite(ledPin, LOW);  
     delay(300);
     digitalWrite(ledPin, HIGH); 
     delay(300);
     digitalWrite(ledPin, LOW);  
     delay(300);
     digitalWrite(ledPin, HIGH);
     delay(300);
     digitalWrite(ledPin, LOW);  
     delay(300);
     digitalWrite(ledPin, HIGH);
     buttonState01 = digitalRead(buttonPin01);
   }   
     if (buttonState01 == HIGH){
      digitalWrite(ledPin, LOW);
      delay(10000);  

}
}

All of your if() statements are checking exactly the same thing, what exactly are you trying to do? What Arduino board are you using? Are you using an external pullup resistor on your button?

Q1 - I want to use the same button to operate everything. Will I need to create multiple buttonstates i.e. buttonState02 at each point? I have attached an image in the original question outlining the main points of what I am trying to achieve.

Q2 - MEGA 2560

Q3 - It has a resistor on the button. do I need to say INPUT_PULLUP? The buttons has worked before within earlier versions of the code.

Thanks for getting back to me.

KHutchings13: Q1 - I want to use the same button to operate everything. Will I need to create multiple buttonstates i.e. buttonState02 at each point? I have attached an image in the original question outlining the main points of what I am trying to achieve.

If you want the Arduino to do one of several different things, how do you expect it to know which thing to do if you only have one button? There are ways of doing this, but it depends on what you're trying to do with the whole sketch.

KHutchings13: Q3 - It has a resistor on the button. do I need to say INPUT_PULLUP? The buttons has worked before within earlier versions of the code.

It is the other way around actually- if there is no external resistor then you need to turn on the internal resistor via the INPUT_PULLUP option. Since you have an external resistor you don't need to change anything, I just wanted to check and rule that out as a possible issue.

KHutchings13: Thanks for getting back to me.

No worries, that's what the forum's here for :)

If you want the Arduino to do one of several different things, how do you expect it to know which thing to do if you only have one button? There are ways of doing this, but it depends on what you're trying to do with the whole sketch.

The idea of the product is for the drawer to run over a single button which would operate the code. I don't want the user to 'press the button' rather just open the drawer when needed. Therefore only one button can be used to operate it. I hope that makes sense.

As being new to Arduino and coding in general, this is the only method I could think of that might work. Guess it didn't. If there is a way to get the system to work of the one button that would be great.

Cheers,

I see the loop part of the code copy a button state into a variable and then

if the variable is HIGH, do a led and servo thing that takes many seconds and then

the same thing or almost the same triggered by the variable with that first read button state and then repeat, etc.

Why not read the button just before the other if's? Time has passed, maybe the button is not down?

KHutchings13: The idea of the product is for the drawer to run over a single button which would operate the code. I don't want the user to 'press the button' rather just open the drawer when needed. Therefore only one button can be used to operate it. I hope that makes sense.

As being new to Arduino and coding in general, this is the only method I could think of that might work. Guess it didn't. If there is a way to get the system to work of the one button that would be great.

Cheers,

It is immaterial how the button actually gets pressed, what matters is that the button is the only input the Arduino has. You could do something like keep track of how many times the button has been pressed and take action accordingly.

BJHenry: It is immaterial how the button actually gets pressed, what matters is that the button is the only input the Arduino has. You could do something like keep track of how many times the button has been pressed and take action accordingly.

That's a brilliant idea, I'll have a go at coding in that now. Guessing I will need to consider debouncing if I do this then?

Cheers for your help.

BJHenry:
It is immaterial how the button actually gets pressed, what matters is that the button is the only input the Arduino has.
You could do something like keep track of how many times the button has been pressed and take action accordingly.

I believe I have done as you suggested, however, the program is still not working correctly. The code is as follows:

#include <Servo.h>

//Constants
const int buttonPin01 = 31;
const int ledPin = 37;

//variables
int buttonState01 = 0;
int buttonPushCounter = 0;
int lastButtonState = 0;

Servo servo1; 
Servo servo2; 
Servo servo3; 

int pos01 = 80;    
int pos02 = 40;
int pos03 = 50;    
int pos04 = 100;
int pos05 = 100;    
int pos06 = 150;

void setup() {

  pinMode(buttonPin01, INPUT);
  pinMode(ledPin, OUTPUT);
  servo1.attach(30);  
  servo2.attach(34);  
  servo3.attach(36);  
  Serial.begin(9600);
  servo1.write(pos01);             
  servo2.write(pos03);  
  servo3.write(pos05); 
  }

void loop() {

buttonState01 = digitalRead(buttonPin01);

 if(buttonState01 != lastButtonState) {
  if(buttonState01 == HIGH){
    buttonPushCounter++;
    Serial.println("on");
    Serial.print("number of button pushes: ");
    Serial.println(buttonPushCounter);
  }
  else {
    Serial.println("off");
  }
  }
  delay(50);
  lastButtonState = buttonState01; 

 
 if (buttonPushCounter % 1 == 0){
  digitalWrite(ledPin, HIGH);
  delay(1000);
  digitalWrite(ledPin, LOW);
  delay(6000); 
  servo3.write(pos06); 
  delay(500);
  digitalWrite(ledPin, HIGH);
  delay(300);
  digitalWrite(ledPin, LOW);  
  delay(300);
  digitalWrite(ledPin, HIGH); 
  return;
}

 if (buttonPushCounter % 2 == 0){
   digitalWrite(ledPin, LOW);
   delay(6000); 
   servo2.write(pos04); 
   delay(500);
   digitalWrite(ledPin, HIGH);
   delay(300);
   digitalWrite(ledPin, LOW);  
   delay(300);
   digitalWrite(ledPin, HIGH); 
   delay(300);
   digitalWrite(ledPin, LOW);  
   delay(300);
   digitalWrite(ledPin, HIGH);
   return;
} 
   
 if (buttonPushCounter % 3 == 0){
     digitalWrite(ledPin, LOW);
     delay(6000);   
     servo1.write(pos02);
     delay(500);
     digitalWrite(ledPin, HIGH);
     delay(300);
     digitalWrite(ledPin, LOW);  
     delay(300);
     digitalWrite(ledPin, HIGH); 
     delay(300);
     digitalWrite(ledPin, LOW);  
     delay(300);
     digitalWrite(ledPin, HIGH);
     delay(300);
     digitalWrite(ledPin, LOW);  
     delay(300);
     digitalWrite(ledPin, HIGH);
     return;
 }

 if (buttonPushCounter % 4 == 0){
      digitalWrite(ledPin, LOW);
      delay(10000);  
      buttonPushCounter == 0;

}

}

Currently the only thing that is happening is the LED is flashing as if it is running through the third if() statement, however, the servos are not working. (They do work with another code, so wiring and pins are correct).

Have you got any suggestions?

Cheers,

buttonPushCounter % 1

That delivers the remainder of dividing a value by 1. It will always be zero. x % 2 can be 0 or 1.

You could save yourself a lot of typing by learning about grouping variables in arrays. Even the servos can be arrayed.

You can't watch the button or change a led state or anything else while a delay() is running. The BlinkWithoutDelay IDE Example sketch (1st sketch in section 2) explained on the Arduino site shows how to get around delays and do what is ready like watch inputs. There's a sticky thread on this forum that does a better job and the 1st tutorial address in my signature space at the bottom of this post has a well made lesson on the subject.

There's some skill involved but mostly it's a way of looking at coding for events and processes happening over many runs through loop().

Is there a reason you're doing this:

 if (buttonPushCounter % 1 == 0){

Rather than this:

 if (buttonPushCounter == 1){

What is your serial monitor showing? Is it reading and counting the button presses correctly?