PDA

View Full Version : Continuous Rotation Servo



Somnium
10-16-2006, 03:39 AM
I'm testing out my servos i got form Parallax and have been having slight difficulty. I'm using the Servo-4 object from the Object Exchange and have been fiddling it to try and move only a certain angle and repeat when necessary... All i have so far are just more questions... Is it possible to move it only a certain angle, such as 30, pause, then do it again?

MacGeek117
10-16-2006, 03:45 AM
I would suggest using the BS2_Functions object from the Object Library. The PULSOUT routine would be best.
RoboGeek

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
"I reject your reality and subsitute my own!"

Adam Savage, Mythbusters
www.parallax.com (http://www.parallax.com/)
www.goldmine-elec.com (http://www.goldmine-elec.com)
www.expresspcb.com (http://www.expresspcb.com)
www.startrek.com (http://www.startrek.com)
·

Mike Green
10-16-2006, 03:59 AM
With continuous rotation servos, you only have control of speed and direction. You only have coarse control of distance (or angle) through timing (move slowly in one direction for a certain number of milliseconds, then stop). There's no inherent feedback on distance (or angle) travelled. If you use conventional servos, the pulse width directly corresponds to position, but you're limited to maybe 270 degrees of rotation.

With the continuous rotation servos, you could use the Servo-4 routines, put out a pulse for rotation in the direction you want (every 10-20ms) adjusting the pulse frequency so it's a submultiple of the time you want the servo to move (if the servo needs to move 250ms, put out 25 pulses, every 10ms, each pulse maybe 1.25ms wide (or 1.75ms wide for the other direction), then change the pulse width to 1.5ms to stop the motor.

Post Edited (Mike Green) : 10/15/2006 9:05:26 PM GMT

Paul Baker
10-16-2006, 04:18 AM
Somnium, servos cannot provide angular precision and be fully rotational, however by using an encoder, it is possible to provide feedback to the continuous rotation servo's angular position.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker (mailto:pbaker@parallax.com)
Propeller Applications Engineer
[/url][url=http://www.parallax.com] (http://www.parallax.com)
Parallax, Inc. (http://www.parallax.com)

Somnium
10-16-2006, 06:18 AM
very much appreciated guys thanx

Somnium
10-16-2006, 08:43 AM
umm... hmm... having problems understanding the "pulse" fuctions in the BS2_Functions Object... how does it exactly work?

Somnium
10-17-2006, 10:07 PM
CON

_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000

button = 22
servo1 = 3
servo2 = 1

OBJ
SERVO : "Servo4"

PUB go | unit0
dira[button] := 0
dira[servo1] := 1
dira[servo2] := 1

if button == 1
servo.start(1000,0,1000,1,1500,2,1000,3)
unit0 := 1
repeat
servo.move_to(3,2000,50)
servo.move_to(1,2000,50)
else
servo.move_to(3,0,0)
servo.move_to(1,0,0)




Here's the code I have so far... what do you think should happen? Cause it's not doing what I'm hopin wud happen...

Mike Green
10-17-2006, 10:26 PM
1) Move the "servo.start" to before the "IF" statement. It has to be executed before any other calls to the servo4 object.

2) Since you're only using two servos at the moment, disable the other 2 slots by using zero as a pulse width as described in the comments in Servo4 (like "servo.start(1500,servo1,1000,servo2,0,0,0,0)")

3) Doing a repeat of the "servo.move_to" won't do what you might expect. Once you specify a new position, the Servo4 routines work in parallel to control the servos. The "servo.wait" call is intended to make your program wait until the movement is done.

4) You really have to read the documentation (as limited as it may be) on the routines you're using and make sure you understand it. If you have questions about what things mean, do ask

Somnium
10-17-2006, 10:37 PM
the if statement I wrote... should it work or is there something that I'm missing?... When it's put onto the propeller it doesn't move when I press it... when i press it a couple of times it move the slightest amount then stops...

Mike Green
10-17-2006, 10:47 PM
The IF statement as you wrote it only executes once when the Propeller starts. That would be fine if you had a toggle switch and wanted to do one of two things when you reset the Propeller based on the setting of the switch. It won't do what it sounds like you want ... continually test the pushbutton switch and do something when the pushbutton is pushed.

It sounds like you should read the "What's a microcontroller?" tutorial that's downloadable from the Parallax website. It's written for the Stamp processors, but the same basics apply to the Propeller and the tutorial has plenty of examples. It might be a good exercise for you to translate them for the Propeller. Just be careful about the circuit diagrams. They all show things connected to +5V because that's what the Stamps use. For the Propeller, that should be the +3.3V supply. There are some resistors shown in many of the circuits, usually their values are not critical and they should work fine on the lower supply voltage.

Somnium
10-18-2006, 01:20 AM
i'm still confused why this isn't working??




CON

_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000

button = 22
servo1 = 3
servo2 = 1
PUB go | pin
dira[button] := 0
dira[servo2] := 1

repeat 10
if dira[button] := 0
repeat
OutA[servo2] := 1 'LED ON
WaitCnt(8_000_000 + Cnt)
OutA[servo2] := 0 'LED OFF
WaitCnt(8_000_000 + Cnt)
else
OutA[servo2] := 0





I've switched it to LED to make it somewhat easier... still no progress...

I'm also still having problems adjusting the amount it moves... how do I use the PULSEOUT object? I've tried and nothin worked


Mike said...
With the continuous rotation servos, you could use the Servo-4 routines, put out a pulse for rotation in the direction you want (every 10-20ms) adjusting the pulse frequency so it's a submultiple of the time you want the servo to move (if the servo needs to move 250ms, put out 25 pulses, every 10ms, each pulse maybe 1.25ms wide (or 1.75ms wide for the other direction), then change the pulse width to 1.5ms to stop the motor.
[code]

Post Edited (Somnium) : 10/17/2006 6:42:20 PM GMT

Beau Schwabe (Parallax)
10-18-2006, 01:56 AM
I think...




if dira[button] := 0




..should read...




if ina[button] == 0


▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe (mailto:bschwabe@parallax.com)

IC Layout Engineer
Parallax, Inc.

Somnium
10-18-2006, 02:39 AM
nope... nothin...

Graham Stabler
10-18-2006, 02:40 AM
Beau is right,

== means is equal too
:= means make equal to

and

dira is a register that is used to set the pins to be outputs or inputs

ina is the register that contains the state of the pins (whether they are defined as inputs or outputs) it does not control them.

outa is a register used to write to output pins

When stuck first read the definitions of the commands and registers you are using, this information cannot be known without reading about it.

knowledge is power and reading provides knowledge.

Graham

Graham Stabler
10-18-2006, 02:41 AM
You have a repeat of 10, what will happen if the button is not pressed within those 10 loops (that will take all of no time)

Graham

Somnium
10-18-2006, 02:44 AM
... I'm sorry guys but my head is about to freakin explode... I've been trying to get this thing to work for way too long and still no promising outcome... I know I'm sounding like some whiney·[expletive] but could someone get me code for:

Button that moves a servo
Continuous Rotation servo that moves a certain amount with time

these are all i need... plz I'm getting desperate... I'm still learning this in my class and thought I could do something with it for another class and apparently i'm not capable of it yet... If anyone could help me I'll be ever so grateful... I will learn to do this on my own some time in the near future... but i need this done by thursday and with my brain, i just won't be able to do this...

sorry guys... i feel like i failed u guys... failed the propeller...

Post Edited By Moderator (Chris Savage (Parallax)) : 10/19/2006 9:33:32 PM GMT

Graham Stabler
10-18-2006, 03:06 AM
Its only tuesday

Read about the if statement
Read about the repeat statement

UNTIL YOU GET THEM

Think about what you want your program to do. Remember it does it step by step and it only does what you tell it.

Don't just keep trying things, your program working is based on cold hard logic.

You can do this and if you do you will get the credit you deserve, ditto if you don't.

Graham

Somnium
10-18-2006, 03:30 AM
ok... the last code i submitted was completely wrong and i only figured that out just now... i've got the servos back on and have it revised...




CON

_clkmode = xtal1 + pll16x 'Sets the clock speed to 80 MHz using a times 16 multiplier
_xinfreq = 5_000_000 'Crystal speed: 5 MHz

Button = 22 'Input Pin
ServoPin1 = 1
ServoPin2 = 3 'Output Pin
'
OBJ
SERVO : "Servo4"

PUB START
Button_1

PUB Button_1 | unit0

Dira[Button] := 0 'Make Button pin an INPUT
Dira[ServoPin1] := 1
Dira[ServoPin2] := 1 'Make LED pin an OUTPUT

servo.start(0,0,1000,1,0,0,1000,3)
unit0 := 1
repeat
if Ina[Button] == 1
servo.move_to(3,1500,10)
servo.move_to(1,800,10)
servo.move_to(3,0,0)
servo.move_to(1,0,0)
else
servo.move_to(3,0,0)
servo.move_to(1,0,0) 'move one at a time




to my knowledge i don't see anything wrong... or at least that's what I think... only thing it does so far is that when i press the button a couple of times, the servos move in small increments...

James Long
10-18-2006, 03:46 AM
try this:



servo.move_to(3,1500,50)

servo.move_to(1,800,50)

WaitCnt(8_000_000 + Cnt)

I think the servos are not having enough time to move....but I'm guessing.

James L

Somnium
10-18-2006, 04:03 AM
yeah i've thought of that... tried it and nothin... there's even a "wait" object in the Servo4 object, which also doesn't work...


Mike Green said...
With the continuous rotation servos, you could use the Servo-4 routines, put out a pulse for rotation in the direction you want (every 10-20ms) adjusting the pulse frequency so it's a submultiple of the time you want the servo to move (if the servo needs to move 250ms, put out 25 pulses, every 10ms, each pulse maybe 1.25ms wide (or 1.75ms wide for the other direction), then change the pulse width to 1.5ms to stop the motor.


how would i go about doing that??

Post Edited (Somnium) : 10/17/2006 9:07:32 PM GMT

Graham Stabler
10-18-2006, 04:05 AM
Firstly I would try running the servo demo program servo4_demo with your modified start values just to make sure all it well.

Then look at the servo move example more closely, it would seem that you really need to use the:

servo.wait command to give the servos chance to move.

In the servo object there is a function that just produces pulses, the servo.move_to commands just modify the variables than this function uses, if you have them in a repeat loop with no delay or servo.wait function they will never actually be able to respond to the new pulse length.

Graham

p.s. good job on getting the loops sorted!

Mike Green
10-18-2006, 04:06 AM
The other thing you can do is to put a "servo.wait(1)" and a "servo.wait(3)" after each pair of "servo.move_to" statements.
That would make sure that the servos have finished moving before trying to do something else with them. James makes a
good point. There's only a couple of hundred microseconds between when you tell the servos to move (the first two
"servo.move_to"s) and when you tell them to stop and turn off (the second set of calls).

Somnium
10-18-2006, 04:08 AM
Mike Green said...
The other thing you can do is to put a "servo.wait(1)" and a "servo.wait(3)" after each pair of "servo.move_to" statements.
That would make sure that the servos have finished moving before trying to do something else with them. James makes a
good point. There's only a couple of hundred microseconds between when you tell the servos to move (the first two
"servo.move_to"s) and when you tell them to stop and turn off (the second set of calls).


Thats exactly what i tried out... but no effect...

Graham Stabler
10-18-2006, 04:09 AM
Can we see that code!

please try my demo suggestion also

Somnium
10-18-2006, 04:15 AM
whoops my bad... here's the code... i also tired the version of the servo demo with my modifications... even with the cycle to one it continues... doesn't seem to stop...



CON

_clkmode = xtal1 + pll16x 'Sets the clock speed to 80 MHz using a times 16 multiplier
_xinfreq = 5_000_000 'Crystal speed: 5 MHz

Button = 22 'Input Pin
ServoPin1 = 1
ServoPin2 = 3 'Output Pin
'
OBJ
SERVO : "Servo4"

PUB START
Button_1

PUB Button_1 | unit0

Dira[Button] := 0 'Make Button pin an INPUT
Dira[ServoPin1] := 1
Dira[ServoPin2] := 1 'Make LED pin an OUTPUT

servo.start(0,0,1000,1,0,0,1000,3)
unit0 := 1
repeat
if Ina[Button] == 1
servo.move_to(3,1500,1)
servo.move_to(1,1500,1)
servo.wait(3)
servo.wait(1)
servo.move_to(3,0,0)
servo.move_to(1,0,0)
else
servo.move_to(3,0,0)
servo.move_to(1,0,0) 'move one at a time

Joel Rosenzweig
10-18-2006, 04:22 AM
Here's my advice:

Stop using the modified servo temporarily.· You can make that work later.·

Focus on writing a simple program that can output a pulse of a given·duration.· Once you have mastered that concept, it will be a trivial matter to modify the code to output any duration you want.· And once you master that, it will be easy to modify the code so that it outputs this pulse in response to your button presses.

A standard servo will go the neutral position if given a positive pulse with a duration of 1.5ms.· Full deflection one way is about 2.0ms, and full deflection the other way is about 1.0ms.· A standard servo needs a pulse every 20ms.·

Pseudo code for controlling a standard servo looks like this:

' send a servo a pulse width of X ms

repeat
· set pin high
· wait for X ms to elapse
· set pin low
· wait for 20 ms - X ms time to elapse

Once you get this going, you can experiment by changing the value of X, and see that the servo position changes proportionally to X.

For a continuous rotation servo,·the servo always believes its in the wrong position, and it will move provided you give it a pulse that is something other than its neutral position pulse width (about 1.5ms).· This value will depend on the method you used to make the continuous rotation servo.

So, let's say you've mastered how to send any pulse width out to the servo.· Now you can put your continuous rotation servo back in, and try sending it a non-neutral pulse (something other than about 1.5ms, say 2.0ms).· And you should see the servo move continuously in one direction.· If you give it a 1.0ms pulse, it should move continuously in the opposite direction.

You still need to update the servo with a new pulse every 20ms or else the servo won't move continuously.· If you give it a pulse infrequently, the servo will move, then stop, then move, then stop, with whatever granularity you actually provided the pulses.· So, for your application, you might choose to send a non-neutral pulse for several seconds, or whatever you want, before you stop sending that stream of pulses.· The key is that your pulses will cause the servo the move.· If you don't send the pulse train, the servo won't go anywhere.

Spin code for setting the pin high, waiting, then setting it low looks like the following:

·····outa[1] := 1· 'pick the pin you really want
···· waitcnt(X·+ cnt) 'make sure to put X into the right units, depends on the speed of·your device, and you can calculate it if you want.
···· outa[1] := 0
See if you can figure out the rest..

Joel-

·

Graham Stabler
10-18-2006, 04:27 AM
OK,

try this, with nothing else




repeat
servo.move_to(1,1500,1)
servo.wait(1)




And try different values instead of 1500. On a continuous rotation servo I think 1500 should stop it rotating but it might need to be 1520 or something, just have a play.

Turning the servo off may not stop it.

Graham

Somnium
10-18-2006, 04:31 AM
argh... got class soon... i'll test out what you guys said... thanx fo the input so far... i'll brb

Somnium
10-18-2006, 06:56 AM
repeat
servo.move_to(1,1500,1)
servo.wait(1)



umm... hmm... is it normal for it to go in the direction and keep going? I've tried inputtin different numbers into the "servo.move_to(1,X,1)" and it does the same thing...

Paul Baker
10-18-2006, 06:58 AM
Have you centered your servo?

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker (mailto:pbaker@parallax.com)
Propeller Applications Engineer
[/url][url=http://www.parallax.com] (http://www.parallax.com)
Parallax, Inc. (http://www.parallax.com)

Somnium
10-18-2006, 07:06 AM
ok hold up n/m... i've put numbers in and determined that from 1164 - 1155 there is no movement... anythin lower spins it clockwise, anythin higher spins it C-clockwise... doesn't stop yet though...

Somnium
10-18-2006, 07:58 AM
OK!... i know how to control the position of the standard servo! Woot!... but have no idea how to do it with the continuous servo... and still no idea how to incorporate the button

Somnium
10-18-2006, 08:34 AM
more progress through experimentation... continuous servo seems to run and stop eventually, but doesn't stop at specific points... will need to work on this more...

-edit-

furthur experimentation... continuous servo doesn't seem to follow rules... or its supposed to do that...

Initial Position Position change Outcome Angle
2000 1900 720ish
1598 1000 270 then back 180
1598 500 190 then back 360
2000 1000 540 then back 90

is this normal or is there something wrong?

Post Edited (Somnium) : 10/18/2006 1:42:49 AM GMT

James Long
10-18-2006, 08:41 AM
more progress through experimentation... continuous servo seems to run and stop eventually, but doesn't stop at specific points... will need to work on this more...
That is one problem associated with a continuous servo. The stopping point has to do with the timing of your program....not the servo itself. The servo rotates in the desired direction (depending on the pulse) until you tell it to stop.

A regular servo only positions itself to the pulse length. But it can not go in a full revolution.......so there are trade offs for each type.

James L

Joel Rosenzweig
10-18-2006, 08:44 AM
Somnium,

A continuous rotation servo will do exactly that.· You give it a pulse that is non-neutral (other than about 1.5ms) and it will rotate continuously, provided you keep giving it pulses every 20ms.· If you give it pulse > neutral pulse, you get a rotation in one direction.· If you give it a pulse < neutral position, it goes the other direction.· These devices are no longer really "servos".· They're more like traditional motors when used this way, with a special front end.· These modified servos will not stop at specific points.· The best you can do is to stop them at specific times, which you will extrapolate to a certain amount of angular rotation.· If you need it to stop at a specific angle of rotation, you need to add an external shaft encoder.· Otherwise, you're back to using an unmodified servo. ;-)

The unmodified servos will go to a specified position, directly proportional to the pulse width that you give it, from 1.0 to 2.0ms, extreme to extreme.

If you want to stop a continuous rotation servo, you need to send it a neutral pulse.· and if you want to lock it there, you have to continue to send neutral pulses every 20 ms.·

If you want to move a continuous rotation servo just a little bit, that means you have to send it non-neutral pulses for a certain amount of time.· It will move for as long as you keep giving it these pulses, spaced 20ms apart.· The magnitude of the pulse determines the direction of rotation.· See above.·

Joel-
·

Somnium
10-18-2006, 08:51 AM
what is this shaft encoder? hmm... oh jeez... that's a seperate part... urgh... guess its more experimentation... http://forums.parallax.com/images/smilies/cry.gif

Joel Rosenzweig
10-18-2006, 09:01 AM
A shaft encoder is a device that outputs a series of pulses as the shaft it is connected to spins. Some shaft encoders output a pulse train using quadrature output (2 signals, 4 values) that can be used to determine relative direction of rotation. Others output a discreet word that describes absolute position.

Don't worry about this.. this isn't what you need for your project. I think you need to step back and figure out what you are really trying to accomplish. Earlier in the thread, you stated that you knew how to move a standard servo, and a continuous rotation servo. So, now that you have both building blocks working, you should be good to go, right? Is the success that you stated above an accurate statement, or do you still have issues getting either to work?

Joel-

Somnium
10-18-2006, 09:03 AM
sweet!! ok i got it to move like 1 degree stop and repeat... i know how to modify this so i'm gud... i just need to figure out the button portion of the code now http://forums.parallax.com/images/smilies/yeah.gif
u have no idea how happy I am... thanx fo all the help... not there yet but getting there

James Long
10-18-2006, 09:07 AM
Glad you got it moving....now on to more complex things...and keyboard head banging.



James L

Somnium
10-18-2006, 09:31 AM
hehe oh goodie... thats all a little 2day and all of 2morrow... whoop di doo... http://forums.parallax.com/images/smilies/shakehead.gif

James Long
10-18-2006, 10:41 AM
Hey....remember we think this is fun!!· http://forums.parallax.com/images/smilies/devil.gif



James L

Beau Schwabe (Parallax)
10-18-2006, 11:41 AM
Somnium,

Just remember that we have all been there. You must have patience and your results will eventually pay off.
The caveat is that once you are bitten by the bug it is usually here to stay, creating more and more challenges
for you to overcome along the way. Have fun!! enjoy the ride!!

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe (mailto:bschwabe@parallax.com)

IC Layout Engineer
Parallax, Inc.

Somnium
10-19-2006, 01:15 AM
Umm... hmm... here's what i have so far...




CON

_clkmode = xtal1 + pll16x 'Sets the clock speed to 80 MHz using a times 16 multiplier
_xinfreq = 5_000_000 'Crystal speed: 5 MHz
button = 22
servo1 = 1
servo2 = 3
'
OBJ
SERVO : "Servo4"

PUB START
Button_1

PUB Button_1 | unit0
servo.start(0,0,1000,1,0,0,1000,3)
Dira[button] := 0
Dira[servo1] := 1
Dira[servo2] := 1

If Ina[button] == 1
servo.wait(1)
servo.wait(3)
servo.move_to(1,700,42)
servo.move_to(3,700,42)
servo.wait(1)
servo.wait(3)
servo.move_to(1,65,0)
servo.move_to(3,65,0)
servo.wait(1)
servo.wait(3)
else
servo.wait(1)
servo.wait(3)
servo.move_to(1,65,0)
servo.move_to(3,65,0)




button isn't workin still... i also came upon a problem... I'm makin this convier (don't know how to spell it) belt and apparently i didn't make them with even space... there are ten spaces... is it possible to make it move a certain amount for each time pressed?... like the first time it's some amount then the second time a different amount... then repeat for every ten

Somnium
10-19-2006, 01:41 AM
i have a thought of how to do the code i want but unsure as to how... i'll say it verbally

Button pushed add 1 to "X"
check "X" and move servo dependent on that number
When "X" reaches 10 erase and repeat over

I'm so confused as to how to do this... help plz!

Graham Stabler
10-19-2006, 01:46 AM
You need a repeat in your button_1 routine otherwise it will check the button and finish instantly.

The repeat should be before the if statement so it will keep checking the button, if it is pressed it will do one thing otherwise it will do the other.

Graham

Somnium
10-19-2006, 04:17 AM
alright sweet... got the button to react with the servo... now i need help with this portion...



I'm makin this convier (don't know how to spell it) belt and
apparently i didn't make them with even space... there are
ten spaces... is it possible to make it move a certain amount
for each time pressed?... like the first time it's some amount
then the second time a different amount... then repeat for
every ten



any ideas and thoughts would be great

Mike Green
10-19-2006, 05:16 AM
With the continuous rotation servos, you can't reliably get them to move the same amount every time you activate them (to move your conveyor belt [conveys stuff down the road or whatever]). If you need reliable positioning, you will need an external encoder of some kind. Look at Parallax's encoder for the BOE-BOT <http://www.parallax.com/detail.asp?product_id=28107>. This just counts the number of wheel holes that move by a sensor, but can provide fairly accurate wheel positioning data. You could attach a sensor belt to your conveyor belt, just a fabric or plastic/rubber strip with holes evenly spaced where you want the belt to stop. An IR sensor near your servo motor could sense when a hole comes by and cause the Propeller to stop the servo right there.

Phil Pilgrim (PhiPi)
10-19-2006, 06:06 AM
You could also put marks on the conveyor belt, and use an optical sensor to detect them. It sounds as if your belt is separated into zones or pockets. You could just have one mark per pocket, and program the Prop to stop when it sees the mark. If the belt will be used in a dirty industrial environment, holes would be better than marks, or even small magnets used with Hall-effect sensors or reed switches.

-Phil

Somnium
10-19-2006, 07:55 AM
umm... well... here's the thing... 9 out of 10 of them are evenly spaced... one is off... i'll do some more modifications and see what happens... i do have a photo resistor... mayb i cud try and use that somehow...