Cog doesnt run
portblock
Posts: 9
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----
·
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
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.
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
Is this for an rc helicopter?
helicopter, yes it is, its for a swash setup, and cycler I am working on.
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)
They told me no no longer answer to simple newbie questions...
But this goes on for some time now...
Your issue is
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".
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..?
(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:
You have to
(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
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
is right. The startOfPulse (pwSwashFrameBegin) is added in when he sets pwSwashTimeOutFrame here
Checking CNT can only be performed the way I coded it above: compare to a DIFFERENCE.
Post Edited (deSilva) : 3/8/2008 12:07:29 PM GMT
And this would show up the problem. The wraparound can be so useful at times and so annoying at others
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
Post Edited (deSilva) : 3/8/2008 12:17:46 PM GMT
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]
·
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
than in objB you want to do
This won't work but you could include a copy of object_1 in object_2 like this
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
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?
Than in main something like this
Of course that is inefficient and it would be better to store it in a variable like this