Shop OBEX P1 Docs P2 Docs Learn Events
PropBasic Counters & Servos — Parallax Forums

PropBasic Counters & Servos

skynuggetskynugget Posts: 172
edited 2011-11-12 10:29 in Propeller 1
Hello All!

i am trying to emulate JonnyMacs neat way of driving multiple servos with the system counter (jm_servo8_adv.spin) in PropBasic. Here is what i came up with so far, and it "kind of" works, but there is no real tourqe on the servo turn, and it chatters like a mofo when it gets to the target location.

i suspect my math for the timing is off, does anything see anything wrong with this?

thanks in advance!

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2011-10-24 20:06
    Which version of the compiler are you using? With 1.14 stuff like 2500 * us001 gets mistranslated. BTW, us001 should be 80 not 5 for your setup. The code generated is (us001 == 80):
    mov     tmp,_2500           '    tmp = 2500 * us001
    shl     tmp,#4                      
    
    This basically messes up your timing.
  • skynuggetskynugget Posts: 172
    edited 2011-10-24 20:19
    thanks for the heads up kuroneko, ill try that when i get back to the the compiler. im using v1.25
  • kuronekokuroneko Posts: 3,623
    edited 2011-10-24 20:25
    Do you have a link for 1.25?
  • kuronekokuroneko Posts: 3,623
    edited 2011-10-24 20:57
    Thanks, but that doesn't generate any output for me (1.14 generates 2 SPIN files). I tried two different machines (XP and Vista, JPN) and both come up empty. Anyway, if you can find a way to inspect the generated code have a look at the 2500 * us001 line.
  • skynuggetskynugget Posts: 172
    edited 2011-10-24 21:18
    odd, are you using bst? i don't think this version will work as it doesn't have the hooks, its straight from Bean. ive been using viewport and cedit to compile with this version.
  • kuronekokuroneko Posts: 3,623
    edited 2011-10-24 21:23
    skynugget wrote: »
    odd, are you using bst?
    Initially I used it from the command line (which works for the 1.14 release). Then I tried bst and it died (as expected). Maybe it's tied to viewport in a way and requires a specific environment. Beats me.

    So in order to check if the same bug is still present you could multiply by 80 manually (*5*16):
    tmp = pos << 2    ' *4
          tmp = tmp + pos   ' *5
          tmp = tmp << 4    ' *80
    
    And the other location could just load 200000 (2500*80) directly.
  • skynuggetskynugget Posts: 172
    edited 2011-10-24 21:39
    ha i just realized i based all my math on 5mhz instead of 80, i guess i just had the crystal value stuck in my head! still playing around so far.
    here is what is generated:
     mov           tmp,_2500                    '    tmp = 2500 * us001
                      mov           __temp1,tmp                 
                      shl           tmp,#4        
    
  • kuronekokuroneko Posts: 3,623
    edited 2011-10-24 22:24
    Just remembered something re: [thread=134729]multiply with constants[/thread] (outstanding bug). When you move us001 into a variable first then it should generate proper multiply code, e.g.
    tmp = us001
    tmp = pos * tmp
    
  • skynuggetskynugget Posts: 172
    edited 2011-10-25 12:28
    got the task timing all the servos now! il post up the rest once i have time to get the subs done, thanks!
    ' ----- TASK Variables (LONG only) ------------------------------------
    us001   con 80 '5   '80_000_000 / 1_000_000 tick per microsecond
    so      con 18  'servo offset start at pin 18
    
    idx     var long
    outpin  var long
    
    slot    var long
    pos     var long
    tgt     var long
    dlt     var long
    tmp     VAR long
    
    ' ----- SUB and FUNC Definitions ---------------------------------------
    '(2^32)/clkfreq = 4294967296/80_000_000 = 53.6870912
    'clkfreq=80_000_000  53.6870912 * 65536 = 3518437.2088832
    
    SrvStart:
      OUTPUT servos
      frqa = 1                      'preset for counter
      phsa = 0
      slot = cnt
      
    SrvMain:
      for idx = 0 to 7
        rdlong position(idx), pos   'get chanel position value
        rdlong target(idx), tgt     'get channel target value 
        rdlong delta(idx), dlt      'get speed value
        
        outpin = idx + so           'set servo pin via offset 
        COUNTERA 32,outpin          'start counter
          tmp = pos * us001          
          phsa = -tmp 
          
        if pos < tgt then           'is pos less the taget pos?
          pos = pos + dlt 
          pos = pos max tgt
        elseif pos > tgt then
          pos = pos - dlt
          pos = pos min tgt
        endif
      
        tmp = 2500 * us001           'slot timing
        slot = slot + tmp
        WAITCNT slot                'wait for slot to finish
      
        ctra = 0
        wrlong position(idx), pos   'put channel poition value
      next
      goto srvmain                  'loop
    
    ENDTASK
    
  • skynuggetskynugget Posts: 172
    edited 2011-11-12 10:29
    here is what i ended up with. it seems to work rather well except for one bug i can't seem to figure out.

    if you the first set_servo you use has a speed other then 0, the servo will swing all the way to the srvmin pos at full speed, then will turn to the requested position at the requested speed. i got around it by just initiating all the servos with no speed control when i start the program.

    special thanks to bean, jonnymac, and parallax.

    if ya make it better please share!
Sign In or Register to comment.