Shop OBEX P1 Docs P2 Docs Learn Events
How to get the servo position in real time with the Propeller Servo Controller — Parallax Forums

How to get the servo position in real time with the Propeller Servo Controller

kevinspacekevinspace Posts: 56
edited 2011-04-10 20:08 in Propeller 1
Hello everyone,I'm not sure my grammar is true! But I'm as far as possible to express my problem.

Now, I'm using the Propeller Demo Board connect with the Propeller Servo Controller USB(#28830) that try to

control my servo, therefor, I'm writing the program with spin language.

So far I can set my servo to desired position with specified speed, but now I don't know how to capture the

servo position of "real time".

I try to use the "ServoControllerSerial.spin" program which from the Propeller Object Exchange

(http://obex.parallax.com/objects/449/).

And using the "FullDuplexSerialPlus.spin" to display the position messages

Here is my used code

OBJ
PSC : "ServoControllerSerial"
Debug: "FullDuplexSerialPlus"

CON
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000

COMPIN = 3 'Pin used for communication with the PSC
PSC_BAUD = 0 'Baud rate (0 - 2400, 1 - 38400)
VAR long Stack[100]
word Position

PUB LaunchBlinkCogs
coginit(1,Main, @stack[0])
coginit(2,Messages, @stack[50])

PUB Main
PSC.START(COMPIN, PSC_BAUD)
PSC.SETPOS (0, 1, 750)
PSC.GETPOS (0)
Position := PSC.GETPOS (0)

PUB Messages
Debug.start(31, 30, 0, 57600)
waitcnt(clkfreq*2 + cnt)
Debug.tx(16)
repeat
Debug.str(string("position: ", 13))
Debug.DEC(Position)
Debug.str(string(13))
waitcnt(clkfreq + cnt)

The above program that I can get the servo position, but it is not "real time" .

In other words, when I set the servo turning from 0 degree to 180 degree with very slow speed,

I Expect that I can get the servo position in any time when the servo until turning into 180 degree.

Comments

  • wjsteelewjsteele Posts: 697
    edited 2010-12-10 04:42
    Servos do not have a feedback mechanism, so they can't tell you their position. You would need to add a some kind of sensor or encoder to get that information.

    Bill
  • prof_brainoprof_braino Posts: 4,313
    edited 2010-12-10 05:24
    wjsteele wrote: »
    ...they can't tell you their position.

    I remember something about servo read from basic stamp, but maybe that was only the last requested position. I had thoughts of measuring the current draw of the servo to determine if it was still under load, but never finished. The idea was current draw + positon would tell me something.

    I'd be interested to see any solution you come up with.

    EDIT - http://www.openservo.com/VelocityControl is an open source project if you want to void a warranty
    It does not use a prop per se but, being open source, may be adaptable

    It DOES allow position feedback
  • wjsteelewjsteele Posts: 697
    edited 2010-12-10 07:23
    It DOES allow position feedback

    Hmmm.... that's not quite right... it's only telling you the velocity of the servo, not the position. When the velocity reaches near zero (after a change in PWM) then you can assume that it has arrived at the requested position. However, that postion will be different from servo to servo.

    Look at it this way. If I tell a blind person to move 5 steps forward and then tell a second blind person to do the same, they'll move a different distance because of the individual differences in their height and stride. Both can say they are five steps out and both will be right, but they'll have different actual measurements.

    Obviously, servo tollerances will be the limiting factor here, but it's a pretty cool way to measure it. If you could match two servos (or measure their individual errors) then you can get close... but I think you'd still have to have some form of position feedback to be accurate.

    Bill
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2010-12-10 08:28
    kevinspace,

    Here is a method I discovered ... In the thread there have been others that took this idea and streamlined it, but it works on the same basic principle as the method outlined.

    Link to Servo Tracking Page

    attachment.php?attachmentid=41311&d=1145423620
  • kevinspacekevinspace Posts: 56
    edited 2010-12-12 19:28
    Thanks for everyone, because the former version PSC ("Parallax" Servo Controller #28023) which can report the "current" servo position,

    Here is the former version PSC manual (http://www.parallax.com/dl/docs/prod/motors/ServoController.pdf),

    The RSP Command – Report the Position of a Servo Channel which can report the "current" servo position.

    But the new version PSC ("Propeller" Servo Controller #28830) which can only return the pulse width value last set for sepecified channel,

    Here is the new version PSC manual (http://www.solarbotics.com/assets/documentation/28830-propservocontrollerusb-v10.pdf)

    The RSP Command – Report Servo Position which can only return the pulse width value last set for sepecified channel,

    so I want to verify it, The program which I have posted and its result just like the new version PSC manual described.

    How can I Improve it ? Can I modify the open-source PSC Propeller Firmware to achieve it, and how to modify it ?
  • kevinspacekevinspace Posts: 56
    edited 2010-12-13 05:10
    Hello everyone, this is PSC Propeller Firmware which I have Added

    (http://www.parallax.com/Portals/0/Downloads/docs/prod/prop/PSCPropellerFirmware.zip)

    Could someone can offer me some suggestion, thanks.
  • Mike GMike G Posts: 2,702
    edited 2010-12-13 06:31
    Standard hobby servos do not report angular position. Either follow Beau's advise, modify the servo electrionics, add an external encoder, or use a servos that can report angular position like an AX-12.
  • kevinspacekevinspace Posts: 56
    edited 2010-12-14 00:34
    I know that servos does not have a feedback mechanism, I think try to describe In other words,

    the former version PSC ("Parallax" Servo Controller #28023) which can report the "current" servo position, I guess it does not


    capture the servo position, but it get the "current" pulse width value from its own output signal (pulse width value), means that


    when I set the servo turning angle from 0 to 180 with very slow speed, the PSC will divide the pulse width value into several pulse


    width value from small to large, then continue output the pulse width value from small to large, each divided pulse width value


    represent the position respectively. Thus, the servo will be turn with very slow speed.

    Here is a video to show and explain my description.

    [video]http://www.youtube.com/user/kevinspace2#p/a/u/1/4mOli-zTCyE[/video]
  • hover1hover1 Posts: 1,929
    edited 2010-12-14 11:44
    I think the problem has to do with the wording in the old command "Current Servo Position". Since that code is not published, it is hard to tell. I believe it reports the same value as the new "Report Servo Position" command.

    From what I can see, with the new code, "Report Servo Position" will report the position that the servo was commanded to go to, no matter where the servo is at the time. I think that's the way the old "Current Servo Position" worked. The wording is a little misleading.

    Of course, that doesn't help you with trying to read the current position in real time. It may be possible to start another Cog to measure the servo pin signal, and report in real time.

    Jim
    kevinspace wrote: »
    I know that servos does not have a feedback mechanism, I think try to describe In other words,

    the former version PSC ("Parallax" Servo Controller #28023) which can report the "current" servo position, I guess it does not


    capture the servo position, but it get the "current" pulse width value from its own output signal (pulse width value), means that


    when I set the servo turning angle from 0 to 180 with very slow speed, the PSC will divide the pulse width value into several pulse


    width value from small to large, then continue output the pulse width value from small to large, each divided pulse width value


    represent the position respectively. Thus, the servo will be turn with very slow speed.

    Here is a video to show and explain my description.

    [video]http://www.youtube.com/user/kevinspace2#p/a/u/1/4mOli-zTCyE[/video]
  • kevinspacekevinspace Posts: 56
    edited 2010-12-16 23:57
    Excuse me, this is a video which compare the new version PSC ("Propeller" Servo Controller #28830) with

    the former version PSC("Parallax" Servo Controller #28023), however, the result is different obviously, the

    former version PSC can report the "current" pulse width value, but the new version PSC can't . Moreover,

    The above two method that I'm uesed the same code to compile it.

    Here are two videos to show and explain my description :

    The servo turning angle from 0 to 180 with very slow speed by former version PSC



    The servo turning angle from 0 to 180 with very slow speed by new version PSC



    I think my problem which I'm encountered is how to modify the open-source Firmware of new version

    PSC("Propeller" Servo Controller #28830) to achieve the same result of former version PSC.
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2010-12-17 08:33
    kevinspace,

    I'll see if I can get another "Propeller" Servo Controller to test this with in the next few days. After I wrote the original code I had to surrender my PSC unit to another engineer. :-)

    looking over the Firmware code, there are a few things.

    Inside of the 'PSC Propeller Firmware' under the PUB heading of 'ReadServoPosition' the value returned is actually the 'destination' value ... you could probably confirm this based on your own results.

    See attached Image1

    Inside of the 'Servo32v7' code, the variable 'ServoData[32]' contains the servo position, but there is no PUB mechanism to read it into the 'PSC Propeller Firmware'

    See attached Image1

    ...I'm sorry for this oversight on my part. I will get another PSC and make the necessary updates.
    1024 x 819 - 124K
    1024 x 819 - 106K
  • StefanL38StefanL38 Posts: 2,292
    edited 2010-12-17 13:00
    Hi,
    first I thought this would be offtopic and then be placed in the sandbox.
    But I think it is related to this thread.

    Today I discovered a small device that modifies any kind of standardsize hobbyservo in a much more accurate servomotor.

    The Robotic Rebirth of the Hobby Servo Supermodified]

    demovideo

    EDIT: strange the link is working on my notebook
    anyway here the URL as blank text

    http://www.youtube.com/watch?v=8jajnIBX2cU

    and if this doesn't work either
    try a search on youtube with searchwords "Hack your servo v3.00"

    best regards

    Stefan
  • RS_JimRS_Jim Posts: 1,768
    edited 2010-12-18 06:58
    StefanL38 wrote: »
    Hi,
    first I thought this would be offtopic and then be placed in the sandbox.
    But I think it is related to this thread.

    Today I discovered a small device that modifies any kind of standardsize hobbyservo in a much more accurate servomotor.

    The Robotic Rebirth of the Hobby Servo Supermodified]

    demovideo

    best regards

    Stefan

    Stefan,
    Tried your link but it did not work. Can you reedit it and try again?
    Thanks
    RS-Jim
  • Mike GMike G Posts: 2,702
    edited 2010-12-18 08:31
    The supermodified servos work great, a little pricey though. http://www.01mech.com/supermodified
  • kevinspacekevinspace Posts: 56
    edited 2010-12-19 08:21
    Thanks for your attention , Beau Schwabe.

    I'll also try to modify the 'Servo32v7' code to achieve it, and if I have any discovery or question,

    I will consult with you again.
  • kevinspacekevinspace Posts: 56
    edited 2010-12-19 08:37
    Thanks, Stefan.

    In order to more convenient to get the position, I hope that I can modify the Firmware of "Propeller" servo controller to achieve it.

    But thank for your suggestion.
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2010-12-20 14:21
    kevinspace,

    Before I post this to the OBEX, please try the updated PSC Firmware and the updated Servo32 object.
  • kevinspacekevinspace Posts: 56
    edited 2010-12-23 02:28
    Thanks for your help, Beau Schwabe.

    I have try to use the new code to get the servo position, and it seems like to be success.

    But it appears some bugs.

    The pulse width value of my servo which can receive is 350 to 1150.

    ( because of the pulse width value are specified in 2us increments, and the ceceived range of my servo is

    750ms~2300ms )

    When I set the pulse width value for 350 to my servo, then I get the servo position from PSC,

    but the value which I get is 348, moreover, when I set the pulse width value for 1150 to my servo,

    but the value which I get is 1147.

    Although it is not a serious problem, but I still propose it and hope it can be solved.


    Here is the figure and video of my question :


    The first, I set the pulse width value for 350 to my servo

    The second, I set the pulse width value for 350 to my servo
    632 x 476 - 41K
    628 x 478 - 41K
  • wjsteelewjsteele Posts: 697
    edited 2010-12-23 08:11
    kevinspace wrote: »
    When I set the pulse width value for 350 to my servo, then I get the servo position from PSC, but the value which I get is 348, moreover, when I set the pulse width value for 1150 to my servo, but the value which I get is 1147.

    There is going to be a small amount of error and this appears to be within a very acceptable range of less than 1% error margin. That's because he's actually doing the math to calculate the actual position based on the clock frequency instead of just reading back the destination (target) value. This is done to give you a progressive change in the value as the servo is tracking to the target value.

    Bill
  • kevinspacekevinspace Posts: 56
    edited 2011-04-10 04:06
    The get servo position value is not very correct !!

    Could anyone help me to improve the problem?


    Thanks a lot !!
  • StefanL38StefanL38 Posts: 2,292
    edited 2011-04-10 04:55
    Hi Kevin.

    please attach your complete code to a posting by using the archive-project function of the propellertool.

    Sometimes strange things happen with a program (not enough stackspace overwriting data, unintended call of another method changing the value etc.)

    The problem gets narrowed down faster if you provide your actual code. I assume Beau has done some testings with improved results before attaching Servo32v8.zip to posting #18 in this thread

    best regards

    Stefan
  • kevinspacekevinspace Posts: 56
    edited 2011-04-10 08:09
    Hi StefanL38
    I have posted the test code at the page response #19 ( and it also added the video !! )
    and the Servo32 object have posted at the page response #18

    Thanks your attention !!
  • Mike GMike G Posts: 2,702
    edited 2011-04-10 09:03
    @kevinspace, In 19 you posted an image of your source code which ends inside a repeat loop. Does the repeat loop forever or is there an end like if(position == 350) quit?

    Please post all your code as a file.
  • StefanL38StefanL38 Posts: 2,292
    edited 2011-04-10 09:28
    Bill wrote:
    That's because he's actually doing the math to calculate the actual position based on the clock frequency instead of just reading back the destination (target) value. This is done to give you a progressive change in the value as the servo is tracking to the target value.

    If I understand right the error comes from calculating with integer-math which cuts off the fraction behind the decimalpoint.

    OK How about improving the GetServoPos-method if ramping has finished

    some kind of a if-condition if ramping has finished give back the target-value.
    else caclulate value

    Kevin what do you want to do in the end? often a suitable solution depends on the project you need this detail for

    best regards

    Stefan
  • kevinspacekevinspace Posts: 56
    edited 2011-04-10 10:21
    Thanks for your attention, StefanL38 and Mike G.
    Because I only used the servo32v8 object to control my servo finally, I didn't connect with the PSC ( Propeller Servo Controller ) ,
    so I think I must to arrange my code and I will add the code later, and I will describe the detail for you a few hours later.


    Thanks for your attention !!
  • Mike GMike G Posts: 2,702
    edited 2011-04-10 11:14
    StefanL38, I did not know if Bill was referring to Kevin or Beau's code. I'd guess that Beau's code is tested and working properly.

    Kevin, so the code you referred us to is not what you have loaded in the Propeller? If so, that's a bit annoying.
  • PublisonPublison Posts: 12,366
    edited 2011-04-10 16:45
    Just to get a base line so we are all on the same page. You have downloaded Beau's new code (PCS Firmware V2 including Servo32V8.spin and Servo32_Ramp_v2.spin) to the Propeller Servo Controller (Part # 28830) You have saved that to EEPROM on PSC. You then want to communicate with another Propeller based product via "ServoControllerSerial.spin"

    kevinspace wrote: »
    Hi StefanL38
    I have posted the test code at the page response #19 ( and it also added the video !! )
    and the Servo32 object have posted at the page response #18

    Thanks your attention !!
  • kevinspacekevinspace Posts: 56
    edited 2011-04-10 19:22
    Hi everyone~
    I have test the "Get the servo position" command by two method !!

    The first one, I tested the object Servo32V8's function "GetServoPosition", and debug the value by FullDuplexSerialPlus, I discoveried some error !! When I set the pulse width value for 2300 to my servo, then I get the servo position, but the value which I get is 2294, moreover, when I set the pulse width value for 700 to my servo, but the value which I get is 697.

    Here is the Program :
    GetPosition_error1.JPG


    GetPosition_error2.JPG

    And another way I connected with the PSC, I have downloaded Beau's new code (PCS Firmware V2 including Servo32V8.spin and Servo32_Ramp_v2.spin) to the Propeller Servo Controller (Part # 28830), then I have saved that to EEPROM on PSC, and I communicate with another Propeller based product via "ServoControllerSerial.spin". In the way, When I set the pulse width value for 350 to my servo, then I get the servo position from PSC, but the value which I get is 348, moreover, when I set the pulse width value for 1150 to my servo,but the value which I get is 1147.

    Here is the Program :
    PSC_GetPosition_error1.JPG

    PSC_GetPosition_error2.JPG
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2011-04-10 20:08
    kevinspace,

    I understand your frustration. The difference in timing is due to how the Ramp function operates.

    The Ramp function takes 3100 clocks to process all 32 servo Channels whether you are using them or not. This leaves a Delay interval of 38.75us.

    So instead of incrementing or decrementing the Delay by 3100 clocks (38.75us) every 20ms, I choose a value that was 1/5th of this that fit best with the previous servo controller's delay resolution. 1/5th of 3100 clocks equals 620 clocks or a Delay resolution of 7.75us ... Don't confuse Delay resolution with Pulse width, although this is the root of your discrepancy in your numbers, you can adjust the CoreSpeed value yourself within "Servo32_Ramp_v2" for a smaller Delay resolution, but the trade off is the amount Delay that it takes your Servo's to pan from one position to the other. Like I said 620 for a CoreSpeed was a good fit to abide to our previous servo controller and still encompass the entire range of delays, but that doesn't mean you can't change this value for yourself.

    Ok, after saying that, let me back up and explain the numbers that you are getting...

    Think of the CoreSpeed value as a "grid snap" plain and simple.

    Look at the SetRamp function within 'Servo32v8"... the line in particular that reads...

    ServoTarget[Pin] := ((clkfreq / _1uS * S_Width)/SERVO#CoreSpeed)*SERVO#CoreSpeed

    At 80MHz, 'clkfreq / _1uS' is equal to 80, and the CoreSpeed I have said is set to 620. So the line above becomes...

    ServoTarget[Pin] := ((80 * S_Width)/620)*620

    ... 'S_Width' is your desired pulse width. Lets take your number of 350

    ServoTarget[Pin] := ((80 * 350)/620)*620
    ServoTarget[Pin] := (28000/620)*620
    ServoTarget[Pin] := 45*620
    ServoTarget[Pin] := 27900 <- Notice the 'grid snap' difference?

    If we divide 27900 by 80 we get 348, which is the number that you are seeing.

    If we do the same thing with 1150 we get 1147.

    A lower value for the Core Speed would correct this problem for you, but you may not get the overall range in delay that you desire.

    I hope this helps to shed some light.


    EDIT --- Thanks kuroneko!! , this 'grid snap' also introduces a bit of hysteresis so that once the servo is at 'position' it doesn't constantly 'hunt' for the position.
Sign In or Register to comment.