Shop OBEX P1 Docs P2 Docs Learn Events
Equation for PULSOUT value for Certain Angle — Parallax Forums

Equation for PULSOUT value for Certain Angle

RevCRevC Posts: 12
edited 2013-08-27 07:14 in BASIC Stamp
I am working with Board of Education and the BS2 Stamp and the standard servo that comes with it. What is the equation for deriving to PULSOUT value with a given angle in degrees?

90 degrees = 1.5ms with 20ms in between pulses.

While reading "What's a Microcontroller" I did not see an equation in the chapter where they covered this. Such equation does exist, right?

Comments

  • stamptrolstamptrol Posts: 1,731
    edited 2013-08-18 05:10
    There is no specific formula. You can generate your own formula based on the servo you are using.

    As the PULSOUT changes up or down from 1.5 mS, the servo will turn clockwise or counterclockwise a certain amount. Try it by varying the PULSOUT from 1 mS to 2 mS.

    Don't forget, the BS2 doesn't use mS directly, so you'll have to use the time units ( 2 uS, I think) of the chip.

    Once you have control of the servo, you can generate your own formula to know what PULSOUT value corresponds to what angular position. It will be more or less, 0 deg at 1 mS, 90 deg at 1.5 mS and 180 deg at 2 mS.

    Cheers,
  • RevCRevC Posts: 12
    edited 2013-08-18 10:37
    I think I found the equation!! You will have to find some values which you then use to solve the equation, but it works!!

    Equation:
    PULSOUT = Minimum PULSOUT Value + ( (Desired Angle x Full Span of PULSOUT)/180)
    PULSOUT = MinPV + ( (DA x FSP)/180)

    Minimum Pulsout Value: This is the value to get your horn pointing to 0°
    Desired Angle: The angle you're looking for in degrees (e.g. 67°, 160°, etc)
    Full Span value of PULSOUT from 0° to 180°: count from minimum range (250 for 0°), to maximum range (1250 for 180°) = 1250 - 250 = 1000
    180: This is the max angle

    First thing! Test your servo and find these values!:
    For horn to point to 0° PULSOUT = ?? (I'm using 250 (this is Minimum PULSOUT value))
    For horn to point to 180° = ?? (I'm using 1250 for 180° (this is Maximum PULSOUT value)) (your servo may go past 180)

    So to find the PULSOUT value for 45°

    PULSOUT value = MinPV + ( (DA x FSP)/180)
    PULSOUT value = 250 + ( (45° x 1000)/180°)
    PULSOUT value = 250 + (45000/180°)
    PULSOUT value = 250 + 250
    PULSOUT value = 500
    PULSOUT 500 = 1000µs: This is because each unit given to PULSOUT is equal to 2µs (500x2µs = 1000µs = 1ms)

    I hope this isn't confusing, and most importantly I hope I didn't miss something!

    Hope this helps someone!
  • Mike GreenMike Green Posts: 23,101
    edited 2013-08-18 10:54
    Just a little advice ... Don't count on this formula being very accurate or precise. There's a lot of variation from servo to servo and there's some slop in servo movement as well. Also remember that the full range of servo movement will vary from servo model to servo model. It may be 180 degrees or it may be 240 degrees or more. Some specialized servos (called winch servos) may have 720 degrees or more of movement. The minimum and maximum PULSOUT range may be as little as 0.5ms or as much as 2.5ms. Test your servos individually to determine their mechanical range and the range of control pulses that they'll accept.
  • RevCRevC Posts: 12
    edited 2013-08-18 11:40
    Mark Thank you for the response!!

    I did count on this, and I think you can achieve accuracy by adjusting the equation to your own numbers. I used 180° like when a square wave is used to symbolize a digital signal on a textbook, in the real world signals may not look that perfect, but it shows the principle.

    In my defense I did "attempt" to put a disclaimer that this number may change, in retrospect I think I could have done better.

    my original post:
    [QUOTE=RevC;1201787
    ...

    For horn to point to 180° = ?? (I'm using 1250 for 180° (this is Maximum PULSOUT value)) (your servo may go past 180)

    ...
    [/QUOTE]

    In my case I will be measuring my servo, I already know mine goes past 180°. So my equation may read something like PULSOUT value = MinPV + ( (DA x FSP)/192)
    This value should actually be an other constant that the user has to find for their servo, just like Minimum PULSOUT value, etc..
  • ercoerco Posts: 20,257
    edited 2013-08-18 18:39
    Great job coming up with your equation, RevC! Glad it worked for you. From my experience, it's not a perfectly linear relationship (degrees per microseconds of pulsout), especially near the endpoints. It should be fairly consistent, though, for any given servo, so you can program around it or make a third-order polynomial equation for more precise curve-fitting. :)
  • RevCRevC Posts: 12
    edited 2013-08-19 03:17
    Erco,

    Thanks, I just finished some code to have the BS2 calculate the angle for me. It was a pain to have the BS2 divide numbers above 65535 but it's doing it just fine. I'm going to test this with a full protractor, if it works well, I may make a video of it.

    Could you please elaborate as to how I or anyone would use "third-order polynomial"? I am lacking in math but I'm curious to know more and interested in seeing how others use it.
    It doesn't have to be long explanation, unless you wanna :-)! Just wanna know the principals or the concept you meant.
  • ercoerco Posts: 20,257
    edited 2013-08-19 06:42
    I was mostly joking about how you can make it as accurate and difficult as you want. It's a very involved subject, but start here: http://en.wikipedia.org/wiki/Curve_fitting
  • phatallicaphatallica Posts: 64
    edited 2013-08-19 16:06
    Great question at just the right time, RevC. I just started playing with my first servo yesterday and was in the process of writing a similar algorithm.

    For the knock-off MG996R servos that I have:
    0.48 msec ... 0-degrees
    2.63 msec ... 180-degrees

    Most beginner references like to suggest that servos are high-precision and consistent, with 1msec = 0-degrees; 1.5msec = 90-degrees; and 2msec = 180-degrees. I only found one that was quite frank that there is no standard or consistency. I feel so disillusioned.
  • ercoerco Posts: 20,257
    edited 2013-08-19 17:13
    phatallica wrote: »
    I feel so disillusioned.

    Take a number, Pal!

    I'm disillusioned, disconnected, disenfranchised, disinfected, and Disney-fied, courtesy of my twin baby girls. :)
  • RevCRevC Posts: 12
    edited 2013-08-20 07:51
    erco wrote: »
    I was mostly joking about how you can make it as accurate and difficult as you want. It's a very involved subject, but start here: http://en.wikipedia.org/wiki/Curve_fitting

    Here I thought you were going to wow me with some genius math :lol:
    phatallica wrote: »
    Great question at just the right time, RevC. I just started playing with my first servo yesterday and was in the process of writing a similar algorithm.

    For the knock-off MG996R servos that I have:
    0.48 msec ... 0-degrees
    2.63 msec ... 180-degrees

    Most beginner references like to suggest that servos are high-precision and consistent, with 1msec = 0-degrees; 1.5msec = 90-degrees; and 2msec = 180-degrees. I only found one that was quite frank that there is no standard or consistency. I feel so disillusioned.

    Phatallica, you're right those numbers wont work. Thankfully the equation and method above works. I found it easier to use the mechanical limit on the right as 0°, then go on to measure which PULSOUT value will get the horn to swing to the left the farthest (when you know you're getting close to the mechanical limit of servo increase pulsout by one at a time, so you can find the exact moment your servo reaches the limit).

    My 0° number is PULSOUT = 205 not 250 like WAM book says...

    Maybe I'll make a video of it to show and tell. So far the tests have been pretty accurate.
  • 72sonett72sonett Posts: 82
    edited 2013-08-27 07:14
    I used the StandardServoPositions.bs2 program to determine the 0 deg and 180 deg position of a specific Modelcraft RS-2 servo. That turned out to be 700 and 3200 respectively, so the linear angle to duration conversion function is;

    duration = (3200-700)/180*angle + 700 =~ 14* angle +700.

    Then I used this subroutine;
    ' ===========Set variables ========
    t           VAR     Byte                ' counter
    duration     VAR     Word                ' duration servopulse
    angle         VAR     Word                ' servo 'rotate to' angle
    servonr      VAR      Byte                ' I/O pin for servo signal
    LED1pin     PIN          13                ' I/O pin for LED on PCB
    
    minduration   CON    700               ' min duration of servopulse  = 0 deg
    maxduration   CON  3200                ' max duration of servopulse  = 180 deg
    
    '============== Main program ===========
    ...
    
    END
    '===========Subroutines ========
    rotateservo:                        ' rotate servo '[I]servonr[/I]'  to  '[I]angle[/I]'[INDENT]DEBUG "Rotateservo: ", DEC servonr, " to angle; ", DEC angle, CR
    [/INDENT]
    [INDENT]HIGH LED1pin                                                ' LED1 on while servo is rotating
    [/INDENT]
    [INDENT]duration = (14*angle + minduration) MAX maxduration
    [/INDENT]
    [INDENT]FOR t = 1 TO 40                                             ' for approx. 1 sec.
    [/INDENT]
    [INDENT=2]PULSOUT servonr, duration   
    PAUSE 20                                             ' pause pulse
    [/INDENT]
    [INDENT]NEXT
    [/INDENT]
    [INDENT]LOW LED1pin                                                 ' LED off
    [/INDENT]
     RETURN
    '====================
    

    From anywhere in the main program I can call the subroutine with parameters 'servonr' and 'angle' , like;
      servonr = 0
      angle = 90
      GOSUB rotateservo
    

    and that will rotate the servo to the center 90 deg position.

    Then I used a second, same brand same type servo and that turned out to have slightly different extreme and center positions, so the similar code
      servonr = 1
      angle = 90
      GOSUB rotateservo
    
    did not position this servo at exactly 90 degrees.

    If I want more accuracy, I can determine the min/max durations for each servo, declare them as constants and pass them as parameters to the subroutine, with in the subroutine;
    duration = (maxduration-minduration)/180*angle + minduration
    

    Or, put them in an array;
    minduration   VAR Word(3)                  ' min durations of servopulses = 0 deg
    minduration(0) = 650                        ' min duration of servo nr 0
    minduration(1) = 700                        ' min duration of servo nr 1
    minduration(2) = 600                        ' min duration of servo nr 2
    maxduration   VAR Word(3)                  ' max duration of servopulses  = 180 deg
    maxduration(0) =   3100                    ' max duration of servo nr 0
    maxduration(1) =   3100                    ' max duration of servo nr 1
    maxduration(2) =   3200                    ' max duration of servo nr 2
    ...
    
    in subroutine;
    duration = (maxduration(servonr)-minduration(servonr))/180*angle + minduration(servonr)  MAX maxduration(servonr)
    
Sign In or Register to comment.