PDA

View Full Version : PASM and cogs



blake_macho
03-17-2009, 03:06 PM
I am clearly a newbie here, and I realize that this code sucks in a variety of ways (e.g. redundancy between the x and y servo routines). Please look past that as I try to ask my first question, then help me with that as you address my second question =).

#1. Whichever repeat 10 loop I list first in the code is the only one that works, the second one does nothing. They both work fine independently. Order of the cognew functions has no impact. What am I missing?
#2. Obviously, I ideally want to pass in two parameters to a single 'servo' PASM block. The first being a servo pin, the second being a position. How do I go about that? (I believe I am to pass a memory address and then do some fancy PASM to look it up and pull out the necessary values). I am a total ASM and PASM noob, sadly. So I have no clue on how to go about that. Any tutorials/links/example code?

Thanks for helping out. Much appreciated.



CON
_xinfreq=5_000_000
_clkmode=xtal1+pll16x
LASER = 26

VAR
long x_position
long y_position

PUB Main
cognew(@y_servo,@y_position)
cognew(@x_servo,@x_position)

laser_toggle(1)

'The new cog that is started above continuously reads the "position" variable as it's changed by the example Spin code below
repeat 10
y_position:=70_000
waitcnt(clkfreq+cnt)
y_position:=105_000
waitcnt(clkfreq+cnt)

repeat 10
x_position:=96_000 'Start sending 1ms servo signal high pulses (80_000 * 1/(80MHz clock freq) = 1ms)
waitcnt(clkfreq+cnt) 'Wait for 1 second (1ms high pulses continue to be generated by the other cog)
x_position:=168_000 'Start sending 1.375ms servo signal high pulses (Center position)
waitcnt(clkfreq+cnt) 'Wait for 1 second (1.5ms high pulses continue to be generated by the other cog)


PUB laser_toggle(on)
dira[LASER]~~
outa[LASER] := on
DAT
'The assembly program below runs on a parallel cog and checks the value of the "position" variable in the main Hub RAM (which
' other cogs can change at any time). It then outputs a servo high pulse for the "position" number of system clock ticks and
' sends a 10ms low part of the pulse. It repeats this signal continuously and changes the width of the high pulse as the
' "position" variable is changed by other cogs.

org 'Assembles the next command to the first cell (cell 0) in the new cog's RAM
x_servo mov dira,XPin 'Set the direction of the "ServoPin" to be an output (and all others to be inputs)

LoopX rdlong HighTimeX,par 'Read the "position" variable (at "par") from Main RAM and store it as "HighTime"
mov counterX,cnt 'Store the current system clock count in the "counter" cell's address
mov outa,AllOnX 'Set all pins on this cog high (really only sets ServoPin high b/c rest are inputs)
add counterX,HighTimeX 'Add "HighTime" value to "counter" value
waitcnt counterX,LowTimeX 'Wait until "cnt" matches "counter" then add a 10ms delay to "counter" value
mov outa,#0 'Set all pins on this cog low (really only sets ServoPin low b/c rest are inputs)
waitcnt counterX,0 'Wait until cnt matches counter (adds 0 to "counter" afterwards)
jmp #LoopX 'Jump back up to the cell labled "Loop"

'Constants and Variables:
XPin long |< 5 '<------- This sets the pin that outputs the servo signal (which is sent to the white wire
' on most servomotors). Here, this "7" indicates Pin 7. Simply change the "7"
' to another number to specify another pin (0-31).

AllOnX long $FFFFFFFF 'This will be used to set all of the pins high (this number is 32 ones in binary)
LowTimeX long 1_600_000 'This works out to be a 10ms pause time with an 80MHz system clock. If the
' servo behaves erratically, this value can be changed to 1_600_000 (20ms pause)
counterX res 'Reserve one long of cog RAM for this "counter" variable
HighTimeX res 'Reserve one long of cog RAM for this "HighTime" variable
fit 'Makes sure the preceding code fits within cells 0-495 of the cog's RAM
DAT
org 'Assembles the next command to the first cell (cell 0) in the new cog's RAM
y_servo mov dira,YPin 'Set the direction of the "ServoPin" to be an output (and all others to be inputs)

LoopY rdlong HighTimeY,par 'Read the "position" variable (at "par") from Main RAM and store it as "HighTime"
mov counterY,cnt 'Store the current system clock count in the "counter" cell's address
mov outa,AllOnY 'Set all pins on this cog high (really only sets ServoPin high b/c rest are inputs)
add counterY,HighTimeY 'Add "HighTime" value to "counter" value
waitcnt counterY,LowTimeY 'Wait until "cnt" matches "counter" then add a 10ms delay to "counter" value
mov outa,#0 'Set all pins on this cog low (really only sets ServoPin low b/c rest are inputs)
waitcnt counterY,0 'Wait until cnt matches counter (adds 0 to "counter" afterwards)
jmp #LoopY 'Jump back up to the cell labled "Loop"

'Constants and Variables:
YPin long |< 0 '<------- This sets the pin that outputs the servo signal (which is sent to the white wire
' on most servomotors). Here, this "7" indicates Pin 7. Simply change the "7"
' to another number to specify another pin (0-31).
' servo behaves erratically, this value can be changed to 1_600_000 (20ms pause)
AllOnY long $FFFFFFFF 'This will be used to set all of the pins high (this number is 32 ones in binary)
LowTimeY long 1_600_000 'This works out to be a 10ms pause time with an 80MHz system clock. If the
' servo behaves erratically, this value can be changed to 1_600_000 (20ms pause)

counterY res 'Reserve one long of cog RAM for this "counter" variable
HighTimeY res 'Reserve one long of cog RAM for this "HighTime" variable
fit 'Makes sure the preceding code fits within cells 0-495 of the cog's RAM

Jetfire
03-18-2009, 01:29 AM
I'm not sure what is causing your first problem. One thing that I noticed is that the second waitcnt is:


waitcnt counterX,0


This is adding the value of register 0 to counterX, not "0". Change it to:


waitcnt counterX,#0



As for choosing the pin, you have everything in place. What you want to do is change XPin in Spin before you start the cog.


XPin := |< 3
cognew(@x_servo,@x_position)


This change the value of XPin in the hub, when the cog starts this is brought into cog memory.

You should also then be able to start two cogs using the same assembly by choosing the pin before you start them and giving them different parameter variables.


XPin := |< 3
cognew(@x_servo,@x_position)
XPin := |< 5
cognew(@x_servo,@y_position)

blake_macho
03-18-2009, 01:41 AM
JetFire, thanks for the info. I fixed the 0 to #0 issue (though it seemed to operate identically either way). And I had no idea I could change variables via Spin then call the PASM via cogs. So that helped as well.

Sadly my original problem still exists, and I'm not sure why. Was wondering if anyone had any thoughts? The repeat 10 loop that is run first in the code works as expected, the second one doesn't. It basically does nothing. If you re-order the repeat 10 loops the other will work. I must be missing something just I'm not sure what. Also appears that the order of the cognew functions does not matter as well. Here is the updated code.




CON
_xinfreq=5_000_000
_clkmode=xtal1+pll16x 'The system clock is set at 80MHz (this is recommended for optimal resolution)
LASER = 26

VAR
long x_position 'The assembly program will read this variable from the main Hub RAM to determine
' the servo signal's high pulse duration
long y_position

PUB Main
Pin := |< 0
cognew(@servo,@y_position)
Pin := |< 5
cognew(@servo,@x_position)
laser_toggle(1)

'The new cog that is started above continuously reads the "position" variable as it's changed by the example Spin code below

repeat 10
x_position:=96_000 'Start sending 1ms servo signal high pulses (80_000 * 1/(80MHz clock freq) = 1ms)
waitcnt(clkfreq+cnt) 'Wait for 1 second (1ms high pulses continue to be generated by the other cog)
x_position:=168_000 'Start sending 1.375ms servo signal high pulses (Center position)
waitcnt(clkfreq+cnt) 'Wait for 1 second (1.5ms high pulses continue to be generated by the other cog)

repeat 10
y_position:=70_000
waitcnt(clkfreq+cnt)
y_position:=105_000
waitcnt(clkfreq+cnt)


PUB laser_toggle(on)
dira[LASER]~~
outa[LASER] := on

DAT
org 'Assembles the next command to the first cell (cell 0) in the new cog's RAM
servo mov dira,Pin 'Set the direction of the "ServoPin" to be an output (and all others to be inputs)

Loop rdlong HighTime,par 'Read the "position" variable (at "par") from Main RAM and store it as "HighTime"
mov counter,cnt 'Store the current system clock count in the "counter" cell's address
mov outa,AllOn 'Set all pins on this cog high (really only sets ServoPin high b/c rest are inputs)
add counter,HighTime 'Add "HighTime" value to "counter" value
waitcnt counter,LowTime 'Wait until "cnt" matches "counter" then add a 10ms delay to "counter" value
mov outa,#0 'Set all pins on this cog low (really only sets ServoPin low b/c rest are inputs)
waitcnt counter,#0 'Wait until cnt matches counter (adds 0 to "counter" afterwards)
jmp #Loop 'Jump back up to the cell labled "Loop"

'Constants and Variables:
Pin long |< 5 '<------- This sets the pin that outputs the servo signal (which is sent to the white wire
' on most servomotors). Here, this "7" indicates Pin 7. Simply change the "7"
' to another number to specify another pin (0-31).

AllOn long $FFFFFFFF 'This will be used to set all of the pins high (this number is 32 ones in binary)
LowTime long 1_600_000 'This works out to be a 10ms pause time with an 80MHz system clock. If the
' servo behaves erratically, this value can be changed to 1_600_000 (20ms pause)
counter res 'Reserve one long of cog RAM for this "counter" variable
HighTime res 'Reserve one long of cog RAM for this "HighTime" variable
fit 'Makes sure the preceding code fits within cells 0-495 of the cog's RAM

{Copyright (c) 2008 Gavin Garner, University of Virginia}

Post Edited (blake_macho) : 3/17/2009 5:47:16 PM GMT

TreeLab
03-18-2009, 01:59 AM
Changing the 0 to #0 has no effect because at the top of the loop you explicitly set the value of counter to cnt, so it does not matter what was added at the end of the loop. #0 is better practice though because the value is well defined, where as register 0 may not be

When you say it 'does nothing', does this mean that it does not execute, or the motors do not twitch, or ... ? If you do debug printing on each iteration of each repeat 10 loop, does it appear like the spin component is running as expected?

My ignorance here : is there a limit on how many res can be listed at the end of PASM code?

Cheers!
Paul Rowntree

Post Edited (TreeLab) : 3/17/2009 6:06:11 PM GMT

blake_macho
03-18-2009, 03:21 AM
Yes, when I say it does nothing I mean the motor does not twitch (e.g. the code running in the cog is not working correctly). The Spin code is working as expected for both loops. This is really weird and frustrating. =P

Thanks for your help.

kwinn
03-18-2009, 05:41 AM
When you swap the position of the "repeat 10" blocks does it change the servo that responds to the command? Does the X block move the X servo when it is first, and the Y block move the Y servo or does one servo move for both blocks?

I am wondering if the Pin definition below is overriding the pin assignment before the cognew statement.

'Constants and Variables:
Pin long |< 5 '<------- This sets the pin that outputs the servo signal (which is sent to the white wire

blake_macho
03-23-2009, 01:21 PM
This was very frustrating! I resolved this by setting both x_position and y_position before the cognew commands. Then everything worked as expected.

Thanks for the help.

-Blake

Post Edited (blake_macho) : 3/23/2009 5:26:29 AM GMT

jazzed
03-23-2009, 02:15 PM
I bet without initializing the VAR positions, that you would eventually have movement if you wait long enough.

Here's why:
If VAR variable contents pre-initialized to 0 as seems to be the case by looking at the F8 output, you ended up
getting a very long wait value for your pulse since the value you ended up waiting for with waitcnt had already
passed by the time the instruction executed. If you use small values say <= 12 (3 instructions * 4 ticks per
instruction) or very large values, you would have the same result.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve


Propalyzer: Propeller PC Logic Analyzer (http://www.brouhaha.com/~sdenson/Propalyzer)
http://forums.parallax.com/showthread.php?p=788230 (http://forums.parallax.com/showthread.php?p=788230)