Shop OBEX P1 Docs P2 Docs Learn Events
New Parallax 360 Feedback Servo - Page 7 — Parallax Forums

New Parallax 360 Feedback Servo



  • tomcrawfordtomcrawford Posts: 1,126
    edited 2017-11-30 23:22
    twm47099 wrote: »
    Is there a way to get the actual rpm from the pasm so it could be printed or transmitted as data to a control program (using an XBee for example).
    Tom M.

    Here is a version that returns the measured velocity ONLY WHEN IN CONSTANT VELOCITY MODE.
    Since spin is best at returning a single value, CCW velocity is returned as negative. I am still thinkin' how best to make it more general.

    I do not know for sure that my conversion from RPM to clicks/tic is correct and so I don't if the velocity is actually what is programmed. I can just sort of
    eyeball it and say "one-mississippi two-mississippi" and it looks right, but...

    I don't have any way to easily install mount an encoder to actually measure the rpm. If you have encoders on your activitybot and wanted to temporarily spend
    a cog to independently measure velocity, that would be way cool.

    Found a way to mount an encoder and will write code to compare claimed RPM to actual RPM.

  • Here is the latest (and I hope final) PASM driver for the Feedback Servo. It includes methods for ConstantPulseWidth, SetPosition, SetVelocity, GetPosition, and GetVelocity. A demonstration program is included. There is a little bit of engineering code in the driver but it is commented out.

    Tom, I believe the driver is strictly compatible with the previous version posted in the previous comment. I made it possible to read the velocity in ConstantPulseWidth and generally cleaned things up in the PASM (comments, VariableNames).

    There is also an object that displays the current velocity according to a ActivityBot encoder on servo 2.

    Finally, I append a couple of pictures of my test rig as well as a picture of what is left of my cannabalized Bot.

    I would like to suggest the Blockly guys have a look at this. Four servos in one cog is more better than one servo in two cogs
  • Tom,
    Thanks. This looks interesting. I tried the previous version last night and had a problem running the SPIN program - I would get text printed out but the servos did not turn. I finally realized that I had not set the pins for servo3 to zero (I only have 3 servos). Then it worked. But since it was about 2AM when I started to port the code I took that as an omen that I wasn't thinking clearly enough to continue. Glad I waited. I hope to work on it this evening.

    How did your rpm measurements compare with the encoder values?

    Tom M.
  • Yup. If the PASM part tries to measure feedback from a servo that doesn't exist, it dies a horrible death.

    I think it actually runs about 5% fast. That is, the encoder returns a value about 5% faster than what is commanded or sensed. I do not know why. I'm trying to decide if I think that is close enough.
    Perhaps you can have a look at VelocityTest.spin and see if you see anything obvious.
    The good news is that the velocity is just about completely independent of load. Plenty of gear noise, though.

    Tom C
  • I did some "AfterTheFact" flowcharts of the guts of the driver I wrote.

    It turns out to be straightforward.
    2550 x 3550 - 1M
    2550 x 3550 - 1M
    2550 x 3550 - 767K
  • Thanks for the code, Tom!
  • rjo__rjo__ Posts: 2,114
    edited 2017-12-14 03:53
    I have an encoder issue that I can't figure out.

    This is P2asm... but it is easy to read.
    The biggest difference from Pasm is that waitpeq and waitpneq have been replace by edge instructions...
    So, we are waiting for positive and negative edges.

    If you compare this with the logic that Phil posted, it is nearly identical.
                    waitse1            'wait for positive encoder edge
                    getct t1            'store counter in t1
                    mov t3,t1         'save t1 to t3
                    waitse2            'wait for negative encoder edge
                    getct t2            'store counter in t2
                    mov hperiod,t2    'move counter at negative edge to hperiod
                    sub hperiod,t1    'subtract counter value to give pulse width
                    waitse1               'wait for next positive encoder edge
                    getct t1               'store counter in t1
                    mov lperiod,t1     'move latest (positive) edge counter value to lperiod
                    sub lperiod,t2     'subtract counter value from lperiod to give low period
                    mov period,t1      'move latest positive encoder edge time to period
                    subs period,t3     'subtract first positive edge encoder vale to give complete period
                    jmp #.looper

    This works as expected. I am getting a total period (depending upon how hard I drive the servo) right around 87,990 clocks)
    I get a pulse width (just before the zero crossing) of 85,400 clocks... which is 97.0% of the period (perfect).

    The problem is that when the zero crossing occurs, I get an immediate next pulse width value of 18,191 clocks... way too big.
    AND this value stays until the servo turns about 30-40 degrees...
    After that everything goes back to normal until the next zero crossing.

    I am currently driving the servo at 5.80V with a pulse width of 1470us, but I have varied both with similar results.
    I have tried two different servos.

    I don't think it is a coding issue, and I don't think it is a hardware issue. Everything is wired up right.
    What else is there?
  • 1. Can you look at the feedback signal with a scope? That would tell you for sure whether you are measuring correctly or not.
    2. I found that it was easier initially, at least, to not drive the servo but rather turn it by hand to experiment with the feedback signal.
  • rjo__rjo__ Posts: 2,114
    I have turned the servo by hand and have the same problem. That is actually where I started.
    In my experience it is always a software problem. What flabbergasts me is that it can be so perfect and on spec 2/3 of the time... and then just fail so miserably. I have 3 other units. I'm going to test them all today and then hook up a Propeller Activity Board.

  • rjo__ wrote: »
    What flabbergasts me is that it can be so perfect and on spec 2/3 of the time... and then just fail so miserably. I have 3 other units. I'm going to test them all today and then hook up a Propeller Activity Board.

    Yeah, you always wonder about overflow, but with 32-bit registers and about 17-bit numbers, no...

    I put my quad P1 driver up on OBEX. It all works on an activity board with 4 servos. I'd love to have more people try it.....
  • rjo__rjo__ Posts: 2,114

    Problem solved... I had serial and servo running out of the same cog. It took too many clocks in the serial loop.
    By putting another wait edge state at the beginning of the loop all is good.

    Fresh eyes never hurt.

    I'll take a look over in OBEX... haven't been over there for a while.

  • twm47099twm47099 Posts: 867
    edited 2017-12-15 15:57
    I've updated my port of Tom Crawford's servo360 spin driver into C and attached a zip folder with the project "libservo360b full".

    "libservo360b full" contains demos that Tom had in his folder and a couple I added. One C function I added to the driver is fdsdrive(L-RPM, R-RPM) for driving an ActivityBot (or similar robot). The only specific requirement for that function is that servo0 is the left servo (CCW= robot fwd) and servo1 is the right servo (CW = robot fwd).

    *** Note *** The demo as written is not set up for running an activitybot. The early parts of the demo exercise the servos (including randomly) which will result in weird movement.

    One thing I noted is that when using the fdsdrive command (which uses the SetVelocity driver function) if a servo gets a command in the same direction it had been rotating, it will start sooner than the servo that gets a command in the opposite direction to which it had been going.
    For example in the code below the robot is commanded to pivot to the left "fbsdrive(-20, 20);" for 3 seconds, then stop. It is then commanded to travel straight " fbsdrive(20, 20);". Since the right servo is +20 in the pivot command and also in the travel straight command, it starts to move before the left servo (even though the command to "SetVelocity" for the left servo is immediately before that for the right servo.) Changing the code so that the left servo gets the commands with the same direction causes the left servo to start moving before the right.
    Any ideas?
    // now pivot left 
      print("Pivot left\n");
      fbsdrive(-20, 20);
      pause(3000);    // do for 3 seconds
      fbsdrive(0, 0);  
    // straighten out 
      print("fwd 20 RPM\n");
      fbsdrive(20, 20);
      pause(3000);    // do for 3 seconds
    // and stop 
      fbsdrive(0, 0);

    I've used that code to build a servo360 C library that I'm testing - so far it works. I'm also adding functions to the library (e.g. adding a drive function to move at a certain distance (inches & cm) per second which requires initialization with the wheel diameter) . Once I happy with it, I'll post the library.

  • My Bad,Tom. I'm pretty sure I can fix the delay problem. I will be sure to just ramp up from DeltaMin rather than zero.

    But just now I am helping with Tree decoration and am starting beef broth for braising chuck roast on Monday.
  • Tom,
    It sounds like you are doing the important things. Enjoy.
    I'm just starting to shop for my nieces and nephews.

    Tom M.
  • tomcrawfordtomcrawford Posts: 1,126
    edited 2017-12-17 17:52
    Here is a new version of the DAT section only. Should be able to put it right on top the old DAT. Basically, it makes servos start up from zero whenever a servelocity is issued.

    Tom C
  • Tom,
    I tried the new DAT section. It solved the "one servo starting before the other" issue, but one of its effects is that it is not possible to change speed while traveling in the same direction without stopping. For example, starting to move fwd at 20 rpm, increasing speed to 40 and then 80 rpm, the servos come to a stop before each speed change. With the previous version, the servos appeared to keep turning during the speed change.

    Tom M.
  • kwinnkwinn Posts: 8,697
    @Tom M
    Here is a new version of the DAT section only. Should be able to put it right on top the old DAT. Basically, it makes servos start up from zero whenever a servelocity is issued.

    Tom C

    Wouldn't this start from zero account for that?
  • kwinn wrote: »
    @Tom M
    Here is a new version of the DAT section only. Should be able to put it right on top the old DAT. Basically, it makes servos start up from zero whenever a servelocity is issued.

    Tom C

    Wouldn't this start from zero account for that?

    It accounts for it, all right. Tom is just sayin' that is not the way it should work. He is correct, of course. I hope to find some time over the weekend.
  • Tom M,
    This ought to be mo' better. I ramp up (or down) from the current delta or from DeltaMin, whichever is greater. It seems to change speeds pretty smoothly.

    I added another demo segment that exercises the ramping capability. I am also posting just the PASM portion.

    I think I will replace my original on OBEX next week.
    tom c
  • Tom,

    Thanks. I haven't had a chance to look at the program in detail yet.
    Were the changes made to only the DAT section or were there also changes to the Spin functions (in FeedBackServo5)?

    Thanks again
    Tom M.
  • tomcrawfordtomcrawford Posts: 1,126
    edited 2017-12-24 17:00
    Changes were made only to the DAT section. The rest of FeedBackServo5 is identical to FBS4.

    Edit: I posted the DAT section as a separate file. Endedit

    tom C
  • twm47099twm47099 Posts: 867
    edited 2017-12-24 19:30
    Thanks -- it works. (and gives me a few examples of PASM to study.)

    I've attached a zip of the full C program that contains the driver and my demo (didn't add a smooth ramp function to my demo yet). I will turn this into a SimpleIDE library when I get a chance, but for now it runs as one program (with FeedBackServo4.spin updated to include the new DAT section in the same folder).

    I did change the pin numbers to those used by the Parallax SimpleIDE servo360 library instead of the ones we've previously used. Now they are:
    #define CP0 12      // also for ActivityBot left wheel (CCW = fwd)
    #define CP1 13      // also for ActivityBot right wheel (CW = fwd) 
    #define CP2 16      // Servo2 control
    #define CP3 0
    #define FP0 14      // Servo0 feedback
    #define FP1 15      // Servo1 feedback
    #define FP2 17      // Servo2 feedback
    #define FP3 0

    I'm not happy about using the ActivityBoard servo header for the feedback pins since those headers can supply Vin for servos that need higher than 5v. In the future when I've explored the Parallax library and figured out how to change pin numbers I will change the feedback pins to something less than P12.

    Tom M.

    Edit: I deleted the zip and reposted version "b" in the post below. I had to correct my method for stopping the servo rotation in the demo. I added a new driver function "fbsdrivestop()" that stops the rotation by using the Width function to set 1500 usec in each wheel servo.

  • Here is a logic capture of accelerating from 20 CCW to 40 CCW. The yellow trace is pulsed when the pulse width is increased by one microsecond; the green trace when the pulse width is decreased. Wider pulses mean faster CCW. The pulse on the red trace is the demo program just prior to issuing the faster FBS.SetVelocity command.

    Prior to the new command, you can see increase/decrease cases that pretty much balance each other. Immediately following the new command, a lot of increases take place until the servo has ramped up to the new velocity; then the increases/decreases again balance each other. It takes about 1/2 second.
    1366 x 768 - 305K
  • Attached is the modified program mentioned in the post above.
    Tom M.
  • I tried to upload the new version to OBEX but was unable to convince it that I am not a robot.
  • Here is the latest final version.
    Tom M, the DAT section is exactly the same as above except the debugging instructions are removed altogether rather than commented out.
  • Updated version of my driver is on OBEX. It includes the fix to SetVelocity() that ramps from the current velocity rather than from zero.
  • Idle speculation, could Parallax build these as a cheap encoder by leaving out the motor?
  • There isn't a measurent on the mechanical drawing to the centre of the shaft. What is the relative distance to the centre of the shaft ?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2018-02-15 18:03
    It's the same as for a standard servo:


    In this case, B = 0.53", and C = 1.33". IOW, the shaft is offset from the center by 0.4".

Sign In or Register to comment.