Sail Winch servo help

Hi, i wonder if i can pick some brains.

I’ve currently got two servos to power from my arduino uno board. The first servo (regular 0-180 servo) works as it should. However the second servo doesn’t want to know. The second is the sail winch type that does 4 revolutions instead of 0-180. When i connect the servo in question it moves to it’s starting position as you would expect. When the button is pressed it then moves, as you would expect. However. It then doesn’t return to it’s starting position and subsequent presses of the button do nothing ?

  • Servo is powered by a 6v (1500MaH) NiMh pack
  • Servo/battery shares a ground on the board
  • Switch runs from the 5v input on the board

There’s something wrong with my code that i can’t get my head around

#include <Servo.h>

Servo myservo;
Servo myservo2; 
                
 
const int buttonPin = 2;        // the number of the pushbutton pin 
int pos = 0;                  // variable to store the servo position 
int buttonState = 0;          // variable for reading the pushbutton status

const int buttonPin2 = 3;    // second button input
int pos2 = 1000;             // as above
int buttonState2 = 0;        // as above
 
void setup() 
{ 
  myservo.attach(9);           // attaches the servo on pin 9 to the servo object 
  pinMode(buttonPin, INPUT);   // initialize the pushbutton pin as an input:
  myservo2.attach(8);          // as above
  pinMode(buttonPin2, INPUT);  // as above
} 
 
 
void loop() 
{ 
  buttonState = digitalRead(buttonPin); // read the button state...
  if (buttonState == HIGH)
  {
    if(pos < 50)             // only do servo position increment if it's not already at 50 degrees
   {
     pos += 1;             // increase servo position
     myservo.write(pos);       // tell servo to go to position in variable 'pos' 
     delay(30);                // waits 30ms for the servo to reach the position 
   }
  }
 
  // the below loop runs any time the button isn't pressed
  // it checks the servo position, and if it's greater than 2, moves it back
  
  if(buttonState == LOW)
  {
    if(pos > 2)             // only move the servo back if it's not already at 2
    {
      pos -= 1;             // decrease servo position
     myservo.write(pos);
     delay(30);
   }
  }
  
             /////// BUTTON / SERVO #2 ///////
   
  buttonState2 = digitalRead(buttonPin2); // read the button state...
  if (buttonState2 == HIGH)
  {
    if(pos2 < 1500)             // only do servo position increment if it's not already set
   {
     pos += 1;             // increase servo position
     myservo2.writeMicroseconds(pos2);       // tell servo to go to position in variable 'pos2' 
     delay(15);                // waits 15ms for the servo to reach the position 
   }
  
  
 
  // the below loop runs any time the button isn't pressed
  // it checks the servo position, and if it's greater than 0, moves it back
  
  if(buttonState2 == LOW)
  {
    if(pos2 > 1000)             // only move the servo back if it's not already at 0
    {
      pos -= 1;             // decrease servo position
     myservo2.writeMicroseconds(pos2);
     delay(15);
    }
  }
  }
   
}

thanks for any help

prophet-KGB:

  • Switch runs from the 5v input on the board

Sounds a possible culprit. Normally you would switch to ground and use the built-in
pull-ups. Switch going to +5V requires a pull-down resistor which you haven't mentioned.

Im using the resistor on the negative :blush:

prophet-KGB:
Im using the resistor on the negative :blush:

What does that mean? Draw your switch wiring.

Very simple servo/button code that does not use a resistor.

//zoomkat servo button test 7-30-2011

#include <Servo.h>
int button1 = 4; //button pin, connect to ground to move servo
int press1 = 0;
Servo servo1;

void setup()
{
  pinMode(button1, INPUT);
  servo1.attach(7);
  digitalWrite(4, HIGH); //enable pullups to make pin high
}

void loop()
{
  press1 = digitalRead(button1);
  if (press1 == LOW)
  {
    servo1.write(160);
  }
  else {
    servo1.write(20);
  }
}

prophet-KGB:

The resistor is wired to wrong side of the switch.

retrolefty:

prophet-KGB:

The resistor is wired to wrong side of the switch.

That diagram isn't conclusive - if its meant to be a pictorially
accurate tactile button switch then it is wired correctly.

But it that actually so? The symbol for a switch is abstract, not
a picture of a particular switch for a very good reason. Something
like:

MT:

Your right from a technical point, but I was coming from a practical side as one working a lot with those cheap push buttons. Four terminals for a SPST switch is a real recipe for errors for people that haven't worked with those switches, as most beginners are to arduino/electronics. The best rule when using them is to only make two connections to either diagonal opposite terminals, leave the other two diagonal pins unconnected.

Also you rarely see arduino project use the 100 ohm series protection resistor shown even though it's cheap insurance against brain farts. :wink:

Hi. Yea the picture was mean’t to represent one of the four legged push-buttons you get with the arduino kits. I wanted it to look as it would if you were actually looking at the switch (if you know what i mean)

I use that same setup for my first servo and it works fine ?

I’ve been through and read a different link for another sail winch setup and tried to incorporate it in my code. However regardless of any changes i make i always get the same result; The servo spins when attached to the pin, then spins once, once the button is presses. Any subsequent pushes of the button do nothing. This is the code im working with at the moment. The first servo in the code works fine (and is a regular 0-180 degree servo). The second is a ‘king max SW4805-4PA’ sail winch servo.

As always any feedback, advice or ideas are gratefully received as this is driving me nuts now :0

#include <Servo.h>

#define PWM1_MIN 1000
#define PWM1_MAX 2300

#define PWM_STEP  1

int PWM1 = 1500;      // global stores value of PWM in microseconds



Servo myservo, myservo2; 
                
 
const int buttonPin = 2;        // the number of the pushbutton pin 
int pos = 0;                  // variable to store the servo position 
int buttonState = 0;          // variable for reading the pushbutton status

const int buttonPin2 = 3;    // second button input
int pwm1 = 1000;             // as above
int buttonState2 = 0;        // as above
 
void setup() 
{ 
  myservo.attach(9);           // attaches the servo on pin 9 to the servo object 
  pinMode(buttonPin, INPUT);   // initialize the pushbutton pin as an input:
  myservo2.attach(8, PWM1_MIN, PWM1_MAX);          // as above
  pinMode(buttonPin2, INPUT);  // as above
} 
 
 
void loop() 
{ 
  buttonState = digitalRead(buttonPin); // read the button state...
  if (buttonState == HIGH)
  {
    if(pos < 50)             // only do servo position increment if it's not already at 50 degrees
   {
     pos += 1;             // increase servo position
     myservo.write(pos);       // tell servo to go to position in variable 'pos' 
     delay(30);                // waits 30ms for the servo to reach the position 
   }
  }
 
  // the below loop runs any time the button isn't pressed
  // it checks the servo position, and if it's greater than 2, moves it back
  
  if(buttonState == LOW)
  {
    if(pos > 2)             // only move the servo back if it's not already at 2
    {
      pos -= 1;             // decrease servo position
     myservo.write(pos);
     delay(30);
   }
  }
  
             /////// BUTTON / SERVO #2 ///////
   
  buttonState2 = digitalRead(buttonPin2); // read the button state...
  if (buttonState2 == HIGH)
  {
    if(pwm1 < PWM1_MAX)             // only do servo position increment if it's not already set
   {
     pos += 1;             // increase servo position
     myservo2.writeMicroseconds(pwm1);       // tell servo to go to position in variable 'pos2' 
     delay(15);                // waits 15ms for the servo to reach the position 
   }
  
  
 
  // the below loop runs any time the button isn't pressed
  // it checks the servo position, and if it's greater than 0, moves it back
  
  if(buttonState2 == LOW)
  {
    if(pwm1 > PWM1_MIN)   // only move the servo back if it's not already at 0
    {
      pos -= 1;             // decrease servo position
     myservo2.writeMicroseconds(pwm1);
     delay(15);
    }
  }
  }
   
}

Shouldn't the line (in the section dealing with the sailwinch)

      pos -= 1;             // decrease servo position

be

      pwm1 -= 1;             // decrease servo position

?

...R

Ah yes thanks ! That works. Now i can move the servo in one direction more times than one with multiple button presses. However, it doesn't reset back to it's original position once the button is released (which is what im after) ?

I owe you a drink (and am happy to paypal you a few quid too. Send me your paypal addy if you do)

Thanks, but no money is required. Just pay the system back by helping some other person with some future problem they have.

By the way did you change pos to pwm1 in both places?

...R

Thanks. Not sure how much help i can be but perhaps in the future ?

Yes i’ve changed ‘pos’ for ‘pwm1’, both here :

buttonState2 = digitalRead(buttonPin2); // read the button state…

  • if (buttonState2 == HIGH)*
  • {*
  • if(pwm1 < PWM1_MAX) // only do servo position increment if it’s not already set*
  • {*
  • pos += 1; // increase servo position*
  • myservo2.writeMicroseconds(pwm1); // tell servo to go to position in variable ‘pos2’*
  • delay(15); // waits 15ms for the servo to reach the position*
  • }*

And here :

if(buttonState2 == LOW)

  • {*
  • if(pwm1 > PWM1_MIN) // only move the servo back if it’s not already at 0*
  • {*
  • pos -= 1; // decrease servo position*
  • myservo2.writeMicroseconds(pwm1);*
  • delay(15);*
  • }*

I’m one step closer now as it’ll register multiple button presses. You can either hold the bottom down, or keep pressing to make the servo rotate. However once it gets to it’s ‘final’ position it should rotate back to the starting position, it doesn’t, it sits at the final position until you reset the board.

Perhaps it’ll make a little more sense if i explain exactly what this is all for

I’m a bit of a costumer and am currently installing animatronics in my xenomorph head. The idea is two-fold; To have lips that move and a jaw that opens. The first part of the code runs the lips. This is powered by two servos that pull wires attached to the inside of the latex lips. This part works ok as can be seen in the video here -

The second part of the code, and the sail winch servo are to open/close the mouth. At the rear of the jaw i’ve got a steel cable that runs up inside the head and will spool onto the sail winch. So by pressing a button the servo will spool the cable and pull open the jaw (from the rear of the jaw as it’s hinged). When you release the button it’ll close again (the lower jaw is attached to the upper by a few latex strips that’ll pull it closed once the tension is released).

So that’s where i’m at now :slight_smile:

I presume that “if(buttonState2 == LOW)” is the part that’s meant to make the servo return to the start position?

Have you inserted a Serial.println() so you can tell whether buttonState2 is actually low?

What happens if you swap the logic (temporarily) so that the press makes it go back and the release makes it go forward?

What about using “else” rather than “if(buttonState2 == LOW)” ?

It probably would have been more useful to post the revised code rather than the incorrect code with the errors highlighted?

Your questions lead me to think that you suspect the solution to a programming question is likely to be complicated. 90% of problems are stupidly simple. You just need to note carefully what behaviour is actually happening, think about what might cause that behaviour and think about how you can test that your program is doing what you think it’s doing.

…R

Thanks for the tips. I’ll try ‘else’ instead of ‘button = low’

Hmmm i’ve just actually put a mark on the servo spindle so i can watch it properly.

  • When you attach the servo to the board it rotates anti-clockwise approximately one-and-a-half spins
  • When you first press the button it rotates anti-clockwise also to it’s start point
  • When you press the button after it’ll move to it’s finish point

So for some reason the first button press will set it to it’s start point but subsequent presses will move it forwards. However it doesn’t reset once at the final position

This is the revised code

#include <Servo.h>

#define PWM1_MIN 1000
#define PWM1_MAX 2000

#define PWM_STEP  1

int PWM1 = 1000;      // global stores value of PWM in microseconds



Servo myservo, myservo2; 
                
 
const int buttonPin = 2;        // the number of the pushbutton pin 
int pos = 0;                  // variable to store the servo position 
int buttonState = 0;          // variable for reading the pushbutton status

const int buttonPin2 = 3;    // second button input
int pwm1 = 1000;             // as above
int buttonState2 = 0;        // as above
 
void setup() 
{ 
  myservo.attach(9);           // attaches the servo on pin 9 to the servo object 
  pinMode(buttonPin, INPUT);   // initialize the pushbutton pin as an input:
  myservo2.attach(8, PWM1_MIN, PWM1_MAX);          // as above
  pinMode(buttonPin2, INPUT);  // as above
} 
 
 
void loop() 
{ 
  buttonState = digitalRead(buttonPin); // read the button state...
  if (buttonState == HIGH)
  {
    if(pos < 50)             // only do servo position increment if it's not already at 50 degrees
   {
     pos += 1;             // increase servo position
     myservo.write(pos);       // tell servo to go to position in variable 'pos' 
     delay(30);                // waits 30ms for the servo to reach the position 
   }
  }
 
  // the below loop runs any time the button isn't pressed
  // it checks the servo position, and if it's greater than 2, moves it back
  
  if(buttonState == LOW)
  {
    if(pos > 2)             // only move the servo back if it's not already at 2
    {
      pos -= 1;             // decrease servo position
     myservo.write(pos);
     delay(30);
   }
  }
  
             /////// BUTTON / SERVO #2 ///////
   
  buttonState2 = digitalRead(buttonPin2); // read the button state...
  if (buttonState2 == HIGH)
  {
    if(pwm1 < PWM1_MAX)             // only do servo position increment if it's not already set
   {
     pwm1 += 5;             // increase servo position
     myservo2.writeMicroseconds(pwm1);       // tell servo to go to position in variable 'pwml' 
     delay(15);                // waits 15ms for the servo to reach the position 
   }
  
  
 
  // the below loop runs any time the button isn't pressed
  // it checks the servo position, and if it's greater than 0, moves it back
  
  if(buttonState2 == LOW)
  {
    if(pwm1 > PWM1_MIN)   // only move the servo back if it's not already at 0
    {
      pwm1 -= 5;             // decrease servo position
     myservo2.writeMicroseconds(pwm1);
     delay(15);
    }
  }
  }
   
}

Put some Serial.println() commands into your code so that you can follow what it is doing and what value the important variables have.

You have to do some of the work :slight_smile:

...R

Of course :). I'm not trying to get spoon-fed. Just thought that if i post up the code then someone with a lot more knowledge than me might take one look at it and say 'It's this'. I'll keep tinkering :slight_smile:

Your braces are the problem: the test for button2 being low is inside the test for it being high - it will never be executed.

Well done! I was suspicious of the braces but I didn't spot that. One more reason to dislike C.

...R