Servo motor forward reverse toggle with button

I'm new to Arduino and this programming language too, and I am having great trouble doing something as seemily simple as making a servo motor go forward with the press of a button, and with another press make it go back. I've found a couple of different codes, but no matter how much I try none of them work for me. It seems to work for others. What am I doing wrong?

My motor is connected to pin 9. The button is connected to pin 2.

Here's one:

#include <Servo.h>
const int switchPin = 2; //active low
const int servoPin = 9;
Servo servo;

void setup() {
  pinMode(switchPin, INPUT_PULLUP);
  servo.attach(servoPin); 
}

void loop() {
  if (digitalRead(switchPin))
    servo.write(90);  // HIGH (switch is off)
  else
    servo.write(100);  // LOW (switch is on)

  delay(500);  //delay for debounce
}

Here's another one:

//zoomkat servo button toggle test 4-28-2012

#include <Servo.h>
int button = 5; //button pin, connect to ground to move servo
int press = 0;
Servo servo;
Servo servo1;
boolean toggle = true;

void setup()
{
  pinMode(button, INPUT); //arduino monitor pin state
  servo.attach(7); //pin for servo control signal
  servo1.attach(8); //pin for servo control signal
  digitalWrite(5, HIGH); //enable pullups to make pin high
}

void loop()
{
  press = digitalRead(button);
  if (press == LOW)
  {
    if(toggle)
    {
      servo.write(160);
      servo1.write(20);
      toggle = !toggle;
    }
    else
    {
      servo.write(20);
      servo1.write(160);
      toggle = !toggle;
    }
  }
  delay(500);  //delay for debounce
}

Here's yet another:

			//Directions are using the same pins from zoomkat servo button toggle test code so that a zwave switch could easily be added to test new code
		        //run 4.8 to 6v ground wire spliced to servo and ground on digital side of nano,
			// and a 3rd splice to z wave isolated switch to switch the ground for the nano to read
			//then the other side of the z-wave isolated switch (same ground) back to pin D7 on nano
			//the 4.8 to 6v positive/red wire to servo motor
			//run servo's white control wire to pin D5
			// run separate 12v to VIN pin on nano and the same 12v source's ground to the GRN pin next to VIN

                        // Shout out and Thanks a ton to Zoomkat for the first code for the momentary switch. I have learned a ton!
                        //Thanks Lar3ry for showing me things to learn to better my skills, I have learned a ton!

//zoomkat servo button toggle test 4-28-2012  combined from code suggested my reallifeonhold source unknown

#include <Servo.h>

const int button_pin = 2 ;         			//The issue I see is this takes voltage from the nano and NOT completing my circuit which would be to run ground from digital 
							//side GRN to pin 7, in short this just uses the nano to send 5V to pin D7 what code is needed?


int led = 13;                              		// use LED aka pin 13 for visual confirmation as to which state the Arduino was in.

Servo s1;
int pos = 0; 						// variable to store the servo start position deg
int button_value = 180; 				//variable to store switch position e.g. 180 turn 

void setup()
{
  s1.attach(9); 					// attaches the servo's control wire on pin 5 White wire
  pinMode(led, OUTPUT);    
 
}
                                        		// code for z wave switch recognition 
void loop()
{
  button_value = digitalRead(button_pin);
  if (button_value==HIGH){				//do this
    s1.write(135); 					//Value to open servo to on/off of switch
    digitalWrite(led, HIGH);   				// turn the LED on LED corresponding to switch
    }
  else {						//or else do this
    s1.write(45);					//Value to open servo to on/off of switch
   digitalWrite(led, LOW);   				// turn the LED of corresponding to switch
    }
}

First rule of getting code to work - don't use a scatter-gun.

I've picked this from your post because it looks like it will work. There seems to be some strange stuff in the second example which, I suspect, is not down to Zoomkat.

#include <Servo.h>
const int switchPin = 2; //active low
const int servoPin = 9;
Servo servo;

void setup() {
  pinMode(switchPin, INPUT_PULLUP);
  servo.attach(servoPin); 
}

void loop() {
  if (digitalRead(switchPin))
    servo.write(90);  // HIGH (switch is off)
  else
    servo.write(100);  // LOW (switch is on)

  delay(500);  //delay for debounce
}

This code makes the servo move to 100 when the button is pressed and to 90 when it is not pressed.

You want code for two buttons so you need to record the state of each button first and then your code can figure out what to do.

Try this

#include <Servo.h>
const byte switchPinA = 2; //active low
const byte switchPinB = 3; //active low
const byte servoPin = 9;
Servo servo;
byte switchAstate = HIGH;
byte switchBstate = LOW;
byte servoPos = 20;

void setup() {
  pinMode(switchPinA, INPUT_PULLUP);
  pinMode(switchPinB, INPUT_PULLUP);
  servo.attach(servoPin); 
}

void loop () {
   readButtons();
   moveServo();
}

void reabButtons() {
   switchAstate = digitalRead(switchPinA);
   switchBstate = digitalRead(switchPinB);
}

void moveServo() {
   if (switchAstate == LOW) {
       servoPos = 90;
   }
   if (switchBstate == LOW) {
        servoPos = 100;
   }
   servo.write(servoPos);
   delay(100);
}

...R

Robin2:
First rule of getting code to work - don't use a scatter-gun.

I've picked this from your post because it looks like it will work. There seems to be some strange stuff in the second example which, I suspect, is not down to Zoomkat.

What does using a scatter-gun imply? :slight_smile:

Your code doesn't work. It gives the error:

sketch_aug15a.ino: In function 'void loop()':
sketch_aug15a:17: error: 'readButtons' was not declared in this scope

Edit: I tried messing around with it but I just keep getting tons of errors around that readButtons thing. I have no idea what I'm doing :frowning:

Korvboll:

Robin2:
First rule of getting code to work - don't use a scatter-gun.

I've picked this from your post because it looks like it will work. There seems to be some strange stuff in the second example which, I suspect, is not down to Zoomkat.

What does using a scatter-gun imply? :slight_smile:

Trying several different things that have nothing to do with each other rather than focusing on the problem

Your code doesn't work. It gives the error:

sketch_aug15a.ino: In function 'void loop()':

sketch_aug15a:17: error: 'readButtons' was not declared in this scope




Please correct my typo in **void reabButtons() {** - sorry I'm not perfect. Also you are expected to do a little of the work.

Edit: I tried messing around with it but I just keep getting tons of errors around that readButtons thing. I have no idea what I'm doing :(

...R

No need to be rude. Doesn't work anyway. Never mind.

Korvboll:
No need to be rude.

Robin2 is probably one of the least rude members on this forum...

Anyhoo, his code worked for me, once I changed reab to read of course 8). Only thing I did was change the servo positions from 90 and 100 to 10 and 170 to make the motion more apparent.

So I'll hazard a guess that your wiring may be wrong.

Assuming you want further help, and this....

Doesn't work anyway. Never mind.

.... indicates you probably don't, you should:

  • Describe how it doesn't work: what's it (not) doing
  • Give a sketch of you circuit.

Here's my circuit which worked with Robin's code.

servo 2 buttons v3.png

Here's what I have:

I might have been misunderstood. I tried making the program use one single button to go both ways. Such as first press to say 170 degrees and the second press to 20. I notice that you have two buttons in your scheme. Right now nothing happens when I press the button.

I tried changing the commands to "readButtons" instead of "reabButtons" because I thought it made more sense to "read" the value of the buttons :slight_smile:

so, try it this way:

#include <Servo.h>
const int switchPin = 2; //active low
const int servoPin = 9;
int oldButtonState;
int state, oldState;
Servo servo;

void setup() 
{
  pinMode(switchPin, INPUT_PULLUP);
  servo.attach(servoPin); 
}

void loop() 
{
  int buttonState = digitalRead(switchPin);
  if (buttonState == LOW)
  {
    if (oldButtonState == HIGH)
    {
      state = !state; //toggle state
    }
  }
  oldButtonState = buttonState;
  if (state != oldState)// changed state
  {
    if (state == 1)
    {
      servo.write(90);  // HIGH (switch is off)
      delay(500);
    }
    else
    {
      servo.write(100);  // LOW (switch is on)
      delay(500);
    }
  }
  oldState = state;
}

BulldogLowell:
so, try it this way:

Doesn't work either. Nothing is happening.No error codes or anything, just that nothing happens when the button is pressed.

so put some Serial.println() in the code or toggle the on-board LED and find out what's happening.

#include <Servo.h>
const int switchPin = 2; //active low
const int servoPin = 9;
int oldButtonState;
int state, oldState;
Servo servo;

void setup() 
{
  pinMode(switchPin, INPUT_PULLUP);
  pinMode(13,OUTPUT);
  servo.attach(servoPin); 
}

void loop() 
{
  int buttonState = digitalRead(switchPin);
  if (buttonState == LOW)
  {
    if (oldButtonState == HIGH)
    {
      state = !state; //toggle state
      Serial.println(F("StateChange"));
    }
  }
  oldButtonState = buttonState;
  if (state != oldState)// changed state
  {
    if (state == 1)
    {
      servo.write(90);  // HIGH (switch is off)
      digitalWrite(13, HIGH);
      delay(500);
    }
    else
    {
      servo.write(100);  // LOW (switch is on)
      digitalWrite(13, LOW);
      delay(500);
    }
  }
  oldState = state;
}

and the code you provided was using internal pull-up resistor on you button, so wire it like this:

I misread your original post and I thought you wanted to use 2 buttons.

This version works with a single button. So that you can see what changes were necessary I have just commented out the parts for the second button and I have added // new to mark the new pieces.

I have increased the delay a little to eliminate switch bounce - which wasn't an issue when there were 2 buttons.

I have tested this on my Uno.

#include <Servo.h>
const byte switchPinA = 2; //active low
//const byte switchPinB = 3; //active low
const byte servoPin = 9;
Servo servo;
byte switchAstate = HIGH;
//byte switchBstate = LOW;
byte servoPos = 20;
byte posA = 60; // new
byte posB = 120; // new

void setup() {
  pinMode(switchPinA, INPUT_PULLUP);
//  pinMode(switchPinB, INPUT_PULLUP);
  servo.attach(servoPin); 
}

void loop () {
   readButtons();
   moveServo();
}

void readButtons() {
   switchAstate = digitalRead(switchPinA);
//   switchBstate = digitalRead(switchPinB);
}

void moveServo() {
   if (switchAstate == LOW) {
     if (servoPos == posA) {  // new
        servoPos = posB;
     }
     else { 
       servoPos = posA;
     }
     switchAstate = HIGH; // new
   }
//   if (switchBstate == LOW) {
//        servoPos = 100;
//   }


   servo.write(servoPos);
   delay(200); // modified
}

The earlier code worked fine (with 2 buttons) when I corrected the typo.

...R

HI,
It all looks OK to me! What are you using for batteries or power?? A servo can take an Amp or so, and a 9v PP3 is not going to do the trick, not that you're using one, but you might. 4x AA's usually does the trick....

Regards

Mel.

so put some Serial.println() in the code or toggle the on-board LED and find out what's happening.

It doesn't display anything. The serial monitor is blank :frowning:

Robin2:
I misread your original post and I thought you wanted to use 2 buttons.

This version works with a single button. So that you can see what changes were necessary I have just commented out the parts for the second button and I have added // new to mark the new pieces.

I have increased the delay a little to eliminate switch bounce - which wasn't an issue when there were 2 buttons.

I have tested this on my Uno.

This still doesn't work for me. Maybe something is wrong with the wiring?

HI,
It all looks OK to me! What are you using for batteries or power?? A servo can take an Amp or so, and a 9v PP3 is not going to do the trick, not that you're using one, but you might. 4x AA's usually does the trick....

Regards

Mel.

I'm powering it from the USB. The servo seems to work fine as far as I can tell. I have managed to get it to run, just not with the button and the way I want it to. With the program I have now if i cut the power and move the servo to a different position it will go to the starting position when I enable power.

Don't power the servo from the Arduino as in your Fritzing- power it like I showed in my circuit, Reply#5.

Serial.println() exactly like that won't print anything: you need to put something in the brackets. That something can be either a variable to see what its value is:

Serial.println(myServoPos);   // no quotes

.... or some text to show you where the code has taken you:

Serial.println("in setup"); //with quotes

Korvboll:

so put some Serial.println() in the code or toggle the on-board LED and find out what's happening.

It doesn't display anything. The serial monitor is blank :frowning:

Robin2:
I misread your original post and I thought you wanted to use 2 buttons.

This version works with a single button. So that you can see what changes were necessary I have just commented out the parts for the second button and I have added // new to mark the new pieces.

I have increased the delay a little to eliminate switch bounce - which wasn't an issue when there were 2 buttons.

I have tested this on my Uno.

This still doesn't work for me. Maybe something is wrong with the wiring?

HI,
It all looks OK to me! What are you using for batteries or power?? A servo can take an Amp or so, and a 9v PP3 is not going to do the trick, not that you're using one, but you might. 4x AA's usually does the trick....

Regards

Mel.

I'm powering it from the USB. The servo seems to work fine as far as I can tell. I have managed to get it to run, just not with the button and the way I want it to. With the program I have now if i cut the power and move the servo to a different position it will go to the starting position when I enable power.

I don't normally repeat entire posts in my answers but I need to here to illustrate what I want to say.

This is all over the place. First there is a comment about the serial monitor not working - but without showing the code that is claimed not to work.

Second there is a suspicion that there might be a wiring problem - but no wiring diagram that would enable me to help.

Third the description in the last part is too vague for people to make sense of it. How have you "managed to get it to run"? What do you mean by "just not with the button" - what code are you using? What do you mean by "and the way I want it to" - that sounds like it works some way which you haven't told us.

You need to post the code you are using AND a diagram of your wiring AND a clear detailed description of what happens.

As I said earlier, the code I posted works on my Uno. Start with that and stick with it until the problems have been sorted out.

...R

Hi there! I'm Alan, I was following this post. I tested the code from Robin2 on my Arduino Uno and it works perfectly! What I did notice, is that in the schematic that Korvboll posted, the resistance is connected to the negative side on the switch, once you switch the resistance to the positive side of the switch it works like a charm. Hope this helps guys! Thanks for all the helpful info, have a good one! :slight_smile: