Servo winch always initializes by turning

Hi,

I’m using the servo library that comes with arduino. I have a setup with a servo winch that is capable of turning <360°. Attaching the servo (on pin 9) is no problem. But as soon as I send the first “write” command, my servo does what appears to me are ~2,5 rotations.
Since my setup would mangle all the parts installed, I cannot have this happening. What could be the reason for this strange behaviour?

This is my code-I’m sorry, I prefer you can see everything rather than wasting everyone’s time with snippets that tell only half the truth …

btw: I am using a modelcraft SW 1200 from the German Conrad- online-Store thingy. Unfortunately, there is no documentation available for this online that could be of any value …

#include <Servo.h>
Servo myservo;
int pos = 0; // variable to store the servo position
const int maxServoPos = 45;
boolean gbFirstrun = true;
boolean gbObjectApproached = false;
const int ciIRPin = 4;
const int ciRedPin = 12;
const int ciGreenPin = 7;
const int ciButtonPin = 5;
int iButtonState = 0;
unsigned long ulStartTime = 0;
void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
pinMode(ciRedPin,OUTPUT);
pinMode(ciGreenPin,OUTPUT);
pinMode(ciButtonPin,INPUT);
Serial.begin(9600);
ulStartTime = millis();
Serial.println(“servo attached”);
}
void loop()
{
int iIRVal = 0;
unsigned long ulCurrentTime = 0;
const int ciTolerance = 50;
const int ciLowThreshold = 70;
// start by evaluating the values of the IR-Sensor
// if something approaches, recoil the mat
if (gbFirstrun)
{
ulCurrentTime = millis();
if(ulCurrentTime>=(ulStartTime+12000))
{
// discard all values that are junk data produced by the arduino initializing
gbFirstrun = false;
blink(ciGreenPin,3);
Serial.println(“Arduino initialized, proceeding with evaluation of values”);
}
}
else
{
iIRVal = analogRead(ciIRPin);
Serial.print("iIRVal ");
Serial.println(iIRVal);
if(iIRVal>= ciTolerance + ciLowThreshold) //smooth low values, ignore artifacts
{
gbObjectApproached = true; // set the flag for evaluation during each loop
blink(ciRedPin,1);
Serial.print(“iIRVal within tolerance :”);
Serial.println(iIRVal);
}
iButtonState = digitalRead(ciButtonPin);
if(iButtonState == HIGH)
{
Serial.print(“SIG HUP received, setting servo to zero”);
for(pos; pos >=1; pos -= 1) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable ‘pos’
delay(15); // waits for servo to reach position &/or delays pulses
}
}
else
{
if(gbObjectApproached)
{
Serial.println(“starting servo: fast”);
for(pos = 0; pos < maxServoPos; pos += 1) // goes from 0 degrees to 180 degrees
{
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable ‘pos’
delay(15); // waits for servo to reach position &/or delays pulses
}
for(pos = maxServoPos; pos>=1; pos-=1)
{
if(pos == maxServoPos)
{
Serial.println(“starting servo: slow”);
}
myservo.write(pos);
delay(100+pos*10);
}
}
}
}
}
void blink(int iPin, int iRepeats)
{
for(int i=0;i<=iRepeats;i++)
{
digitalWrite(iPin,HIGH);
delay(250);
digitalWrite(iPin,LOW);
delay(250);
}
}

Many thanks for your help.

bastian

Snippets are better.

If you remove everything in your sketch except the servo positioning code and try that you will have a better idea of what is happening. In fact, try a very simple sketch that just slowly pans the servo from 0 to 180 degrees and see what happens.

You can experiment with a range of angle values to find out what it takes to move your servo. When you know that, you can add back in all the other code and modify it to get the desired angle values. I hope that helps

Snippets are better.

I disagree! I'd prefer to see the whole of the code, because it's usually the bits that the poster has left out that are the cause of the trouble.

I am not familiare with the way servo winches are supposed to work, but are you sure it isnt just moving to the correct "pos" position. Are you physically moving the servo to a particular position before starting your program. If so normal behaviour would be to move to "pos" as soon as the servo code starts. this should be an absolute position, not relative to where you started.

You could test this by starting your code, let the servo move to where it jumps to. Next power everything down. Finally start your code again. See if the servo moves to a "new" position.

I disagree! I'd prefer to see the whole of the code, because it's usually the bits that the poster has left out that are the cause of the trouble.

I was suggesting that the poster remove everything but the servo code to see if he could get the servo working. If he still had a problem then post the simplified code. Are you really disagreeing with that approach?

Its really hard to see the wood from the trees with all the irrelevant logic in the sketch.

Hi,

thanks for the input so far. I have substantially reduced the code:

#include <Servo.h>
Servo myservo;
const int ciRedPin = 12;
void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
pinMode(ciRedPin,OUTPUT);
Serial.begin(9600);
Serial.println(“servo attached”);
}
void loop()
{
blink(ciRedPin,5);
delay(10000);
Serial.println(“starting loop”);
myservo.write(9);
}
void blink(int iPin, int iRepeats)
{
for(int i=0;i<=iRepeats;i++)
{
digitalWrite(iPin,HIGH);
delay(250);
digitalWrite(iPin,LOW);
delay(250);
}
}

The behaviour of the servo is as follows:

when I send arduino the upload code-command, the servo already starts turning, doing it’s 2,5 revs-already very annoying for my setup, but I would figure that this is an issue with the servo itself(any hints on that are welcome …->I’ll try and get the power supply of the servo modified so that it is only connected to +5V once the arduino is set up)

when the servo gets it’s write command, it will once again turn 2,5 (or so) revolutions. It will do so, even if the last command it received was a write to the same position…
I’ll try writing to 0, see where that leads me.

Keep you posted.

Cheers,b.

The behaviour for write(0) is the same as with the write(9) I posted previously. Since there is no block/arrester for the winch servo, I would not really know where to zero the servo manually, either.

I'll give the power on/arduino-setup a shot. If I'm not mistaken, the servo shouldn't budge if my last write was to 0 ...

so now, I give the servo its 5V only after the servo.attach(9) command has been executed. When the power is up, the servo starts it's revolutions again.

I'll try what happens disconnecting the signal as opposed to the 5V, maybe that will get me somewhere...

Well. The behaviour of the servo looks the same to me if I leave 5V & GND connected and only connect the SIG-cable after the Servo.attach command has been exec'd.

I'm completely puzzled. The servo is new, I don't think it fell down or anything. Should be working fine. I'll try a different servo if I get one.

regards, b.

It sounds like the servo is faulty What exactly does the servo do when you run the code posted in #5? It does seem like it moves even with no signal.

My understanding is that winch servos are suposed to turn appx 1.75 revoloutions in each direction. I would expect it to have a hard stop at that point.

Do you think you got a servo with a continuous rotation mod or perhaps a "gearmotor in a servo case" like solarbotics sells. You might even open it up and look and see whether it has a pot on the output shaft. (with the obvious disclamer about taking it apart..)

Also check your voltagt to the servo. I have gotten screwy behavior when my voltage dropped too low. Some servos worked down to 4 volts, but others didnt.

Hi,

there was one obvious error in my script: I did not call the Servo::refresh() command. But now that I'm trying to remedy this, the compiler keeps telling me:

In function 'void loop()': error: 'refresh' is not a member of 'Servo'

strangely, I tried all variations of calling the refresh command, with "myServo" being the name of the instance of the class 'Servo'.

myServo.refresh(); myServo::refresh();

anyone have any idea how to correctly call this function?!! The documentation only states the examples I have tried.

thx.

The voltage on the servo should be 5V directly from the arduino/breadboard. I measure ~5V directly on the connector to the Servo (which is in actual fact a winch-meaning, that it covers more than the 180° of "normal" servos. I wouldn't know of any hardware restrictions regarding the number of degrees it covers. As long as the servo seems to be working, I prefer not opening it-it was a little too expensive for experiments in that direction ... :)

just checked the specs on the servo-it needs 6V. So I'll check it's behaviour with 6V and update what's happening.

regards and thanks for your input so far ...

The servo library that is distributed with Arduino version 0012 does not have or need a refresh method.

Try this code, it should move the servo in steps every ten seconds.

#include <Servo.h> 

Servo myservo;
int position = 0;

void setup() 
{ 
 myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
 Serial.begin(9600);
 Serial.println("servo attached");
 myservo.write(position); 
 delay(10000);
}


void loop() 
{
 position += 10;  
 if(position > 180)
      position = 0;
 Serial.print("changing position to ");
 Serial.println (position);
 myservo.write(position);
 delay(10000);
}

While I haven't yet tried the code you posted, for which I hereby thank you, I did just return from the shop where I bought my servo winch. I had the luck of actually talking to one of the better informed and friendly employees who told me the following: the servo winch SW 1200 (either Pro Line or modelcraft) is controlled differently than regular servos: sending repeated high and low signals of equal length will zero the winch. sending either a longer low and a shorter high or vice versa will turn the servo either [counter-] or clockwise, the ratio of the two determining how far (max 3 rev's per direction) the servo will turn.

While this does not directly solve the mystery of the initial turning, it should help me write basic code [without the use of the servo-library] that will do what I'd like it to ... ;)

I'll try and post my final code here, if anyone's interested ...

Best regards and thanks for all the input. Btw, more out of curiousity: did anyone solve the puzzle about the servo.refresh() command?!

Strange, from that description, it sounds like that servo should be driven by analogWrite instead of using the servo library.

If so, analogWrite of 127 will send repeated high and low signals of equal length.

As the value of analogWrite increases the high pulse is gets longer than the low pulse. As analogWrite decreases in value, the low pulses become longer than the high pulses.

I have not come across this before so I have no idea if this will work, but here is some test code that sends pulses as you have described.

Good luck!

int position = 127; // center the servo

void setup()
{
 Serial.begin(9600);
 Serial.println("centering the servo");
 analogWrite(9, position); // servo attached to pin 9
 delay(10000);
}


void loop()
{
 position += 16;
 if(position >=  255)
      position = 0;
 Serial.print("changing position to ");
 Serial.println (position);
 analogWrite(9, position);
 delay(10000);
}

Btw, more out of curiousity: did anyone solve the puzzle about the servo.refresh() command?!

Did you read my previous post? Refresh is a method not supported or required in the servo library you are using. The hardware timers do the refresh for you.

Hi

I understand that the modelcraft servo sw1200 goes to zero position with 50% PWM. Does the frequency matter? It seems to me that the behavior of the servo isn't smoot in both directions. I used a PWM of 50Hz. The datasheet of the servo I have is rather useless.