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

Servo problems

Dave HaldaneDave Haldane Posts: 2
edited 2008-11-21 19:39 in Propeller 1
I'm incredibly new to the spin language, but I've already gotten myself in deep: I've got 2 weeks to get an r/c project working.

Anyways, after slapping the chip in my PDB, I decided to write a bit of servo code, to see if it works. I've got experience in BS2 programming, but I was having trouble getting the library to work for me, so decided I'd give it a whack just using some basic Spin language.

Here's the code:


{{PWM_test.spin}}

CON
  pwidth_high   = 28_800                                '180 degree pulse time  (2400 uSec)
  pwidth_low    = 7_200                                 '0 degree pulse time    (600 uSec)
  duty          = 240_000                               '20ms between pulses
  pause         = 6_000_000                             ' .5 Sec pause
  pin           = 17                                    'PWM signal pin
  High          = 1                                     'High constant
  Low           = 0                                     'Low constant
  Out           = %1                                    'Output constant
PUB Main

dira[noparse][[/noparse]pin] := Out                                        'Set pin 17 to Output

  repeat
    repeat 5                                            'repeat position signal 5 times
     outa[noparse][[/noparse]pin] := High                                  'Set output pin high
     waitcnt(cnt + pwidth_low)                          'Wait for low-end pulsewidth
     outa[noparse][[/noparse]pin] := Low                                   'Turn off output pin
      waitcnt(cnt + duty)                               'wait 20ms before repeating signal
    waitcnt(cnt + pause)                                'wait half a second
    repeat 5                                            'repeat position signal 5 times
     outa[noparse][[/noparse]pin] := High                                  'set output pin to high
     waitcnt(cnt + pwidth_high)                         'send long pulsewidth
     outa[noparse][[/noparse]pin] := Low                                   'turn off pin
     waitcnt(cnt + duty)                                'wait 20ms before repeat
    waitcnt(cnt + pause)                                'wait .5 Sec before repeat
    





The result of the code was the servo bouncing off one limit until jumpin.gif *bad click* (It didn't take much bouncing). I tried a couple variations, but couldn't ever manage to get the servo to behave like I meant it to (moving from one limit to the other)

When I changed the pause time to 2 seconds, I managed to get the thing to move through 90 degrees of its sweep, not the full 180 I expected.

So I'm taking the servo apart to repair it, and I hope maybe someone out there can help my in the meantime.

Ah, the equipment

Professional development board: Pin 17 wired to servo output 0
http://www.servocity.com/html/hs-635hb_high_torque.html on servo output 0


Any help at all would be appreciated. I wouldn't be surprised if I was implementing PWM incorrectly, mis-treating the servo, or performing various other faux-pas... I'm rather new to this.

Comments

  • JasonDorieJasonDorie Posts: 1,930
    edited 2008-11-20 19:23
    The internal oscillator is not very precise, and can vary a lot (like 8 Mhz) from the 12Mhz you expect. A typical servo responds to a pulse width in the range of 1500 uS +/- 500 uS. You're well outside that range already, and if your prop is running slower or faster than normal, you'd be WAY outside that and could easily damage the servo. Using a crystal will make the oscillator much more accurate. Note that I said 'typical' servo. Some servos DO respond to signals outside that range - Just be sure.

    Servos require constant pulses at 50hz to make them hold. During your pause you aren't sending anything, so if your servo hasn't gotten into position, it'll just stop because it's no longer being told to. If the servo has a relatively slow response time, 5 cycles might not be enough time for a full sweep.

    If you're doing this as a programming exercise, great - If not, you're probably better off using the Servo32 object that comes with the Prop libraries. It'll drive up to 32 servos with 1uS resolution, runs on its own cog, is written in ASM, etc. It would probably save you a good deal of time. [noparse]:)[/noparse]

    Jason
  • GavitronGavitron Posts: 3
    edited 2008-11-20 23:27
    Hi Dave,

    Yesterday I·posted a reply to the "Using a cog to control a motor" thread and uploaded some programs under the name "RC_Servo_Control" to the Propeller object exchange site that show you some easy ways to control RC servomotors with the Propeller. As Jason said, you should not use the internal oscillator when you need precise timing. I recommend using an 80MHz system clock (the maximum). The professional development board has a 5MHz crystal, so you just have to add the following two lines·to the top of your code to use this external crystal and·get the phase locked loop to multiply its frequency by 16 times to give you 80Mhz.
    CON
      _xinfreq=5_000_000            
      _clkmode=xtal1+pll16x      'The system clock is now set to 80MHz                                             
                                                                                                                            
    


    Also, FYI, because of the way the Propeller executes Spin instructions, you should always add the system counter value (cnt) last (on the right)·when using·the waitcnt instruction (e.g., use "waitcnt(pwidth_low+cnt)") . Otherwise, the cnt value will continue increase as the other value is processed and added,·which will result in·the timing·being off.

    The good news is that if you·were using·a Parallax/Futaba Standard Servo with a 5V power supply, then based on my experience, I doubt that you could have done·any serious internal damage to·it with your previous attempts. When you take it apart, you may notice that the white plastic tab on the output shaft (under the servo's horn) may have sheared off a plastic gear tooth. The servo should still work okay though for most applications. If it doesn't work with my demo programs, then you may have burnt out a coil in the DC motor's rotor armature (by·passing too much current through it when the motor was stalled). If this is the case, you'll need a new servomotor.

    Check out my post on·this thread...

    ·http://forums.parallax.com/showthread.php?p=763415

    -Gavitron
  • Dave HaldaneDave Haldane Posts: 2
    edited 2008-11-21 19:39
    Hey everyone,
    Thanks a lot for the help. I only lost one servo in a big way to the clock issue. Two others got grumpy, but they're mostly repaired out of parts of the first one (heh heh, frankenservo).

    Anyways, the clock change and using the servo32 library helped a lot. Here's the test code I ended up writing.

    {{PWM_test2}}
    ''Makes use of Servo32v3 library to sweep a servo across most of its travel
    CON
        _clkmode = xtal1 + pll16x                  'set clockmode to crystal speed x 16        
        _xinfreq = 5_000_000                       'set crystal frequency input to 5MHz
        speed_delay = 80_000                       'Set speed of Servo
       
    VAR
      long cur_pos                                 'current servo position
    
    OBJ
      SERVO : "Servo32v3"                          'Assigns Servo Library object
    
    PUB Main                                       'Cues Servo to low end
    cur_pos := 1000                                'Passes Servo position to Servo Object
    servo.set(17, cur_pos)                         'Initializes Servo Object
    servo.start
    
    repeat                                         'Repeat loop for constant sweep  
     waitcnt(speed_delay + cnt)                    'Waits speed_delay/80M seconds 
     servo.set(17, cur_pos)                        'Sends new servo position
     cur_pos++                                     'Increments servo position
     if 1850 < cur_pos                             'evaluates if upper limit is reached
        repeat until cur_pos == 1001               'Repeats until servo is at lower limit
          waitcnt(speed_delay + cnt)               'Waits for speed_delay/80M seconds
          servo.set(17, cur_pos)                   'Sends servo position
          cur_pos--                                'decrements servo position
    
    
    



    Thanks everyone!
Sign In or Register to comment.