stopping/starting multiple cogs
in Propeller 1
I'm having a problem with identifying cogs to be able to start and stop them. I've seen the examples in the pe kit and prop manual. I tried the example in the prop manual , but the compiler said I need a unique variable when I used cogid instead of cog1 (or 2). Also with the prop manual example i'm not sure how to control multiple cogs. The code will compile the way I have it below, but does not work.
var long servostack [150]
long servo2stack [150]
long cog1
long cog2
pub go
halt:=1 'input changes state of halt and is intended to stop a cog
cog1:=cognew(servo2,@servo2stack)
cog2:=cognew(servo,@servostack)
.....other unrelated code here.....
repeat
phsa:= -thar
tt+= tc
waitcnt(tt)
if halt==0
cogstop( cog1) (cogstop for cog2 is the same as this group of code)

Comments
Crappy forum software, killed fixing old posts, attachments, and kills old urls, and old youtube video urls.
DAMN the torpedos, full steam ahead into lame forum software!
And then it was UNattached because it had issues, but this post remains, forever! HUZZZAH!
The reason for the + 1 is that cognew returns -1 if the cog didn't start, or 0 to 7 if it did. By adding one we promote the ID to a value that can be used in a true-false expression (i.e., you'll end up with a value between 1..8 if the cog started). Just remember to account for this when stopping said cog.
if (cogX) cogstop(cogX - 1) cogX := 0And, FWIW, you're consuming WAY too much RAM (4K total) for stack space. With simple routines like that you could get away with far fewer longs. For example, here's an actual bit of code from the EFX-TEK HC-8+ controller. This embedded object runs in its own cog providing a 1ms clock, maitaining a Red/Green LED, and reading 16 inputs via two shift registers. Note the size of the stack = 32 longs.
con { ----------------------------- } { B A C K G R O U N D C O G } { - global milliseconds } { - R/G LED } { - TTL/DMX inputs scanning } { ----------------------------- } var long bcog ' background cog # long bcstack[32] ' stack for background cog long millis ' global milliseconds register pri background | t ' launch with cognew() io.low(R_LED) ' setup R/G LED pins io.low(G_LED) io.high(LD_165) ' setup x165 io pins io.low(CLK_165) io.input(DO_165) millis := 0 t := cnt ' sync loop timer repeat waitcnt(t += MS_001) ' run loop every millisecond ++millis refresh_rg_led ' update the R/G LED scan_ttl_ins ' re-scan TTL & DMX inputs var long rgycolor[2] ' led phase colors long rgytime[2] ' led phase timing (ms) long rgphase ' current phase (red or green chip) long phasetimer ' time in phase long rgtimer ' timer for rg process pri refresh_rg_led ' call only from support() if (++phasetimer => rgytime[rgphase]) ' done with this phase? phasetimer := 0 ' yes, reset timer rgphase := 1 - rgphase ' and invert phase if (++rgtimer == 16) rgtimer := 0 case rgycolor[rgphase] ' set led to color for phase OFF: outa[R_LED..G_LED] := %00 GRN: outa[R_LED..G_LED] := %01 RED: outa[R_LED..G_LED] := %10 YEL: if (rgtimer < 2) outa[R_LED..G_LED] := %10 ' 2 red else outa[R_LED..G_LED] := %01 ' 14 green var long ttlpins long dmxaddr pri scan_ttl_ins : tempin '' Scan TTL and DMX address inputs outa[LD_165] := 0 ' blip Shift/Load line outa[LD_165] := 1 tempin := ina[DMX_A8] ' bit16 ' unrolled for best speed tempin := (tempin << 1) | ina[DO_165] ' bit15 outa[CLK_165] := 1 ' blip clock outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] ' bit7 outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] outa[CLK_165] := 1 outa[CLK_165] := 0 tempin := (tempin << 1) | ina[DO_165] ' bit0 ttlpins := tempin.byte[0] ' update global vars dmxaddr := tempin >> 8I start that cog from my setup() method with this line of codeI have not spend much time with fine tuning that yet. For the cog stop/start methods I was using example code posted earlier, but I think i'm doing something wrong. It will start the cog and i'm confident it's ending up at the halt method at the appropriate time, but it's not stopping the cogs. I'm all set now, but would like to know what I was doing wrong.
pub go halt cogon[0] := (cogs[0] := cognew(servo, @pile[100]) > 0) '1 cog used. cogon[1] := (cogs[1] := cognew(servo2, @pile[200]) > 0) '1 cog used. pub halt if cogon[0]~ ' if object running, mark stopped cogstop(cogs[0]) if cogon[1]~ ' if object running, mark stopped cogstop(cogs[1])repeat waitcnt(0)Since you don't have this at the end of the go method, you have a return-to-nowhere situation.I think thats the same problem I have with it, the stop function dosen't stop the cogs, but i never used it.. I just used the code to start cogs (and comment out ones i didn't want started)
It seems Jon is saying the code is more complicated than it needs to be, perhaps so, I don't understand it myself, i should probably take it and put some debug code into it and see what the cog variables are doing...
Thats interesting that Jon mentions keeping the main cog running... i stated that once in a thread but it was missed.. and my other bad points were focused on. meh...
I also show I did this in the code above.
I'll dig into the code i posted and figure it out soon. That will be my project tonight...
I didn't know you could do that.. Since (from what i understand) there is a minimum limit to the waitcnt command.
I think that needs to be fixed so the cogs get a unique id.
I am looking at the propeller manual and thats where the above code i originally attached, came from.
Propeller manual bottom of page 83.
This "UN-necessarily" complicated code is in the manual and im still looking it over to fully understand it, so i don't know why the manual uses "UN-necessarily" complicated code.
But I see some differences... from what i posted... time to do more testing.
VAR byte Cog 'Used to store ID of newly started cog PUB Start(Pos) : Pass 'Start a new cog to run Update with Pos, 'return TRUE if successful Pass := (Cog := cognew(@Update, Pos) + 1) > 0 PUB Stop 'Stop the cog we started earlier, if any. if Cog cogstop(Cog~ - 1)The @ symbol in front of the Function is not correct, it should be in front of the variable stack.
I think its a typo and meant to read
So,.... After fixing a bug in the manual, I also fixed my bug, both fixed, due to understanding the manual's examples.
My code was changed to match the manual, except for its own address symbol bug...
'' ================================================================================================= ' File...... CogManagement.spin ' Purpose... CogManagement ' Author.... Clock Loop @ parallax forums '' ================================================================================================= CON _clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz _xinfreq = 5_000_000 VAR long cogon[8], cog[8], pile[1000] ' cog management OBJ PUB Start 'Remember this is the first cog. 1 cog used. Stop 'Make sure all cogs are OFF! cogon[0] := ((cog[0] := cognew(Routine1, @pile[100]) + 1) > 0) '1 cog used. cogon[1] := ((cog[1] := cognew(Routine2, @pile[200]) + 1) > 0) '1 cog used. cogon[2] := ((cog[2] := cognew(Routine3, @pile[300]) + 1) > 0) '1 cog used. cogon[3] := ((cog[3] := cognew(Routine4, @pile[400]) + 1) > 0) '1 cog used. cogon[4] := ((cog[4] := cognew(Routine5, @pile[500]) + 1) > 0) '1 cog used. cogon[5] := ((cog[5] := cognew(Routine6, @pile[600]) + 1) > 0) '1 cog used. cogon[6] := ((cog[6] := cognew(Routine7, @pile[700]) + 1) > 0) '1 cog used. 'cogon[7] := ((cog[7] := cognew(Routine8, @pile[800]) + 1) > 0) 'If I launch this cog, won't it fail? since the cog launching this cog, is the last one, so you must run it below? Or will it just use the last cog and not run any code below this line? Routine8 ' This keeps the main cog running. 'Last cog re-used in this Routine. PUB Routine1 Repeat ' This keeps the cog running. waitcnt(100_000 + cnt) 'cpu wait PUB Routine2 Repeat ' This keeps the cog running. waitcnt(100_000 + cnt) 'cpu wait PUB Routine3 Repeat ' This keeps the cog running. waitcnt(100_000 + cnt) 'cpu wait PUB Routine4 Repeat ' This keeps the cog running. waitcnt(100_000 + cnt) 'cpu wait PUB Routine5 Repeat ' This keeps the cog running. waitcnt(100_000 + cnt) 'cpu wait PUB Routine6 Repeat ' This keeps the cog running. waitcnt(100_000 + cnt) 'cpu wait PUB Routine7 Repeat ' This keeps the cog running. waitcnt(100_000 + cnt) 'cpu wait PUB Routine8 Repeat ' This keeps the cog running. waitcnt(100_000 + cnt) 'cpu wait PUB stop if cogon[0] ' if object running, mark stopped cogstop(cog[0]~ - 1) if cogon[1] ' if object running, mark stopped cogstop(cog[1]~ - 1) if cogon[2] ' if object running, mark stopped cogstop(cog[2]~ - 1) if cogon[3] ' if object running, mark stopped cogstop(cog[3]~ - 1) if cogon[4] ' if object running, mark stopped cogstop(cog[4]~ - 1) if cogon[5] ' if object running, mark stopped cogstop(cog[5]~ - 1) if cogon[6] ' if object running, mark stopped cogstop(cog[6]~ - 1) if cogon[7] ' if object running, mark stopped cogstop(cog[7]~ - 1) Dat {{ Terms of Use: MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. }}Get putty.
Upload this code.
And connect to your serial port with putty.
The count will stop every 10 seconds and wait 10 seconds and start the count again. It strays a bit due to starting and stopping the cog without consideration for the timing; when its best to stop the cog, in relation to the variable update, and the display painting.
But the start and stop cog code, works now.
'' ================================================================================================= ' File...... CogManagement.spin ' Purpose... CogManagement ' Author.... Clock Loop @ parallax forums '' ================================================================================================= CON _CLKMODE = XTAL1 + PLL16X _XINFREQ = 5_000_000 '_XINFREQ = 6_250_000 ' I do my code testing on a propscope. Tx = 30 'serial Rx = 31 'serial 'EepromScl = 28 'eeprom. 'EepromSda = 29 'eeprom. VAR long cogon[8], cog[8], pile[1000] ' cog management OBJ Term : "FullDuplexSerialPlus" PUB Start 'Remember this is the first cog. 1 cog used. Stop Term.start(Rx, Tx, %0000, 115_200) '1cog start telnet terminal waitcnt(80_000_000 + cnt) cogon[0] := ((cog[0] := cognew(Routine0, @pile[100]) + 1) > 0) '1 cog used. cogon[1] := ((cog[1] := cognew(Routine1, @pile[200]) + 1) > 0) '1 cog used. cogon[2] := ((cog[2] := cognew(Routine2, @pile[300]) + 1) > 0) '1 cog used. cogon[3] := ((cog[3] := cognew(Routine3, @pile[400]) + 1) > 0) '1 cog used. cogon[4] := ((cog[4] := cognew(Routine4, @pile[500]) + 1) > 0) '1 cog used. 'cogon[5] := ((cog[5] := cognew(Routine5, @pile[600]) + 1) > 0) '1 cog used. 'Can't use this the serial terminal uses a cog. 'cogon[6] := ((cog[6] := cognew(Routine6, @pile[700]) + 1) > 0) '1 cog used. 'Routine0 controls this cog for this test. 'cogon[7] := ((cog[7] := cognew(Routine7, @pile[800]) + 1) > 0) 'If I launch this cog, won't it fail? since the cog launching this cog, is the last one, so you must run it below? Or will it just use the last cog and not run any code below this line? Repeat Routine7 ' This keeps the main cog running. 'Last cog re-used in this Routine. PUB Routine0 Repeat ' This keeps the cog running. cogon[6] := ((cog[6] := cognew(Routine6, @pile[700]) + 1) > 0) '1 cog used. Repeat 10 waitcnt(80_000_000 + cnt) if cogon[6] ' if object running, mark stopped cogstop(cog[6]~ -1) Repeat 10 waitcnt(80_000_000 + cnt) PUB Routine1 Repeat ' This keeps the cog running. waitcnt(100_000 + cnt) 'cpu wait PUB Routine2 Repeat ' This keeps the cog running. waitcnt(100_000 + cnt) 'cpu wait PUB Routine3 Repeat ' This keeps the cog running. waitcnt(100_000 + cnt) 'cpu wait PUB Routine4 Repeat ' This keeps the cog running. waitcnt(100_000 + cnt) 'cpu wait PUB Routine5 Repeat ' This keeps the cog running. waitcnt(100_000 + cnt) 'cpu wait PUB Routine6 Repeat ClockCount PUB Routine7 | old waitcnt(50_000 + cnt) If Secs <> old old := Secs PaintScreen Pub ClockCount waitcnt(80_000_000 + cnt) 'wait 1 second If Secs == 59 Secs := 0 Else Secs := Secs + 1 Pub PaintScreen If Secs == 0 term.str(string(27)) 'Set command mode term.str(string("[2J")) 'clear screen term.str(string(27)) 'Set command mode term.str(string("[2;3f")) 'position term.str(string(27)) 'Set command mode term.str(string("[35m")) 'Purple color text term.str(string(27)) 'Set command mode term.str(string("[1m")) 'Turn bold mode on term.str(string(27)) 'Set command mode term.str(string("#3")) 'Double-height letters, top half term.str(string("Cog Management! ")) term.str(string(27)) 'Set command mode term.str(string("[3;3f")) 'position term.str(string(27)) 'Set command mode term.str(string("#4")) 'Double-height letters, bottom half term.str(string("Cog Management! ")) term.str(string(27)) 'Set command mode term.str(string("[1;1f")) 'Set Position term.str(string(27)) 'Set command mode term.str(string("[0m")) 'Turn off character attributes '--------------AMBIENT------------------ 'term.str(string(27)) 'Set command mode 'term.str(string("[2J")) 'clear screen 'term.str(string(27)) 'Set command mode 'term.str(string("[0m")) 'Turn off character attributes 'term.str(string("[1m")) 'Turn bold mode on 'term.str(string("[2m")) 'Turn low intensity mode on 'term.str(string("[4m")) 'Turn underline mode on 'term.str(string("[5m")) 'Turn blinking mode on 'term.str(string("[7m")) 'Turn reverse video on 'term.str(string("[8m")) 'Turn invisible text mode on 'term.str(string("#3")) 'Double-height letters, top half 'term.str(string("#4")) 'Double-height letters, bottom half 'term.str(string("#5")) 'Single width, single height letters 'term.str(string("#6")) 'Double width, single height letters 'term.str(string("[30m")) 'Black color text 'term.str(string("[31m")) 'Red color text 'term.str(string("[32m")) 'Lime color text 'term.str(string("[33m")) 'Yellow color text 'term.str(string("[34m")) 'Blue color text 'term.str(string("[35m")) 'Purple color text 'term.str(string("[36m")) 'SkyBlue color text 'term.str(string("[37m")) 'White color text term.str(string(27)) 'Set command mode term.str(string("[1m")) 'Turn bold mode on term.str(string(27)) 'Set command mode term.str(string("[5;5f")) 'Set Position term.str(string(27)) 'Set command mode term.str(string("[34m")) 'Blue color text term.str(string("Ticker : ")) term.str(string(27)) 'Set command mode term.str(string("[33m")) 'Yellow color text term.dec(Secs) term.str(string(27)) 'Set command mode term.str(string("[1;1f")) 'Set Position PUB stop if cogon[0] ' if object running, mark stopped cogstop(cog[0]~ - 1) if cogon[1] ' if object running, mark stopped cogstop(cog[1]~ - 1) if cogon[2] ' if object running, mark stopped cogstop(cog[2]~ - 1) if cogon[3] ' if object running, mark stopped cogstop(cog[3]~ - 1) if cogon[4] ' if object running, mark stopped cogstop(cog[4]~ - 1) if cogon[5] ' if object running, mark stopped cogstop(cog[5]~ - 1) if cogon[6] ' if object running, mark stopped cogstop(cog[6]~ - 1) if cogon[7] ' if object running, mark stopped cogstop(cog[7]~ - 1) DAT Secs LONG 0 Dat {{ Terms of Use: MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. }}Waitcnt(0) is unnecessary.
However, the benefit of using waitcnt(0) is that it will put the cog to go into low power mode for ~54 seconds per loop of the 32 bit counter.
The example is correct, it just doesn't have the correct reference. The cognew function has two syntax, one to start Spin functions and another to start PASM code, what you see in that example is the latter. Look at page 79-81 where both syntax are explained.
Your code needs to start a Spin function so your fix is correct because in that case the second argument is the pointer to the Spin stack.
The way I understood the manual...
The prop assembly has a different section.
Page 83 is for SPIN
Page 286 is for pasm.
But the cogstop for pasm says nothing about that, nor does the cogstop for spin mention how the example code is for pasm. (and why is the spin section using a pasm example) LOL
From what I can tell actually pasm and spin syntax are all mixed up in the manual, and not seperate.
THAT IS EXCELLENT, and not confusing at all.
(and i must page back to an area for cognew, to find info on cogstop???)
THAT IS EVEN MORE EXCELLENT!
Im closing PropellerTool, and gonna watch a movie...
Since chaos seems the theme for me tonight.. HardCore Henry should be an excellent movie right now.
Page 286 is to start cogs from PASM while page 83 is to start cogs from SPIN and from Spin you have two different syntax for cognew!
And My page 286 has CogStop for pasm. (but probably not enough examples)
What version of the manual are you using? 1.2 is the one on the parallax website; the one i have.
https://www.parallax.com/downloads/propeller-manual
Page 286 of PropellerManual version 1.2.
Should read
again.... Im closing PropellerTool, and gonna watch a movie... Since chaos seems the theme for me tonight.. HardCore Henry should be an excellent movie right now.
I suppose i could use my theme of the evening to find all the chaos around my world... but that sucks... im just gonna waste it by watching chaos.
By the way, you don't need to define separate method for each cog; the beauty of Spin cogs is that you can run the same cog in multiple interpreter cogs (this is why each needs its own stack). For example:
pub blinker(pin, onms, offms) : t onms *= clkfreq / 1000 ' convert ms to ticks offms *= clkfreq / 1000 dira[pin] := 1 ' make pin an output t := cnt ' sync timing repeat outa[pin] := 1 waitcnt(t += onms) outa[pin] := 0 waitcnt(t += offms)You could blink the LEDs on a PAB at different rates like this