Shop OBEX P1 Docs P2 Docs Learn Events
Spin Grammar — Parallax Forums

Spin Grammar

jaegjaeg Posts: 156
edited 2012-03-14 09:51 in Propeller 1
I'm working on a biped as I stated in my last topic (sorry for starting a new one, I go to a lot of forums where they jump on you for asking different questions in the same thread). I originally was using an Arduino and I designed a class to contain each joint in the robot so I can easily retrieve and set angles amongst various other things. Now to do this in Spin I'm assuming I would design the object the same way the Servo driver is designed (like any other program). So this is my question: Is it gramatically correct for me to do this?

LHip : "Joint.spin"
LKnee : "Joint.spin"
LAnkle : "Joint.spin"
RHip : "Joint.spin"
RKnee : "Joint.spin"
LAnkle : "Joint.spin"

Joint.spin will have functions for setting the pin number the joint is operating on, getting angles, converting angles into frequencies, etc etc.
Right direction?

Comments

  • Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
    edited 2012-03-05 17:04
    Better might be something like this...
    CON
    
      '' Servos plugged into Propeller I/O
    
      LHip   = 0
      LKnee  = 1
      LAnkle = 2
      RHip   = 3
      RKnee  = 4
      LAnkle = 5
    
    OBJ
    
     Joint : "Servo32v5.spin"   
    
    
    PUB  Move | data
    
    Joint.Set(LHip,data)  
    
    
  • jaegjaeg Posts: 156
    edited 2012-03-05 17:14
    Hmm.. ok
    Part of my goal was to use it as a data bag so I could have in contain angle, max, min, and other data along with several new functions. I'm use to programming in C++ if that explains my intentions at all haha
    {{
    *****************************************
    * BRAT                                  *
    * Author: John Godsey                   *
    *****************************************
    }}
    
    CON
        _clkmode = xtal1' + pll16x                           
        _xinfreq = 5_000_000                                'Note Clock Speed for your setup!!
    
        LHip = 4
        LKnee = 5
        LAnkle = 6
        RHip = 8
        RKnee = 9
        RAnkle = 10
    
    VAR
      WORD value 
        
    OBJ
      pst   : "Parallax Serial Terminal"
    
      LHipJoint : "Joint.spin"
      LKneeJoint : "Joint.spin"
      LAnkleJoint : "Joint.spin"
    
      RHipJoint : "Joint.spin"
      RKneeJoint : "Joint.spin"
      RAnkleJoint : "Joint.spin"
    
    PUB Brat | temp
        
        pst.Start(9600)
        pst.Str(String(" Init "))
    
        LHipJoint.init(LHip,500,2500)
        LKneeJoint.init(LKnee, 500, 2500)
        LAnkleJoint.init(LAnkle, 500, 2500)
    
        RHipJoint.init(RHip,500,2500)
        RKneeJoint.init(RKnee,500,2500)
        RAnkleJoint.init(RAnkle,500,2500)
    
        LHipJoint.setPulse(1500)
        LKneeJoint.setPulse(1500)
        LAnkleJoint.setPulse(1500)
    
        RHipJoint.setPulse(1500)
        RKneeJoint.setPulse(1500)
        RAnkleJoint.setPulse(1500)
         
        repeat
          value +=1  
          pst.Dec(value)
          pst.Str(String(","))                                      
    
    
            
           
          waitcnt(clkfreq*1+cnt)     
    
    
    {{
    ******************
    *Joint.spin
    *Author: John Godsey
    *Description: Provides easy control and access to servo data in a multiservo robot
    *
    
    }}
    con
    var
      BYTE pin
      WORD minFreq
      WORD maxFreq
    
    obj
    Servo : "Servo32v7LowPower.spin"
    
    pub init(tempPin,tempMinFreq, tempMaxFreq)
      pin := tempPin
      minFreq := tempMinFreq
      maxFreq := tempMaxFreq
      Servo.Start
    pub setPin(tempPin)
      pin := tempPin
    
    pub setMinFreq(tempMinFreq)
      minFreq := tempMinFreq
    
    pub setMaxFreq(tempMaxFreq)
      maxFreq := tempMaxFreq
    
    pub setPulse(freq)
      Servo.Set(pin,freq)
    

    That's a ruff version of it so far. I'm implementing an angle system so I can just set the limb to say 0 degrees or 90 degrees instead. I'm not use to programming with cogs so does the joint having a servo object cause it to use up too many cogs when used like this?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-03-05 19:09
    I know there are some very successful Propeller powered hexapods and it would be probably a good idea to see how they keep track of their servos (not that you're trying to make a hexapod, but I bet their systems would also apply to bipeds). I haven't looked at the other methods yet because I wanted to try and figure out the IK calculations on my own first.

    This is the approach I took with my hexapod project. I have arrays to hold the various servo parameters.
    long targetX[_LegsInUse], targetY[_LegsInUse], targetZ[_LegsInUse]
      long fDx[_LegsInUse], fDy[_LegsInUse], fDz[_LegsInUse], fInitX[_LegsInUse], fInitY[_LegsInUse], fInitZ[_LegsInUse]
      long fTheta0[_LegsInUse], fTheta1[_LegsInUse], fTheta2[_LegsInUse] 
    


    Here are some byte sized arrays.
    byte servoPin[_ServosInUse] 
      ' used to hold which tripod set is use
      byte limb[_LegsInUse]
      ' each will hold the sevo index used to control it.
      byte waist[_LegsInUse], hip[_LegsInUse], knee[_LegsInUse] 
    
    

    Those are actually just a few of the many parameters. I think you could guess the constant "_LegsInUse" has a value of six and "_ServosInUse" is set to 18.

    Early in my program I assign the servo IDs to each joint.
    repeat localIndex from 0 to 5
        waist[localIndex] := localIndex * 3
        hip[localIndex] := localIndex * 3 + 1
        knee[localIndex] := localIndex * 3 + 2
    

    This lets me use methods that have either servo indexes or leg indexes as parameters depending on which index makes more sense logically to use.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-03-05 19:18
    I don't know if you've seen Paul K.'s hexapod project. Watching Paul demo his hexapod on YouTube is what made me want to try to build one myself.

    I've been holding off studying Paul's code to see how much I could figure out myself but I bet (based on his results) there is a lot one could learn about controlling servos by reading Paul's code.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-03-05 19:23
    jaeg,

    There's nothing wrong with your original proposal. It just creates separate instances of the same object whose VAR variables can contain the state of each one. Another way to do the same thing is:
    CON
    
      LHip   = 0
      LKnee  = 1
      LAnkle = 2
      RHip   = 3
      RKnee  = 4
      LAnkle = 5
    
    OBJ
    
      joint[6] : "Joint"
    

    Then you can access the various instances by joint[LHip].method, joint[RHip].method, etc.

    -Phil
  • jaegjaeg Posts: 156
    edited 2012-03-05 19:33
    Thanks Phil. One more question due to my ignorance of what actually gets put into a cog. Does each joint get stuck into separate cogs? Or is it the functions them self that actually go into cogs when called? If not then I'm good to go if they do all go into their own separate cogs I could see it causing problems.


    EDIT
    By the way in case anyone wants it here is how I convert degrees to frequencies:
    pub setAngle(angle)|freq
        freq :=500+(angle*11)
        Servo.Set(pin,freq)
    

    There are limitations though. No angles with decimal values. Also this is assuming a 500 to 2500 range. It is really easy to figure a new constant though: (center frequency - min frequency) / 90. If you want to change the min angle change 500 in the equation.

    I figured out how to do this today after a little number crunching and hadn't seen anything about it on Google so I figured I'd share.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-03-05 20:11
    Each joint object will remain in the cog that calls it, unless there's code in one of the joint methods that starts a new cog. Calling an external method does not put that method in a new cog before executing, either. BTW, the only things unique to (i.e. replicated for) each object instance are the VAR variables. The code and DAT variables are included in RAM only once.

    -Phil
  • jaegjaeg Posts: 156
    edited 2012-03-06 06:02
    Now that's awesome. I've always wanted to get my robot to run with a Propeller and now that my servo problem was fixed and I can port my code I'm having a blast. The Spin language is kinda funky but I'm getting use to it. I can't wait till the GCC compiler comes out for the Prop. I'm a C++ programmer natively.
  • JonnyMacJonnyMac Posts: 9,197
    edited 2012-03-06 07:59
    I can't wait till the GCC compiler comes out for the Prop. I'm a C++ programmer natively.

    You can jump into the Alpha test now. And if you're a Windows user then Jazzed (Steve) has created a beautiful little IDE that installs the works and has you up and running in about a minute (Linux and Mac ports are in the works).

    -- http://forums.parallax.com/showthread.php?138404-SimpleIDE-Version-0-5-0-Available

    Funny, I think C is "funky" and have no trouble with Spin and PASM, but I am using Prop-GCC to learn C now so that my (EFX-TEK) customers can have more programming language choices with our Propeller-powered boards.
  • jaegjaeg Posts: 156
    edited 2012-03-14 09:51
    That is really tempting. I've never done alpha testing before but it sounds like it would be worth a try.
Sign In or Register to comment.