Go Down

Topic: Servo winch always initializes by turning (Read 2851 times) previous topic - next topic

bastian10

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 ...

[glow]
#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);
 }
}
[/glow]



Many thanks for your help.

bastian

mem

#1
Jan 26, 2009, 05:30 pm Last Edit: Jan 26, 2009, 05:30 pm by mem Reason: 1
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

Anachrocomputer

Quote
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.

drspectro

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.

mem

#4
Jan 27, 2009, 05:38 am Last Edit: Jan 27, 2009, 05:41 am by mem Reason: 1
Quote
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.

bastian10

Hi,

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

[glow]#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);
 }
}

[/glow]


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.

bastian10

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 ...

bastian10

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...

bastian10

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.

mem

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.

drspectro

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.  

bastian10

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.

bastian10

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 ...
:)

bastian10

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 ...

mem

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.

Code: [Select]
#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);
}

Go Up