Using on-off-on toggle switch to control a servo

I was able to put together a breadboard design with my starter kit using an Arduino nano, some momentary switches and a servo so that when you press button a, it turns the servo 90 degrees. Then you press button B and it turns back to zero. That is all well and good, but I want to take that circuit and replace the two momentary switches with a single on-off-on toggle switch. The idea was that when I flip it from off to on (up), it would turn 90 degrees, then back to off - nothing. Then down to on and it would go back to zero. when I tried to swap out the switches for the toggle switch - i didn't work. It seems fine in the off position, then when I switch it to either on position, the servo stutters severely. If I switch it back to off, the servo finishes moving to its location without issue. If I switch it on then off fast enough, it works great. So I think it has more to do with either how I have the loop coded, but I am not sure.

I do not have a schematic yet - still working on figuring out how to draw those properly. I do have a picture though of the first way (with the two momentary switches), the second picture with the on-off-on switch.

And lastly, is my code - hopefully I insert it properly to be seen as code:

//www.elegoo.com
//2016.12.08

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards
// Use two buttons to control servo position.
// First button moves from 0 to 90 degrees
// Second button moves from 90 to 0 degrees

int pos = 16;    // variable to store the servo position

//int ledPinR = 3;
//int ledPinG = 4;
int buttonApin = 9;
int buttonBpin = 10;

byte leds = 0;

void setup() 
{
  //pinMode(ledPinR, OUTPUT);
  //pinMode(ledPinG, OUTPUT);
  pinMode(buttonApin, INPUT_PULLUP);  
  pinMode(buttonBpin, INPUT_PULLUP);  
  myservo.attach(10);  // attaches the servo on pin 9 to the servo object
}

void loop() 
{
  if (digitalRead(buttonApin) == HIGH)
  {
    //digitalWrite(ledPinR, HIGH);
    //digitalWrite(ledPinG, LOW);
  for (pos = 90; pos <= 180; pos += 1) { // goes from 00 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    //delay(1000);                       // waits 15ms for the servo to reach the position
  }
  }
  
  
  if (digitalRead(buttonBpin) == HIGH)
  //else
  {
    //digitalWrite(ledPinR, LOW);
    //digitalWrite(ledPinG, HIGH);
    for (pos = 180; pos >= 90; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    //delay(1500);                       // waits 15ms for the servo to reach the position

  }
  }
}

From what I can tell, the two momentary switches produce the same stuttering if I keep holding the button down. So I think it is how I have the loop coded to read the pin status - high/low. I am very new to coding for arduino but I have quite a bit of general macro and programing experience so I have been trying to figure out if there is a different way I could get the switch status one time to avoid the stuttering vs the polling it seems to be doing. I tried adding a resistor into different connections to see if that would help, but it seems to me that it is just how the code is written - it was intended to work with a momentary switch, not what I am trying to use. Maybe there is a different way to connect the switch to get the status other than the "high / low" method - voltage or something?

Any suggestions would be appreciated.

Hi,
This should help;
switchcirc.jpg
Do you have a DMM?
Tom.. :slight_smile:

(deleted)

Without schematic (doesn't matter if you can draw it perfectly, sketch out the actual components and label them so at least you have an indication of what is connected to what) there is basically no chance to ever make any circuit work.

From your description I can't really understand what you're trying to do but I think it's this:

"I have a switch and a servo. When I switch it in one position, the servo has to move to the 90 degree position, when I switch it to the other position, the servo has to move back to the 0 degree position, and I'm trying to do the same with momentary switches: a press on one turns it to the 0 degree position, a pres on the other to the 90 degree position."

Correct?

That should be quite straightforward to put in a sketch - but only if your wiring is correct, and from the photos no way to tell.

I am working on a schematic now and will upload it later, but I wanted to reply that your understanding is mostly correct as to what i am trying to do.

"I have a switch and a servo. When I switch it in one position, the servo has to move to the 90 degree position, when I switch it to the other position, the servo has to move back to the 0 degree position.”

I did make it work with the momentary seitches already. My problem lies in replacement of the two momentary switches with one on-off-on switch.

I am going to attempt to draw up something and try changing the code per the earlier suggestion and post back later with an update.

Thanks everyone for the suggestions and feedback.

Push buttons: normally wired between a pin and GND, then the pin set to INPUT_PULLUP.

Switch: one pole to Vcc, one pole to GND, switching pole (usually the middle one) to the input pin. Add resistors on both sides of the switch for safety (so in case you set your pin to OUTPUT you won't produce a short).

After that you have two options for the switch: it can read HIGH or LOW - one state is replacement for button 1, the other for button 2.

Your loop can be reduced to this simple oneliner:

void loop() {
  servo.write((digitalRead(switchPin)) ? 90 : 180);
}

I am back and have a crude sketch of what I have now. At least as good as I can do with my current level of understanding. I have also tried changing the "HIGH" to "LOW" in the code which did not work and I also tried to change PIN's on the two switch connections thinking that perhaps I should have not had them connected to a PWM pin. I found a schematic of a nano and tried to figure out what pins were what - I think the ones I had connected were PWM (D9 and D5 on the board) so I tried to move them to D4 and D8 which I think are just Digital without PWM. I am at a loss. I have just confused myself even more. Right now I am thinking that what I am trying to do has to be done a different way. I was trying to figure out a way to put the switch in a different path and have it connected to a pin passing 5V through it when it was switched on and then nothing when not in that one position. Then I could execute the servo code when that pin read 5V (or high) and then go back when it read zero (or lOW). I tried that but either the pins I have connected or setup in my code are't the right pins or I have done something else wrong. The latest code where I tried to change to that approach is shown below as well.

//www.elegoo.com
//2016.12.08

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards
// Use two buttons to control servo position.
// First button moves from 0 to 90 degrees
// Second button moves from 90 to 0 degrees

int pos = 90;    // variable to store the servo position

//int ledPinR = 3;
//int ledPinG = 4;
int buttonApin = 4;
int buttonBpin = 8;

byte leds = 0;

void setup() 
{
  //pinMode(ledPinR, OUTPUT);
  //pinMode(ledPinG, OUTPUT);
  pinMode(buttonApin, INPUT_PULLUP);  
  //pinMode(buttonBpin, INPUT_PULLUP);  
  myservo.attach(10);  // attaches the servo on pin 9 to the servo object
  myservo.write(pos);
}

void loop() 
{
  if (digitalRead(buttonApin) == HIGH)
  {
    //digitalWrite(ledPinR, HIGH);
    //digitalWrite(ledPinG, LOW);
  for (pos = 60; pos <= 150; pos += 1) { // goes from 00 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(1000);                       // waits 15ms for the servo to reach the position
  }
  }
  
  //if (digitalRead(buttonBpin) == LOW)
  else
  //{
    //digitalWrite(ledPinR, LOW);
    //digitalWrite(ledPinG, HIGH);
    for (pos = 90; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(1500);                       // waits 15ms for the servo to reach the position

  }
  }
//}

ServoSchematic.pdf (468 KB)

Powering the servo through the Nano is a bad idea.
The stall current of a servo is most likely higher than the 500mA USB backflow diode and laptop/PC can handle.
And a dipping supply could corrupt and/or restart your Nano.
Power the servo from a separate supply, e.g. four AA batteries, and share grounds.

Make sure your switch/button pins match your sketch.
Leo..

Hi,
The code you posted in post #6, has pins as D4 and D8.
Your circuit diagram shows you are using pins D5 and D9.
This code will only respond to button A input.
What are you expecting the code to do now?
There was nothing wrong with your code in post #1.

Which is it.

Did you try my suggested circuit with the original code in post #1, using pins D3 and D4? (My stuff up)
Pins D9 and D10.
If you make these changes:

 if (digitalRead(buttonApin) == HIGH)
 to

 if (digitalRead(buttonApin) == LOW)
 
and 

 if (digitalRead(buttonBpin) == HIGH)
 to

 if (digitalRead(buttonBpin) == LOW)

Thanks.. Tom.. :slight_smile:

Hi,
Ops circuit.


Tom... :slight_smile:

And with those delays in there any movement is going to be very very very slow.

Steve

Tom - I was using D5 and D9 then as part of my troubleshooting attempts I moved to D4 and D8. I have been updating my code as i move pins on the board. I did try changing code per your suggestion with no luck. I am going to try and power the servo separate power supply and see if it behaves differently. Speed doesn’t bother me - I have no speed requirements- just want it to turn as intended.

SWFanMan:
Tom - I was using D5 and D9 then as part of my troubleshooting attempts I moved to D4 and D8. I have been updating my code as i move pins on the board. I did try changing code per your suggestion with no luck. I am going to try and power the servo separate power supply and see if it behaves differently. Speed doesn’t bother me - I have no speed requirements- just want it to turn as intended.

Fine mate, if the original code worked with the Nano supplying the 5V then it should be okay.
Those little servos are just able to work like that if you don't put a load on the spindle.
Even 4 x AA batteries should be enough, unless you have a 5V plug pack.
Tom.. :slight_smile:

Hi, mate.
Try this code with this circuit, its the circuit you posted.

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards
// Use two buttons to control servo position.
// First button moves from 0 to 90 degrees
// Second button moves from 90 to 0 degrees

int pos;    // variable to store the servo position
int buttonApin = 9;
int buttonBpin = 5

bool buttonAstatus; // stores button state
bool buttonBstatus;

void setup()
{
  pinMode(buttonApin, INPUT_PULLUP);
  pinMode(buttonBpin, INPUT_PULLUP);
  myservo.attach(10);  // attaches the servo on pin 9 to the servo object
}

void loop()
{
  buttonAstatus = digitalRead(buttonApin);
  buttonBstatus = digitalRead(buttonBpin);
  if (buttonAstatus == LOW)
  {
    for (pos = 0; pos <= 90; pos += 1) // goes from 00 degrees to 90 degrees in one degree steps
    {
      myservo.write(pos);              // tell servo to go to position in variable 'pos'
      delay(10);                       // waits 15ms for the servo to reach the position
    }
  }

  if (buttonBstatus == LOW)
  {
    for (pos = 90; pos >= 0; pos -= 1)  // goes from 90 degrees to 0 degrees
    {
      myservo.write(pos);              // tell servo to go to position in variable 'pos'
      delay(10);                       // waits 15ms for the servo to reach the position
    }
  }
}

Tom... :slight_smile:

1 Like

Thanks to TomGeorge and everyone - I think I finally got it. Following the last schematic TomGeorge sent got me 90% of the way there but it was still acting weird. It seemed more code related so I went back and saw the post from wvmarle and changed how I wrote the position for the servo and the combination seems to have worked. Here is my code with all the changes. Thanks again everyone for the feedback and help.

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// Use single on-off-on toggle to control servo position.
// First position moves from X to Y degrees
// Second position moves from Y to X degrees

int pos = 35;    // variable to store the servo position and starting position
int buttonApin = 4;
int buttonBpin = 8;

bool buttonAstatus; // stores button state
bool buttonBstatus;

void setup()
{
  Serial.begin(9600);
  Serial.print("Running v2.0 of Servo controlled by toggle and Nano.");
  pinMode(buttonApin, INPUT_PULLUP);
  pinMode(buttonBpin, INPUT_PULLUP);
  
  buttonAstatus = digitalRead(buttonApin);
  buttonBstatus = digitalRead(buttonBpin);
  Serial.println(buttonAstatus);
  Serial.println(buttonBstatus);
  
  myservo.attach(10);  // attaches the servo on pin 10 to the servo object
}

void loop()
{
  buttonAstatus = digitalRead(buttonApin);
  buttonBstatus = digitalRead(buttonBpin);
  Serial.println(buttonAstatus);
  Serial.println(buttonBstatus);
  
  if (buttonAstatus == LOW)
  {
    myservo.write((digitalRead(10)) ? 45 : 135);
    {
      Serial.print(pos);
    }
  }

  if (buttonBstatus == LOW)
  {
    myservo.write((digitalRead(10)) ? 135 : 45);
    {
      Serial.print(pos);
    }
  }
}

SWFanMan:

    myservo.write((digitalRead(10)) ? 45 : 135);

This just can't be right: pin 10 is the one you have the servo connected to. It doesn't make sense to try and read that very pin and then expect it gives any sensible result for your servo movement.

Hi,
Can you explain exactly what you want your code and circuit to do?
Explain it in step form what you want to happen..

  • If Button1 is pressed, what happens?
  • If Button2 is pressed, what happens?
  • If NO button is pressed, what happens?

Explain it in step form what is happenning.

  • If Button1 is pressed, what happens?
  • If Button2 is pressed, what happens?
  • If NO button is pressed, what happens?

Did you try my code?

Thanks.. Tom.. :slight_smile: