Shop OBEX P1 Docs P2 Docs Learn Events
getting hung at cog stop — Parallax Forums

getting hung at cog stop

Jack3Jack3 Posts: 55
edited 2014-02-06 18:42 in Propeller 1
Where have I goofed? Stand by for clearly stated post

Comments

  • JonnyMacJonnyMac Posts: 9,107
    edited 2014-02-05 13:10
    You'll often find it easier to get assistance when others understand the outcome you desire. You have code that doesn't work. Okay. Explain (in English, not non-working code) what you would love to have happen if it did work. An outside point-of-view -- once fully understanding your desired outcome -- may show you things you hadn't considered that simplifies.

    Initially, you seem to be stacking a lot of things that don't need to be.
  • Jack3Jack3 Posts: 55
    edited 2014-02-05 14:15
    I removed documentation to size it down....Not thinking again, head is spinning....LOL

    I want the top object to call the "BlinkMethod01", passing it the first two pins in the array of pins.

    Expected is to call the LED1 method, which checks and stops cog if in use then returns and starts a cog passing the pin values and runs a pair of led's on the pins. Cleaning out garbage code, and now I get a return from the calling function, but no lights work if I call from the top object. BUT if I add the necessary code to make the BlinkMethod01 work stand alone, the LED's work the way I expected and desire, with that cog.

    If I run serial terminal from the BlinkMethod01 proper, not thru the top object, I can see all my debug code(cleaned out for here) and the led's work

    So this is the TopLED ...top obj
    {{TopLed.spin
     test file for making the LED prog work right
     }}
     
    OBJ
      Flash1 : "BlinkMethod01"  ''LED1 is call
      pst     : "Parallax Serial Terminal"
    
    CON
      _xinfreq = 5000000
      _clkmode = xtal1+PLL16x
    
    VAR
      byte pin[15] {1,2,3,4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
      ''array of the pin nums, leaving 0 for no special reason
    
    PUB Main
        Flash1.LED1(pin[1],pin[2])          ''pins 1&2 sent to method BlinkMethod01, expecting 'success' back
    
    .
    Then this is the BlinkMethod01
    {{  BlinkMethod01
    Purpose to blink LED
     }}
    
    OBJ
    
      pst     : "Parallax Serial Terminal"
     
    VAR
      long stack[20]
      byte cog
     
    PUB LED1 (pin1,pin2): success
      Stop  '' stop cog if already in use
      success :=(cog:=cognew(BlinkMethod01(pin1, pin2), @stack)+1)
    
    PUB Stop
        if cog                      '' it has a value stop it.
            cogstop(cog~ -1)
    
    PRI BlinkMethod01(pin1, pin2) |  rate
      rate:= clkfreq
      dira[pin1]~~
      outa[pin1]:=1
      dira[pin2]~~
      outa[pin2]:=1 {{this sets up the double flash sequence
                      Which changes with the 7404 setup must be correct
                      or it will not work right.}}
      repeat 
        waitcnt(rate/6+cnt)
        !outa[pin1]
        !outa[pin2]            ''for ref, on
        waitcnt(rate/6+cnt)
        !outa[pin1]
        !outa[pin2]               ''for ref, off
          waitcnt(rate/6+cnt)
        !outa[pin1]
        !outa[pin2]             ''for ref, on
        waitcnt(rate/6+cnt)
        !outa[pin1]
        !outa[pin2]              ''for ref, off
        waitcnt(rate/2+cnt)       ''longer wait
    
    

    I am expecting the top object to call a method that starts a cog that runs a method that flashes 2 LED's, for 2 fast short flashes with a longer pause for effect, and for this to continue running while the top object goes and calls another cog and starts another LED process that is totally different.

    I hope this is more clear. My family always gets on my case because they dont' understand what I am trying to say, so please ask if I confused. Thanks for the time you may take on this.
  • JonnyMacJonnyMac Posts: 9,107
    edited 2014-02-05 14:22
    Writing a specification that others will understand is the hardest part -- I just got of the phone with a client.

    BTW... you understand that you cannot pre-initialize a VAR array, correct? Change that to a DAT array if you want to specify the pins in the array without having to do that when the program is running
    dat
    
      Pinz          byte    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
    


    The cool thing is that the array in pre-initialized but still malleable.

    Stepping back a bit, your original code caused me to think you want an object that can flash one or two LEDs. Here's a very simple approach (that works, I tested it) that may give you something to think about. The object object has public methods for each flash type, and corresponding private methods that are launched into a separate cog so that they can run in the background. Calling a new method kills the previous. Of course, you can use .stop to kill anything that is running.
    con
    
      { ----------- }
      { Blinker Cog }
      { ----------- }
      
    
    var
    
      long  cog
      long  blinkstack[32]
    
    
    pub blink1(pin1, ms1)
    
      stop
      cog := cognew(run_blink1(pin1, ms1), @blinkstack) + 1
    
      return cog
    
    
    pub blink2(pin1, ms1, ms2)
    
      stop
      cog := cognew(run_blink2(pin1, ms1, ms2), @blinkstack) + 1      
    
      return cog
    
    
    pub blink3(pin1, ms1, pin2, ms2)
    
      stop
      cog := cognew(run_blink3(pin1, ms1, pin2, ms2), @blinkstack) + 1
    
      return cog
    
    
    pub stop
    
      if (cog)
        cogstop(cog - 1)
        cog := 0
    
    
    pri run_blink1(pin1, ms1) | t 
    
    '' Blink pin1
    '' -- toggles ever ms1 milliseconds
    
      ms1 *= (clkfreq / 1000)                                       ' convert to ticks
    
      dira[pin1] := 1                                               ' output mode
    
      t := cnt                                                      ' sync loop timing
      repeat
        !outa[pin1]                                                 ' toggle
        waitcnt(t += ms1)                                           ' wait
    
    
    pri run_blink2(pin1, ms1, ms2) | t
    
    '' Blink pin1
    '' -- on time in ms1, off time in ms2
    
      ms1 *= (clkfreq / 1000)
      ms2 *= (clkfreq / 1000)          
    
      dira[pin1] := 1                 
    
      t := cnt                       
      repeat
        outa[pin1] := 1     
        waitcnt(t += ms1)
        outa[pin1] := 0
        waitcnt(t += ms2)
        
    
    pri run_blink3(pin1, ms1, pin2, ms2) | t
    
    '' Alternate between pin1 and pin2
    '' -- timing independent per pin
    
      ms1 *= (clkfreq / 1000)
      ms2 *= (clkfreq / 1000)
    
      dira[pin1] := 1
      dira[pin2] := 1
    
      t := cnt
      repeat
        outa[pin1] := 1
        outa[pin2] := 0
        waitcnt(t += ms1)
        outa[pin1] := 0
        outa[pin2] := 1
        waitcnt(t += ms2)  
    
  • Jack3Jack3 Posts: 55
    edited 2014-02-05 15:12
    Jon,
    Thanks, Nope, I misunderstood about initializing variable But, I need to study what I have to do for the data section, not learned that yet, so have questions about what you showed me. You mention "t DAT array" but I don't see a t in the example. I also don't know how to address the data. You show "Pinz" Is the 'z' like a position place? I will go read up on DAT in a few.

    Your description of the blinker program sounds similar. My ultimate goal is to run multiple cogs with varying light displays that all work independently, including one method that uses radio input, splits up the length of the square wave (you gave the the code to do that). Think of an airplane....minimum of 2 each... wing lights, strobes, red flashing, landing lights....all working independently. The only one that would change would be the landing light one, so I kinda left that for last thing for cog 0 to do and to loop that part.

    One cog handles 2 pins solid lights
    one cog handles 2 pins with flash 1
    two cogs handle 4 pins with flash 2
    one cog handles the radio input/get square wave

    Main cog calls all the above and then loops on a method at the end that keeps calling the radio cog and then either calls another cog or just loops back to the check radio cog.(To clarify, it will use a case to determine whether to turn on, wig wag, or turn off the landing lights by starting and stopping one of two methods in one cog by using coginit.....if I ever get that far).....The big point is that I want everything to run independent of each other.
    So I will go write a loop to init my array until I learn how to use the DAT structures and see if this works better, maybe try the offering above and see what I can learn.

    Topping it all off, I haven't a clue, just desire to learn.
  • JonnyMacJonnyMac Posts: 9,107
    edited 2014-02-05 15:49
    That was a typo -- sorry.

    The lights that flash on an airplane are not changing at a fast rate. Cogs are precious -- save them when you can. I'll bet if I understood all of the conditions I (and others) could show you how to use a finite state machine approach to run all the lights in a single cog. Your master code would update a control variable that affects lighting behavior.
  • Jack3Jack3 Posts: 55
    edited 2014-02-05 15:59
    Ok, well just learning here. You guys are pros, I am neonatal here........Going to work on that data statement. I really want to write this myself. I don't want others to do it for me, tho I am not beyond copy and paste to speed things up IF I UNDERSTAND the code. Won't use code I haven't been able to understand yet, that is cheating and not learning. I will get there. Back to plugging along.
  • JonnyMacJonnyMac Posts: 9,107
    edited 2014-02-05 16:36
    Your call. You learned to walk by watching someone else do it -- you can learn to code that way, too. Unless this is the only program you ever plan on working with... :)
  • Jack3Jack3 Posts: 55
    edited 2014-02-05 18:02
    No I actually learn more deciphering other folks code and then use it. Can't just walk with it if you can't understand the cracks in the sidewalk
  • JonnyMacJonnyMac Posts: 9,107
    edited 2014-02-05 18:33
    As this is a thread on airplane lights, can you explain the behavior(s) of the various lights. I love programming, and would love to prove to myself that I can do it in one cog. I won't post that code unless you ask for it.
  • ratronicratronic Posts: 1,451
    edited 2014-02-05 18:36
    Edit: see next post
  • kuronekokuroneko Posts: 3,623
    edited 2014-02-05 18:55
    @ratronic: When cognew fails it returns -1 meaning the if b in your sample would still evaluate to true, not really what you want I'd say.
  • ratronicratronic Posts: 1,451
    edited 2014-02-05 19:01
    Edit: kuroneko is right thanks kuroneko!
  • Jack3Jack3 Posts: 55
    edited 2014-02-06 09:52
    Sure Jon,
    I thought I posted this once, but it wasn't here when I came to ask new question.

    First, sure, I would like to see it, go for it...
    4 LED's on solid, one in each wing tip and sometimes 2 so there needs to be 4 on.
    2 LED's at wing tips, with 1/10 second double flash, with one second pause after On, 1/10 off, On, 1 sec off, repeat
    2 LED's Usually rudder and belly with flash 1/2 second on and 1/2 off, alternating which is on and which is off to save power input for LED's
    2 LED's Landing lights, with 3 options, off, on always, or wigwag between the two 1/2 sec in the on/off.

    The last required the code you gave me to digest the square wave for a case statement for the 3 options, with OFF the default case

    Ok, I think that describes the idea....now.

    Still working on my question, .....later
  • Jack3Jack3 Posts: 55
    edited 2014-02-06 11:10
    Jon,
    With hours of testing and modifying, I can get 3/4 (not gone further yet, one bug at a time). I used your DAT statement, called it pinz, and when I called methods, I used @ pinz[x]. The first time it ran, it ran on the correct pins. Things worked okay through the first two method calls. Then I added the third method call and things went bizarre, The program from that point on shifted all the pin locations up by 5 pins. Even removing power from the board did not clear this problem. I could not get pins 1..4 to do anything until I commented out the data statement, and then by hard code, initialized the pins to their place in the array. That resolved all of the problems I had been chasing around getting nowhere.

    This way the code works. I left in the comment out code
    VAR
      byte pin[15]
      long PulseWidth
      byte index
    
    PUB Main 
    
      {{index :=1
      repeat until index == 16      This doesn't work either
          pin[index] :=  index++ }}
          {{so I hard code it to make program work here}}
      pin[1]:=1
      pin[2]:=2
      pin[3]:=3
      pin[4]:=4
      pin[5]:=5
      pin[6]:=6
      pin[7]:=7
      pin[8]:=8
      
     
      ''Flash1.LED1(@pinz[1],@pinz[2])          Slow flash
      Flash1.LED1(pin[1],pin[2])
      waitcnt(clkfreq/2+cnt)                  ''gives a gap on start so everything isn't starting at same tine
                                                            ''reducing load on 5V side
    
      ''Flash2.LED2(@pinz[3], @pinz[4])    ''all on the same cycle fast flash
      Flash2.LED2(pin[3], pin[4])
      waitcnt(clkfreq/2+cnt)
    
      Solid3.Solids(pin[5], pin[6], pin[7], pin[8])              'all solid on
      ''Solid3.Solids(@pinz[5], @pinz[6], @pinz[7], @pinz[8])
      waitcnt(clkfreq/2+cnt)
      *****************************
    DAT
            pinz  byte 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
              
    
    If you need more information ask me and I will be happy to try to clear things up....try. LOL
  • JonnyMacJonnyMac Posts: 9,107
    edited 2014-02-06 11:21
    Jack,

    Here's an alternative to a method you posted above.
    pri blink_method1(pin1, pin2) | delay1, delay2, t
    
      delay1 := clkfreq / 6                                 ' 6 Hz
      delay2 := clkfreq >> 1                                ' 2 Hz
    
      dira[pin1] := 1                                       ' make pins outputs
      dira[pin2] := 1
    
      t := cnt                                              ' sync timing
      repeat
        repeat 2                                            ' double flash
          outa[pin1] := 1                                   ' on
          outa[pin2] := 1
          waitcnt(t += delay1)
          outa[pin1] := 0                                   ' off
          outa[pin2] := 0
          waitcnt(t += delay1)
          
        waitcnt(t += delay2)                                ' longer off/delay
    


    You can remove a bit of redundancy with an inner repeat loop. I tend not to toggle pins when a specific pattern is required -- I also tend to go for the most obvious coding so I don't use the ~~ or ~ post operators. While it's not important for this app, I like to use synchronized delays. In this case, the delay times are pre-calculated which simplifies the loop code.
  • Jack3Jack3 Posts: 55
    edited 2014-02-06 14:08
    Thanks I see that, did not even cross my mind but definitely is a better way.

    Good I get confused with those Dang ~ operators, do not like them. Like 1's and 0's a whole bunch.... or -1 and 0, whichever, I can grasp that one.

    Can you explain what you mean with the term synchronized delays. Varying output times?
  • JonnyMacJonnyMac Posts: 9,107
    edited 2014-02-06 18:42
    There's a really good explanation of synchronized delays in the manual, starting on page 219. Timing for what happens in the loop synchronized to a singular point, just before entering the loop. Using this style removes the overhead of accessing the cnt register in the middle of the loop, allowing very precise timing of the loop. The only caveat is that anything happening inside the loop, must consume less time than the loop delay.
Sign In or Register to comment.