Servo Speed
jcferguson
Posts: 86
Does anyone have any ideas about how to control the turning speed of a servo (the "ramp"?) with code instead of a PSC?
I have a program that controls three servos via RF link between joystick/bs2 and servos/bs2. I was thinking of different scenarios where I would read the values from the joystick/bs2 with SERIN, then have a separate subroutine to drive each servo that would compare the actual position of the servo to the SERIN value and progress towards that value in slower steps?
Any thoughts about this? My current code is below if it helps. I think this has to be done on the receiver side, though maybe there are other possibilities?
Carlos
I have a program that controls three servos via RF link between joystick/bs2 and servos/bs2. I was thinking of different scenarios where I would read the values from the joystick/bs2 with SERIN, then have a separate subroutine to drive each servo that would compare the actual position of the servo to the SERIN value and progress towards that value in slower steps?
Any thoughts about this? My current code is below if it helps. I think this has to be done on the receiver side, though maybe there are other possibilities?
Carlos
Comments
PULSOUT 0,move
PAUSE 20
·NEXT
old_pos=move
Carlos, Its not truly ramp but this snippet of code will move a servo from its old position to a new position at a constant speed the speed can be varied or controlled by the value of idx.
Jeff T.
Thanks,
Carlos
You can add in more code for true ramping (acceleration) rather than just speed -- in other words, you could have step increment each time through the loop and the servo will move faster and faster over time. Etc.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
Post Edited (Zoot) : 10/5/2006 10:56:42 PM GMT
I think the missing part in my thinking was MAX and MIN - I couldn't figure out how to make sure the stepping servo didn't overstep the actual position. My code - adaptation of yours - is below. It works nicely (though my servomax and servomin seem to make things jumpy - is there a reason for this you can see).
Carlos
My numbers for above were based on 2us steps for a PSC or a BS2 and would result in 180 degrees of travel min to max. Your servos may not have that physical range. You should adjust these numbers to be safely less than your actual physical limits on the servos.
Someone more expert than me will have to say if the above would really work properly -- I'm not sure about setting max and min in same statement as the pulsout .... you may want to try setting limits on the var before the actual pulsout. In my own implementation of code like this I actually store all the servo limits in EEprom and then read them back by channel so I have single subroutine that a) reads limits for a given servo channel, b) sets limits on that channel's position var, c) sends the resulting corrected position to the proper pin (or PSC servo channel).
Looks like you don't have a pause in your loop at all -- are you possibly overdriving the servos? Given that you are reading your RC info serially, I would think your Stamp would blast through this loop pretty quickly ... maybe too quickly. Most servos seem to handle 20ms-45ms between pulses -- have you tried a straight PAUSE 20 there? You might get less jitter.
Lastly, you might get jumpiness if your stepped values "rollover" but that seems unlikely with your small step size, the range of max and min, and the word size variable.
If none of that does the trick, I may be out of ideas [noparse]:)[/noparse]
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
I wondered about putting the max and min there in the pulsout, but thought maybe it would save a command.
I mess around with that pause and try to get the servos sounding smooth, beyond that it seems like guesswork.
Thanks for the tips, my servos are sllllooooooooowwwwwwwwwwww like I want them.
Carlos
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
Now you know how you can control your servo "sllllooooooooowwwwwwwwwwww", you will maybe help me with my problem?
I have a servo and·I want to turn it from the middel to the·left and right. Fast and slow. The fast movement works but I don't know how you can control it that it moves slowly.
I want to control it slowly to a position. If you read my code you wel see that·I give the servo one pulse by "linksbeetje:" and "rechtsbeetje:" the other cases are fine.
By "linksbeetje:" and "rechtsbeetje:"·I only give one pulsout to the servo and then it turns almost 30 degrees. I want to control it in steps of at most 2 degrees. Is that possible? and does someone nows how you can do this?
So if I pres the Q button of my keyboard the servo moves 2 degrees to the left
Greetings
Ernstjan (Dutch student)
The problem in your code is that when you send pulsout 15, 300 or 15, 1200 you are telling the servo to go all the way to point 1200 (full left) or point 300 (full right). You are sending the same command to your servo if they hit "q" or "a" - pulsout 15, 1200. You just tell it to stay there longer with your for/next loop for "links".
What you actually want to do is tell the servo to go "a little more left" or "a little more right" from the present position, right?
You need to set up a variable for your pulsout value so that you can add a little to the value when you hit "q" and subtract a bit when you hit "e".
In Variables:
ServoValue VAR Word 'this is the value sent out to the servo with the driveservo subroutine
In Constants
DrivePin CON 15 'this is the pin that will drive the servo
LeftExtremeValue CON 1200 'these numbers can be adjusted to set the limits of motion on the servo
MiddleValue CON 750
RightExtremeValue CON 300
ServoIncrement CON 10 'this is the size of your "beetje" steps, can be changed to change step size
Then in the main section:
TakeAction: ' Determines what to do based on result of GetInput
SELECT Command
CASE "1","a"
ServoValue = LeftExtremeValue
Gosub DriveServo
RETURN
CASE "2","s"
ServoValue = MiddleValue
Gosub DriveServo
RETURN
CASE "3","d"
ServoValue = RightExtremeValue
Gosub DriveServo
RETURN
CASE "4","q"
ServoValue = ServoValue + ServoIncrement 'add to the Servovalue, change this for larger or smaller steps
ServoValue = ServoValue MAX LeftExtremeValue 'this keeps you from overshooting the left limit
Gosub DriveServo
RETURN
CASE "5","e"
ServoValue = ServoValue - ServoIncrement
ServoValue = ServoValue MIN RightExtremeValue 'this keeps you from overshooting the right limit
GOSUB DriveServo
RETURN
CASE ELSE
DEBUG " : Invalid Command Received", CR
GOSUB DriveServo 'you still need to tell the servo to stay where it is.
RETURN
ENDSELECT
Then your subroutine would just be this:
DriveServo:
Pulsout DrivePin, ServoValue
Pause 10 'this number should be adjusted slightly to make the servo turn smoothly
Return
I should say I am a learner too. I am not sure if this is what you want it to do -- If this doesn't work, perhaps someone else will give you more guidance!
Carlos
Yes thats what I want to do. I did now that I was sending the servo to it extreem position, and·I tryed it with the feedback you get on yout problem but it didn't work so I have to ask !
Next week·I have a vacation so·I can't test you code, but I think it will be fine.
If I have questions I will post again.
Greeting
Ernstjan