PASM and cogs
blake_macho
Posts: 5
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.
#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[noparse][[/noparse]LASER]~~ outa[noparse][[/noparse]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
Comments
This is adding the value of register 0 to counterX, not "0". Change it to:
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.
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.
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.
Post Edited (blake_macho) : 3/17/2009 5:47:16 PM GMT
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
Thanks for your help.
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
Thanks for the help.
-Blake
Post Edited (blake_macho) : 3/23/2009 5:26:29 AM GMT
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://forums.parallax.com/showthread.php?p=788230