Shop OBEX P1 Docs P2 Docs Learn Events
Two Servos with Basic Stamp — Parallax Forums

Two Servos with Basic Stamp

Boots451Boots451 Posts: 5
edited 2009-10-26 17:41 in BASIC Stamp
I am trying to run two servos with the Basic Stamp Home Work Board. The servos to alternate action not simultaneous. Servo A to raise arm, servo B to start position, Servo A to lower arm, Servo B to sweep, Servo A to raise arm, Servo b to return to start and A to lower arm to docking. The code doesn't work. Any help?

Thanks,

Boots451



Dual counter #2



' {$STAMP BS2}
' {$PBASIC 2.5}



counter VAR Word

DO

IF (IN3 + 1 ) THEN

FOR counter = 1 TO 100
PULSOUT 10, 750
PAUSE 7
NEXT

FOR counter = 1 TO 100
PULSOUT 14, 725
PAUSE 50
NEXT

FOR counter = 1 TO 100
PULSOUT 10, 700
PAUSE 7
NEXT

FOR counter = 725 TO 590 STEP 2
PULSOUT 14, counter
PAUSE 750
NEXT

FOR counter = 1 TO 100
PULSOUT 14, 590
PAUSE 50
NEXT

FOR counter = 1 TO 100
PULSOUT 10, 750
PAUSE 7
NEXT

Comments

  • allanlane5allanlane5 Posts: 3,815
    edited 2009-10-23 13:27
    The servo control signal is:

    A high-going pulse of a particular width (1.5 mSec being center position) repeated every 20 msec. Very important that -- REPEATED EVERY 20 MilliSeconds. Some people try to "improve" on this by repeating (as you have) every 7 milliseconds. However, since 7 milliseconds is not 20 milliseconds, this is not a "better" control signal, it's simply incorrect.

    I'm curious -- why are you repeating one every 7 milliseconds, and the other every 50 milliseconds?

    Anyway, attached is a fix.· I've created a "SetServos" subroutine which will "refresh" both servo's, so they both hold position all the time, AND guarantee you get that 20 millisecond pause each time.· So you simply change the "Servo1Pos" then call SetServo repeatedly to move Servo1, and change "Servo2Pos" and call SetServo repeatedly to move Servo2.

    Post Edited (allanlane5) : 10/23/2009 1:44:51 PM GMT
  • Boots451Boots451 Posts: 5
    edited 2009-10-23 15:21
    Allan, First thanks for your help. I am building a record cleaning machine, knock off of the Loricraft. After wet cleaning a suction arm sweeps the record to take away the dirt and dry the record. The reason for the 7 millisecond and 50 millisecond difference is a matter of sweep speed. The initial sweep of the arm has to be slow in order to let it perform properly and the return sweep is faster just a matter of getting it back to the start position. I need the first sweep ( 725 to 590 ) to take about 45 to 60 seconds and this seemed to work with pause of 50. It is not smooth but does what is needed. The return of the sweep is just to get the arm out of the way and backed to dock. The pause 7 is just a smooth way of doing it. All of this is because of being very ignorant of the mechanics of servos and programming. I am eager to try your solution as I have never seen the type of program that you wrote.

    Thanks again,

    Boots 451
  • allanlane5allanlane5 Posts: 3,815
    edited 2009-10-23 15:55
    Interesting. I've normally been using servo's modified for "continuous rotation", and haven't done much 'speed control'.

    Even when controlling speed of the servo, you'll need to refresh it every 20 milliseconds. To slow it down, you'll want to change the step-size less often.

    Let's see. 725 to 590 is 135 steps. 50 seconds / 20 mSec == 2500 commands to the Servos. 2500/135 == 18 times at each step value.

    So:
    · For Count = 725 to 590
    ··· Servo1Pos = Count
    ··· For I = 1 to 18
    ··· · GOSUB SendServos
    ··· NEXT
    · NEXT

    So, let's confirm. The above will send each 'step' to the servo 18 times. 18 * 20 mS == 0.36 seconds. Then we do that for 135 steps. 135 * 0.36 == 48.6 seconds.
    Yup, there's your solution.
  • allanlane5allanlane5 Posts: 3,815
    edited 2009-10-23 16:05
    And you'll have to measure the max speed the servo can move from 590 to 725. If I assume it will take a second, then:

    · Servo1Pos = 725
    · FOR I = 1 to 50 ' 50, because 50 * 20 mSec == 1 second
    ··· GOSUB SendServos
    · NEXT

    See, the servo contains a very simple 'comparator' with a variable resistor tied to the shaft of the servo. Each position of the shaft (and thus the variable resistor) generates a pulse-width inside the servo. Then your PULSOUT commands send to the servo another pulse-width. The servo electronics compare the internal pulse-width with your "commanded" pulse width, and moves the internal electric motor to bring the two pulse-widths to be the same size. This process usually takes longer than 20 mSec, so multiple 'refreshes' of the same "commanded" pulse-width are needed for the servo to complete its move.

    Once the servo reaches the commanded position, if you want it to hold that position against resistance, then you need to keep commanding the servo to the same position -- which is what the subroutine does. If you stop commanding the servo, it stops energizing its motor, and you can turn the shaft by hand (or any weight on the shaft will turn it).
  • Boots451Boots451 Posts: 5
    edited 2009-10-23 23:55
    Alan- I couldn't get some of your code to work for me so I put this crude program together. It does what I need if not to elegant.

    'Dual counter #1



    ' {$STAMP BS2}
    ' {$PBASIC 2.5}



    counter VAR Word
    Servo1 CON 13
    Servo2 CON 12

    Servo1Pos VAR Word
    Servo2Pos VAR Word

    Servo1Pos = 850
    Servo2Pos = 725

    FOR Counter = 1 TO 10 ' Initial Setting
    GOSUB SetServos
    NEXT

    MAIN:


    FOR counter = 1 TO 100 'servo 2 lifts arm
    PULSOUT 12, 7760
    PAUSE 20
    NEXT


    FOR counter = 1 TO 50 'servo1 moves to start position
    PULSOUT 13, 725
    PAUSE 20
    NEXT


    FOR counter = 1 TO 100 'servo 2 lowers arm
    PULSOUT 12, 600
    PAUSE 20
    NEXT

    FOR counter = 725 TO 590 STEP 2 ' servo 1 sweeps
    PULSOUT 13, counter
    PAUSE 750
    NEXT

    FOR counter = 1 TO 25
    PULSOUT 13, 590
    PAUSE 20
    NEXT



    FOR counter = 1 TO 100
    PULSOUT 12, 760 ' servo 2 lifts arm
    PAUSE 20
    NEXT


    FOR counter = 590 TO 850 ' servo 2 returns to over rest position
    PULSOUT 13, counter
    PAUSE 7
    NEXT




    FOR counter = 1 TO 100 'servo 1 lower to rest position
    PULSOUT 12, 760

    PAUSE 7
    NEXT

    END
    SetServos:
    PULSOUT Servo1, Servo1Pos
    PULSOUT Servo2, Servo2Pos
    PAUSE 20
    RETURN

    END
  • MichelBMichelB Posts: 154
    edited 2009-10-24 08:25
    Interesting this thread. I'm a beginner and I want to know what is the "job" of the following line in Main: "IF (IN3 + 1) THEN". Thank you.
  • Boots451Boots451 Posts: 5
    edited 2009-10-26 00:05
    Michel.........I started out trying to put a on-off button[noparse][[/noparse] "IF ( in3 = 1 ) then "] on the machine but took it off for simplicity sake. I'll try to add it back in at a later date when all is well with the rest of the works.
  • MichelBMichelB Posts: 154
    edited 2009-10-26 12:27
    OK, thank you for your reply.
  • allanlane5allanlane5 Posts: 3,815
    edited 2009-10-26 13:51
    Hey, whatever works for you is fine.
  • Boots451Boots451 Posts: 5
    edited 2009-10-26 17:41
    Alan.... Because it works doesn't mean it is right.... This is a work in progress. I put in the


    For Count = 725 to 590
    Servo1Pos = Count
    For I = 1 to 18
    GOSUB SendServos
    NEXT
    NEXT

    and it runs much smoother. But it makes other aspects of the servo run a little buggy( hops a little her and there). So I think that I will have to rewrite some of my header about position of servo #2.

    Thanks for your help

    Boots451
Sign In or Register to comment.