Shop OBEX P1 Docs P2 Docs Learn Events
Servo problems - Page 2 — Parallax Forums

Servo problems

2»

Comments

  • RichardFRichardF Posts: 168
    edited 2007-06-06 11:39
    AttoPilot,
    Thanks for the suggestion on servo32.spin. This is one of my hobbies, along with RC model airplanes. I am prone to want to do everything on my own from scratch for the fun of it, but in this case I may have to break ny own rules. What is frustrating is that my BS2 bot really did great things, like obstacle avoidance and using sensors for navigation, but I didn't like having to do everything in sequence due to the single processor, so the Propeller was the obvious upgrade. I am not getting discouraged, the Prop is so far and above the BS2, it has just been a little frustrating thats all.
    Richard
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2007-06-06 12:14
    So is the circuit breadboarded rather than soldered on the whole?

    I wonder if it is just a bad connection, might be worth checking resistances leg to leg between components etc.

    Graham
  • RichardFRichardF Posts: 168
    edited 2007-06-06 12:16
    Totally breadboarded at this point. I will follow your suggestion.
  • RichardFRichardF Posts: 168
    edited 2007-06-06 22:20
    Yiiikes! my troubles with this chip are never ending.

    Here's the latest:

    Servo speeds change based on the number of repeats in a loop. No kidding! Both servos are running forward under a repeat direction command when the number of repeats is less than 28. When the number of repeats goes above 28 they change directions. Not only that, I can change servo speeds with the repeat number!

    The order in which I initiate a cog process seems to matter. If I initiate the blinking LED cog process before the servo command process, it works fine. Put it after the servo command process and it wont run.

    The "if ina[noparse][[/noparse]pin]"·and·"if not ina[noparse][[/noparse]pin]" directives are erratic. Sometimes they work, sometimes they don't.

    All the while the LED keeps blinking at 1 Hz supposedly indicting the clocks are working okay.

    I am obviously frustrated. Either I have a bad chip or I am really dumb. I am hoping for the bad chip. I will talk to Parallax and get a new chip to try. I will let you know how this works out. Thanks for all of the inputs.

    Richard
  • rokickirokicki Posts: 1,000
    edited 2007-06-06 22:52
    I'd bump the stack from 20 to 50 to be safe (probably not an issue though).

    Also note that each servo is only being updated at 25 times a second because you are doing the
    right and left alternating. (You are only using a single cog for both servos and you are sending
    one pulse to one, waiting 1/50th of a second, then sending a pulse to the other one, and again
    waiting 1/50th of a second.) You might want to use /100 to get updates at 50hz to each
    server, alternating pulses. An update rate of only 25hz will definitely cause the servos to
    act more "jerky" than they normally do.

    Note that there will assuredly be at least some small influence from servo to servo because of
    this (a longer pulse width on the right will also slow the update rate on both, so the same value
    for the left pulse will have different behavior depending on the pulse width for the right.)

    What I would do here is either use FullDuplexSerial or else TV to send output back, and add
    in some debugging printfs. I suspect your ldir/rdir variables are not holding the values you
    think they are.

    Note that the initiated cog will probably not start running until some time after the initiation
    command returns. (It takes some time for a cog to start up, during which the cog that
    started it continues to run.) And this time is affected by the clock rate.

    I still don't understand what is going wrong, however; none of these observations here
    really explain the behavior you are seeing. Your comments on "repeat" don't make sense
    with respect to the earlier code; as always, please attach full code whenever reporting new
    observations.

    When you say "initiate the blinking LED cog process after the server process and it wont
    run" I'm not sure what you mean; what do you observe, and how does that differ from
    what you expect?

    Post your latest complete code and I'll download it to my boebot (after changing the
    servo pin numbers) and let you know what it does on my bot.
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2007-06-07 00:31
    Richard,

    May I suggest that you post as a file the most representative program you have run.

    Also post a picture of your set up.

    And try servo32 just as a test.

    Graham
  • RichardFRichardF Posts: 168
    edited 2007-06-07 12:20
    I got up this morning after a good nights sleep, cleared my mind, and rewired my board and rewrote my program from the beginning, testing each part as added. Attached is the most basic·two_wheeled robot control program which allows you to enter a single robot direction. It works perfectly! The next step is to add a command/direction sequence using variable addresses (pointers) so the servo directions can be changed·on the fly. I wanted everyone to see what I have at this point and the fact that it is working at Pll16x.·However, the problem of changing clock frequency causing a change in "waitcnt" still exists. If I do nothing more than change clkfreq to pll1x the timeing is completely·different and I have to rewrite the "case" satement with new timing values to get the same servo diection results. By the way, all jittering is gone. This doesn't effect my project because I don't need to change clock frequency at run-time, but something is still wrong and I would like to know what it is. When I get the run-time servo direction changes going I will post that.
    Thanks,
    Richard

    Post Edited (RichardF) : 6/7/2007 1:05:40 PM GMT
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2007-06-07 13:23
    By scaling the way you do you ensure that the target for the waitcnt is correct. However the time between the outa[noparse][[/noparse]18]~~ and the waitcnt beginning to wait will vary depending on the clock frequency of the processor because the time taken to evaluate the division will vary.

    Either do all the calculation of the argument for the waitcnt outside of the loop or do:

    repeat
      outa[noparse][[/noparse]18]~~  
      c:= cnt
      waitcnt(clkfreq/direct + c)
      outa[noparse][[/noparse]18]~
      c:= cnt
      waitcnt(clkfreq/50 + c)
    
    



    This way you have taken a note of cnt and it can continue ticking away while you work out the target.

    This may not work for slower clock frequencies (if the calculation takes too long) and you will need to tweak your values a little to begin with.

    Graham

    [noparse]/noparse]edit: the matlab code won't help [noparse]:)[/noparse
  • RichardFRichardF Posts: 168
    edited 2007-06-07 16:44
    I failed to mention that when I rewired my breadboard this morning I kept all leads as short as possible (wires layed flat and direct). The fact that the jittering has gone away, as well as some other wierd behavior I was observing, indicates possible radio frequency interference being fed back into the chip. This may explain why 80MHZ would not work before and now it does. Also, no jittering points to the same thing. The servo motors are brushed and probably sparking. With long length looping wires running from point to point on the breadbooard it is possible RF was being fed through the servo leads into adjacent wiring. I would like to hear what Parallax thinks about this possibility.
  • Beau SchwabeBeau Schwabe Posts: 6,547
    edited 2007-06-07 17:51
    RichardF,

    If you change the scaling factor of the code below....
      outa[noparse][[/noparse]16]~~
      waitcnt(clkfreq/direct + cnt)
      outa[noparse][[/noparse]16]~
      waitcnt(clkfreq/50 + cnt)
    
    



    ...So that it reads...

      outa[noparse][[/noparse]16]~~
      waitcnt((clkfreq/1_000_000)*direct + cnt)
      outa[noparse][[/noparse]16]~
      waitcnt((clkfreq/1_000_000)*20_000 + cnt)
    
    



    ...and you change your case statements so that they read...

    case direction
      stop:
        left_dir  := 1510
        right_dir := 1515
      forw:
        left_dir  := 1351
        right_dir := 1666
      back:
        left_dir  := 1666
        right_dir := 1351
      left:
        left_dir  := 1510
        right_dir := 1666
      right:
        left_dir  := 1351
        right_dir := 1515
    
    



    ...You can save yourself the headache of having to re-calculate your current 'case' statements at different PLL frequencies. (pllx settings 1,2,4,8,16)







    "The servo motors are brushed and probably sparking. With long length looping wires running from point to point on the breadbooard it is possible RF was being fed through the servo leads into adjacent wiring."
    ·
    Yes these can all cause a servo to·jitter.
    ·
    Do you have a current limiting resistor between the Propeller I/O and the servo?· Since you are using a Propeller (3.3V system) with a Servo (> 3.3V system) a resistor is required to prevent I/O damage to the Propeller.· Also, the resistor is two-fold, it acts as a shunt to suppress or dampen any voltage spikes that could be generated from a noisy servo.
    ·
    With long leads from the Propeller I/O, and power·to the servo, it is suggested that you use a 1000uF capacitor as close as possible to the servo power connector.·
    ·
    ·····





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

    IC Layout Engineer
    Parallax, Inc.

    Post Edited (Beau Schwabe (Parallax)) : 6/7/2007 6:01:27 PM GMT
  • RichardFRichardF Posts: 168
    edited 2007-06-07 17:57
    Well, I am glad to announce I now have my bot running smoothly on the Propeller chip and it works great. I am attaching the automonous roving program with whisker obstacle avoidance. Any suggestions would be most welcome and thanks for all of the help. I will be working on better ways for timing the pulses to the servos, putting in rampup and rampdown methods, as well as navigation sensors.

    Thanks again,

    Richard

    Post Edited (RichardF) : 6/7/2007 7:12:29 PM GMT
  • RichardFRichardF Posts: 168
    edited 2007-06-07 17:59
    Beau,

    I didn't see your post until right now. I will incorporate your recommended changes and test it out at different clock frequencies.

    Richard
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2007-06-07 18:06
    Beau,

    Why should it make a difference?

    (clkfreq/1_000_000)*direct is basically:

    clkfreq * (direct/1_000_000)

    Where as what he was doing was:

    clkfreq * 1/direct

    Both (direct/1_000_000) and (1/direct) are constants independant of the PLL.

    I'm just a bit confused now.
  • Beau SchwabeBeau Schwabe Posts: 6,547
    edited 2007-06-07 19:56
    Graham Stabler,

    The short simple answer... It's easier to read the actual uS that you want to delay rather than the inverse of the delay, and you get slightly better resolution.

    Take for example the first value he has for 'direct' to keep the left servo centered... 662

    Example1:
    using the formula...
    ClockCounts = clkfreq * 1/direct
    ClockCounts = 80_000_000 / 662
    ClockCounts = 120845

    To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1510uS (typical servo center is 1500uS)

    Example2:
    using the same formula now we'll use 663
    ClockCounts = clkfreq * 1/direct
    ClockCounts = 80_000_000 / 663
    ClockCounts = 120663

    To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1508uS


    Example3:
    using the same formula now we'll use 661
    ClockCounts = clkfreq * 1/direct
    ClockCounts = 80_000_000 / 661
    ClockCounts = 121028

    To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1512uS


    Example4:
    using the formula...
    ClockCounts = (clkfreq/1_000_000)*direct
    ClockCounts = (80_000_000 / 1_000_000)*1510
    ClockCounts = 120800

    To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1510uS

    Example5:
    using the same formula now we'll use 1511uS
    ClockCounts = (clkfreq/1_000_000)*direct
    ClockCounts = (80_000_000 / 1_000_000)*1511
    ClockCounts = 120880

    To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1511uS

    Example6:
    using the same formula now we'll use 1509uS
    ClockCounts = (clkfreq/1_000_000)*direct
    ClockCounts = (80_000_000 / 1_000_000)*1509
    ClockCounts = 120720

    To confirm this, multiply 'ClockCounts' by 12.5nS and you get 1509uS

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

    IC Layout Engineer
    Parallax, Inc.
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2007-06-07 22:12
    That's what I thought but even with his way or writing it the pulse widths should have shifted with pll multilier to provide roughly the same pulse width:

    @ 80Mhz

    ClockCounts = clkfreq * 1/direct
    ClockCounts = 80_000_000 / 662
    ClockCounts = 120845 = 1510uS

    @ 40Mhz

    ClockCounts = clkfreq * 1/direct
    ClockCounts = 40_000_000 / 662
    ClockCounts = 60422 * 25ns = 1510uS

    Which is what made me suggest taking a note of cnt while the argument of the waitcnt was calculated, I could not see a reason why it would not work as it was.

    Graham
Sign In or Register to comment.