Shop OBEX P1 Docs P2 Docs Learn Events
Cog doesnt run — Parallax Forums

Cog doesnt run

portblockportblock Posts: 9
edited 2008-03-10 02:12 in Propeller 1
Please forgive me if I am in the wrong area or if this has been asked before...

My issue is that the cognew does not apear to be working.

If I call the servodrive directly without doing a cognew, it drives the servos no problem.

Also, it looks like my code also doesnt work as for the variables, example, in main:

servoDriver.setPosA(1500)
the var gets set to 1500, however, the cog never sees this update.

I have seen all the examples of passing pointers, however, I do not want to pass pointers in a function declaration (PUB)

How do I make this code work?



Source:
----MAIN.SPIN----

' Some constants
CON
· _CLKMODE = XTAL1 + PLL16X 'Set to ext. low-speed crystal
· _XINFREQ = 5_000_000 'Frequency on XIN pin is 5 MHz
· ' common stuff constants
· LOW··· = 0
· HIGH·· = 1
· INPUT· = 0
· OUTPUT = 1
· ON···· = 1
· OFF··· = 0
· STACK_SIZE_SX = 23
' *** define some pins ***

VAR

OBJ
· servoDriver : "servo_drive"
PUB Main
· servoDriver.initialize
· servoDriver.start
· servoDriver.setPosA(1500)
· servoDriver.setPosA(1100)

· dira[noparse][[/noparse]16] := OUTPUT
· repeat
··· outa[noparse][[/noparse]16] := HIGH
----END CODE----

----SERVO_DRIVE.SPIN----
CON
··· _clkmode = xtal1 + pll16x··························
··· _xinfreq = 5_000_000
· ' common stuff constants
· _1uS·· = 1000000
· LOW··· = 0
· HIGH·· = 1
· INPUT· = 0
· OUTPUT = 1
· ON···· = 1
· OFF··· = 0
· FRAME_RATE_SX = 20000········· ' uS frame rate
· PIN_SXA·· = 0
· PIN_SXB·· = 1
· PIN_SXC·· = 2
· PIN_SXT·· = 3
· STACK_SIZE_SX = 9·
VAR
· word· pwSwashA·············· ' swash pulse width ' measured in microseconds
· word· pwSwashB·············· ' swash pulse width ' measured in microseconds
· word· pwSwashC·············· ' swash pulse width ' measured in microseconds
· word· pwSwashT·············· ' swash pulse width ' measured in microseconds
· long· pwSwashTimeOutA········ ' pw timeout
· long· pwSwashTimeOutB········ ' pw timeout
· long· pwSwashTimeOutC········ ' pw timeout
· long· pwSwashTimeOutT········ ' pw timeout
· long· pwSwashFrameBegin······ ' start time from clock
· long· pwSwashTimeOutFrame········ ' frame rate timer for swash
· byte· servoOutput
· long· stackSX[noparse][[/noparse]STACK_SIZE_SX]······ 'cog stack space··

·
PUB initialize
· ' set directions
· dira[noparse][[/noparse]PIN_SXA] := OUTPUT
· dira[noparse][[/noparse]PIN_SXB] := OUTPUT
· dira[noparse][[/noparse]PIN_SXC] := OUTPUT
· dira[noparse][[/noparse]PIN_SXT] := OUTPUT
· ' set center
· pwSwashA := 1500
· pwSwashB := 1500
· pwSwashC := 1500
· pwSwashT := 1500
· servoOutput := 1
· cognew(driveServos, @stackSX) ' launch a new cog for driver

PUB start
· servoOutput := 1
PUB stop
· servoOutput := 0
PUB setPosA(pw)
· pwSwashA := pw·

PUB driveServos
· repeat
··· if servoOutput == 1
····· ' we try and keep timing close as possible, thus we get time now, then
····· ' turn servos on before calcing timouts
····· ' get current time
····· pwSwashFrameBegin := cnt
····· 'sync - set all outputs high
····· outa[noparse][[/noparse]PIN_SXA] := HIGH
····· outa[noparse][[/noparse]PIN_SXB] := HIGH
····· outa[noparse][[/noparse]PIN_SXC] := HIGH
····· outa[noparse][[/noparse]PIN_SXT] := HIGH
····· ' calc the timeouts
····· pwSwashTimeOutA := pwSwashFrameBegin + (clkfreq / _1uS * pwSwashA)
····· pwSwashTimeOutB := pwSwashFrameBegin + (clkfreq / _1uS * pwSwashB)
····· pwSwashTimeOutC := pwSwashFrameBegin + (clkfreq / _1uS * pwSwashC)
····· pwSwashTimeOutT := pwSwashFrameBegin + (clkfreq / _1uS * pwSwashT)
····· pwSwashTimeOutFrame := pwSwashFrameBegin + (clkfreq / _1uS * FRAME_RATE_SX)
····· ' start frame
····· repeat while ( cnt < pwSwashTimeOutFrame )
······· ' set each servo pw output low as needed
······· if cnt > pwSwashTimeOutA
········· outa[noparse][[/noparse]PIN_SXA] := LOW··
······· if cnt > pwSwashTimeOutB
········· outa[noparse][[/noparse]PIN_SXB] := LOW··
······· if cnt > pwSwashTimeOutC
········· outa[noparse][[/noparse]PIN_SXC] := LOW··
······· if cnt > pwSwashTimeOutC
········· outa[noparse][[/noparse]PIN_SXT] := LOW··
·
··· else
····· ' set low
····· outa[noparse][[/noparse]PIN_SXA] := LOW
····· outa[noparse][[/noparse]PIN_SXB] := LOW
····· outa[noparse][[/noparse]PIN_SXC] := LOW
····· outa[noparse][[/noparse]PIN_SXT] := LOW
----END CODE----

·

Comments

  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-08 06:41
    The problem is probably that your stack isn't big enough. You have only allowed for a stack of 9. Try making it 20 or 30.
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-08 06:53
    Just noticed that this is your first post. Welcome to the propeller forums and have lots of funsmile.gif

    Also, did you know that there are some objects for driving servos? There is one that will do up to 24 without any external hardware and another that will do at least 96 with a few external components.
  • portblockportblock Posts: 9
    edited 2008-03-08 06:57
    Tried changing it to 30, then 40, still didnt work.

    I placed this code in different places in the servoDrive function, to verify it was executing, and it did light up the led, however, doesnt drive the servo, its as iff the pwSwashA variable contains 0

    code placed at various places for debugging:
    dira[noparse][[/noparse]23] := OUTPUT
    outa[noparse][[/noparse]23] := HIGH

    If I comment out the cognew line, and put a line in main like the following, then the servos go right to center and hold.

    PUB main
    servoDriver.initialize
    servoDriver.setPosA(1500)
    servoDriver.start
    servoDrive.driveServos
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-08 07:34
    Is there any reason you declare the stack size in both files?

    Is this for an rc helicopter?
  • portblockportblock Posts: 9
    edited 2008-03-08 07:52
    I just forgot to delete it, I was bouncing back and forth trying to figure out where I should do a cognew, either in main, or in the obj. I realy want it in the obj file.

    helicopter, yes it is, its for a swash setup, and cycler I am working on.
  • portblockportblock Posts: 9
    edited 2008-03-08 07:56
    I missed your welcome post, thank you for the reception. I did notice there is a driver for servos, however, I like to write most of my own code (better understanding) also, I am trying to move some code from a PIC18 to the propeller becouse I need to proccess some items in parallel.

    I thought my little swash setup tool would be a good test project to port so as I can get familiar with the prop. btw, I have had it for about 12hours now, just came ups today (friday)
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-08 08:13
    Do you have a cro or logic analyser so that you can check what is actually happening on the pins? It is strange that your test code works in the new cog and will work if you don't start it in a new cog. Try putting a pwSwashA:=1500 somewhere in the driveServos method. If that doesn't work than we can try using the serial port to do some more serious debuggingsmile.gif
  • deSilvadeSilva Posts: 2,967
    edited 2008-03-08 08:59
    Sorry, I read this just now...
    They told me no no longer answer to simple newbie questions...

    But this goes on for some time now...

    Your issue is
      ' set directions
      dira[noparse][[/noparse]PIN_SXA] := OUTPUT
      dira[noparse][[/noparse]PIN_SXB] := OUTPUT
      dira[noparse][[/noparse]PIN_SXC] := OUTPUT
      dira[noparse][[/noparse]PIN_SXT] := OUTPUT
    


    You set the registers in the wrong COG.

    Note the subroutine you call with COGNEW works in a different hardware context with an independant set ot INA, OUTA, DIRA, CTR... registers. You must just move the above section to "driveServos".
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-08 09:03
    I should have noticed that. I guess that I looked at it for to long and tried to make it too complicated.
  • portblockportblock Posts: 9
    edited 2008-03-08 09:04
    I just dont get this, I tried putting in some assignments like you suggested, as well as hard coding pin numbers instead of using constants, just doest work.

    On a side note, is there no shared memory access between cogs? ie: simple access to a shared variable?

    I need to have one cog monitor a pin, store info in a variable, another cog monitor said variable, and send output to the serial port, and yet, another cog making descisions on the same variable.

    Not just one variable, but 12 word variables.

    Another issue I am having is having these three cogs use one definition file (CON) so I dont have to declare a pin name in 3 seperate files.

    Or should I just simpley put everything in one freakishly long source file, and forgo objects, etc..?
  • deSilvadeSilva Posts: 2,967
    edited 2008-03-08 09:19
    @portblock, sorry I intervened..... I shall draw back at once again..

    (a) Please understand why my correction above is essential!
    This is not a matter of "trial and error"!
    (b) Understand the difference between COG and Object
    (c) Of course there are more issues in your code!
    E.g. You can't do things like:
    if cnt > pwSwashTimeOutC
    


    You have to
    IF CNT-startOfPulse > pulseWidth
    


    (d) To your questions: There is no problem accessing all variables from all COGs, you already do it all the time!
    Just define your constants in a separate file and "OBJ"-it to each file you need them in - no problem!

    Post Edited (deSilva) : 3/8/2008 9:24:57 AM GMT
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-08 09:55
    To use the CON file you will need to include at least one method in it. Just use something like this
    PUB dummy
    



    You are currently sharing the memory for some of the variables such as servoOutput and pwSwashA

    @deSilva, if you have a look at the post times I think he missed our posts and his post refers back to my older one.
    the
    if cnt > pwSwashTimeOutFrame
    


    is right. The startOfPulse (pwSwashFrameBegin) is added in when he sets pwSwashTimeOutFrame here
    pwSwashTimeOutFrame := pwSwashFrameBegin + (clkfreq / _1uS * FRAME_RATE_SX)
    
  • deSilvadeSilva Posts: 2,967
    edited 2008-03-08 10:34
    Steven, you missed the wrap-around aspect.
    Checking CNT can only be performed the way I coded it above: compare to a DIFFERENCE.
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-08 11:00
    I guess that it is the signed numbers that muck it up? I assume that it would work if using unsigned numbers?
  • deSilvadeSilva Posts: 2,967
    edited 2008-03-08 11:08
    No smile.gif
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-08 11:46
    Took a while but I've got it now. I keep going back to basic algebra (ie a+b>c = a>c-b) and keep forgetting that these things always do things slightly differently. Its almost like learning another form of maths.
  • deSilvadeSilva Posts: 2,967
    edited 2008-03-08 11:50
    Luckily I found the sketch I used to explain it with... But algebra is superior by all means!

    Post Edited (deSilva) : 3/8/2008 12:07:29 PM GMT
    668 x 454 - 49K
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-08 12:02
    I guess that if you are going to use algebra than the function for adding two numbers (unsigned) becomes
               / x+y          if x+y<2^32
    f(x,y)=|  
               \ x+y-2^32 otherwise
    
    


    And this would show up the problem. The wraparound can be so useful at times and so annoying at others
  • deSilvadeSilva Posts: 2,967
    edited 2008-03-08 12:05
    It's the "modulus" calculations.....

    It however should be deep in our common indo-european subconscious mind: Shiva and Brahma, cycle upon cycle, creation and destruction, birth and re-birth, zillions of years... Imagine you were a little electron in a Propeller.. this will help smile.gif

    Post Edited (deSilva) : 3/8/2008 12:17:46 PM GMT
  • portblockportblock Posts: 9
    edited 2008-03-10 00:29
    Thank you to both of you, I guess it was my own ego, and experience with programming in several languages and platforms made me think, hey I can just jump into this.

    Yes, I do need to learn more about the language, such as difference from objs, cogs.

    Can either one of you point me to the area to learn these items:

    1: all objects and or cogs, accessing a var defined in main
    2: hub ram? how do I access it (in spin)

    3: main loads 2 different objects:

    OBJ
    ·objA : "object_1"
    ·objB : "object+2"

    now I want objA to call a pub in objB

    becouse I lack the knowlege, I created another cog, to do this, and thus taken up 3 cogs
    ·objB.setPos(objA.getPos)

    Looks like I went from experieced Pic C programmer straight to uber newbie [noparse]:)[/noparse]
    ·
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-10 01:53
    Have you read chapter 3 of the manual? It goes to great length to explain a lot of this stuff.

    quick answers
    1: The only way to do this is by passing pointers.
    2: Everything in spin resides in the hub. All you VAR variables and local variables are in the hub. You can also access areas of the hub directly by using the byte[noparse]/noparse, word[noparse]/noparse and long[noparse]/noparse instructions.
    3: This is can be kind of hard to do if you have VAR blocks in object_1. It is possible but it takes a lot of mucking around with different pointers and dummy objects. However, you can include the object you want to call again (object_1) in the object you want to call from (object_2) doesn't have any VAR blocks.

    For example
    In main you have
    OBJ
     objA:"object_1"
     objB:"object_2"
    


    than in objB you want to do
    PUB callObjA
      objA.doSomething
    


    This won't work but you could include a copy of object_1 in object_2 like this
    OBJ
     objA:"object_1"
    PUB callObjA
     objA.doSomething
    


    Now, if you have anything in a VAR block than you will get two copies of the VAR block. One for main and one for object_2. However, remember that anything in a DAT block gets shared by every instance of the object. So, if all your variables are in DAT blocks and you don't have any VAR blocks this will work fine and you will get the desired effect.

    Hope that this all makes sense. If it doesn't than I will try to explain it better smile.gif
  • portblockportblock Posts: 9
    edited 2008-03-10 01:59
    I will re-read that chapter when I get home tonight. I read through the PDF before I purchased the eval board, then I tried to jump in.

    Ok, I am understanding what you are saying. One question, and you can simple point me in the direction and I will go try and read/understand it.

    Am I correct in understanding that an item in the DAT block is a item in memory, that can be reard/written to from any object, any cog? And how do I reference a DAT item in main from a cog started in object_2?
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-10 02:08
    Everything in DAT blocks are in the HUB so all objects can get to them. However, other objects don't know where things in the DAT block are so you need to pass a pointer back to main or whatever else wants to use the memory. So you need something like this in object_2
    DAT
    someVariable long 123456
    
    PUB getSomeVariableAddr
      return @someVariable
    


    Than in main something like this
    PUB doSomething
      long[noparse][[/noparse]objB.getSomeVariableAddr]:=23456
    
    


    Of course that is inefficient and it would be better to store it in a variable like this
    VAR
      long someVariablePtr
    
    PUB doSomething|i
      someVariablePtr:=objB.getSomeVariableAddr
      repeat i from 0 to 40
        long[noparse][[/noparse]someVariablePtr]:=i
    
  • portblockportblock Posts: 9
    edited 2008-03-10 02:12
    ok, I am with you thus far. I will give things a shot when I get home.
Sign In or Register to comment.