Shop OBEX P1 Docs P2 Docs Learn Events
Continuous Rotation Servo — Parallax Forums

Continuous Rotation Servo

SomniumSomnium Posts: 46
edited 2006-10-19 00:55 in Propeller 1
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?
«1

Comments

  • MacGeek117MacGeek117 Posts: 747
    edited 2006-10-15 20:45
    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
    www.goldmine-elec.com
    www.expresspcb.com
    www.startrek.com
    ·
  • Mike GreenMike Green Posts: 23,101
    edited 2006-10-15 20:59
    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 BakerPaul Baker Posts: 6,351
    edited 2006-10-15 21:18
    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
    Propeller Applications Engineer

    Parallax, Inc.
  • SomniumSomnium Posts: 46
    edited 2006-10-15 23:18
    very much appreciated guys thanx
  • SomniumSomnium Posts: 46
    edited 2006-10-16 01:43
    umm... hmm... having problems understanding the "pulse" fuctions in the BS2_Functions Object... how does it exactly work?
  • SomniumSomnium Posts: 46
    edited 2006-10-17 15:07
    CON
    
      _CLKMODE = XTAL1 + PLL16X
      _XINFREQ = 5_000_000
    
      button = 22
      servo1 = 3
      servo2 = 1
    
    OBJ
      SERVO : "Servo4"
    
    PUB go | unit0
      dira[noparse][[/noparse]button] := 0
      dira[noparse][[/noparse]servo1] := 1
      dira[noparse][[/noparse]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 GreenMike Green Posts: 23,101
    edited 2006-10-17 15:26
    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
  • SomniumSomnium Posts: 46
    edited 2006-10-17 15:37
    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 GreenMike Green Posts: 23,101
    edited 2006-10-17 15:47
    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.
  • SomniumSomnium Posts: 46
    edited 2006-10-17 18:20
    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[noparse][[/noparse]button] := 0
      dira[noparse][[/noparse]servo2] := 1
    
      repeat 10
        if dira[noparse][[/noparse]button] := 0
          repeat
            OutA[noparse][[/noparse]servo2] := 1         'LED ON                                      
            WaitCnt(8_000_000 + Cnt) 
            OutA[noparse][[/noparse]servo2] := 0          'LED OFF
            WaitCnt(8_000_000 + Cnt)
        else
          OutA[noparse][[/noparse]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.
    [noparse][[/noparse]code]

    Post Edited (Somnium) : 10/17/2006 6:42:20 PM GMT
  • Beau SchwabeBeau Schwabe Posts: 6,547
    edited 2006-10-17 18:56
    I think...

    if dira[noparse][[/noparse]button] := 0
    
    



    ..should read...

    if ina[noparse][[/noparse]button] == 0
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • SomniumSomnium Posts: 46
    edited 2006-10-17 19:39
    nope... nothin...
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2006-10-17 19:40
    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 StablerGraham Stabler Posts: 2,507
    edited 2006-10-17 19:41
    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
  • SomniumSomnium Posts: 46
    edited 2006-10-17 19:44
    ... 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·[noparse][[/noparse]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 StablerGraham Stabler Posts: 2,507
    edited 2006-10-17 20:06
    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
  • SomniumSomnium Posts: 46
    edited 2006-10-17 20:30
    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[noparse][[/noparse]Button] := 0           'Make Button pin an INPUT
      Dira[noparse][[/noparse]ServoPin1] := 1
      Dira[noparse][[/noparse]ServoPin2] := 1           'Make LED pin an OUTPUT
    
      servo.start(0,0,1000,1,0,0,1000,3)
      unit0 := 1
      repeat
        if Ina[noparse][[/noparse]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 LongJames Long Posts: 1,181
    edited 2006-10-17 20:46
    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
  • SomniumSomnium Posts: 46
    edited 2006-10-17 21:03
    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 StablerGraham Stabler Posts: 2,507
    edited 2006-10-17 21:05
    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 GreenMike Green Posts: 23,101
    edited 2006-10-17 21:06
    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).
  • SomniumSomnium Posts: 46
    edited 2006-10-17 21:08
    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 StablerGraham Stabler Posts: 2,507
    edited 2006-10-17 21:09
    Can we see that code!

    please try my demo suggestion also
  • SomniumSomnium Posts: 46
    edited 2006-10-17 21:15
    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[noparse][[/noparse]Button] := 0           'Make Button pin an INPUT
      Dira[noparse][[/noparse]ServoPin1] := 1
      Dira[noparse][[/noparse]ServoPin2] := 1           'Make LED pin an OUTPUT
    
      servo.start(0,0,1000,1,0,0,1000,3)
      unit0 := 1
      repeat
        if Ina[noparse][[/noparse]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 RosenzweigJoel Rosenzweig Posts: 52
    edited 2006-10-17 21:22
    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[noparse][[/noparse]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[noparse][[/noparse]1] := 0
    See if you can figure out the rest..

    Joel-

    ·
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2006-10-17 21:27
    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
  • SomniumSomnium Posts: 46
    edited 2006-10-17 21:31
    argh... got class soon... i'll test out what you guys said... thanx fo the input so far... i'll brb
  • SomniumSomnium Posts: 46
    edited 2006-10-17 23:56
    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 BakerPaul Baker Posts: 6,351
    edited 2006-10-17 23:58
    Have you centered your servo?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
    Propeller Applications Engineer

    Parallax, Inc.
  • SomniumSomnium Posts: 46
    edited 2006-10-18 00:06
    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...
Sign In or Register to comment.