Shop OBEX P1 Docs P2 Docs Learn Events
Cognew Spin troubleshooting: global variables, infinite loops, and serial terminal — Parallax Forums

Cognew Spin troubleshooting: global variables, infinite loops, and serial terminal

KhiyaKhiya Posts: 6
edited 2012-07-31 14:43 in Propeller 1
Hello,

Please let me know if these questions are addressed in another thread - I have simply been unable to find it thus far.
The code in question has been pasted to the end of this post.

THE GENERAL PROBLEM:
Launching an infinitely looping method into a new cog with "cognew" does not return program control to the parent cog. Instead, the child cog obediently carries out its infinite loop and steals the show.
I've determined this behavior with serial terminal updates. I've browsed the Spin manual and Education Kit manual, as well as related forum questions, without quite learning what I've done wrong. I'm assuming an infinite loop can be launched into another cog so that program control returns to the main cog. I'm assuming serial terminal debug updates are not misleading my conclusions. I'm assuming I've assigned plenty of stack space for each method I'd like to launch into another cog. I'd appreciate someone pointing out if I've simply misunderstood some basic facts about the Propeller or Spin in implementing this multitasking thread.

THE SPECIFICS:

I'm using Spin on a Protoboard to read data from a LISY300 gyroscope.
I want to introduce multitasking in order to have three cogs continuously processing gyro data and updating/reading global variables:

Cog 0 initializes this object, starts Cog 1 and Cog 2 with their tasks, and then continuously monitors an input pin waiting for an external trigger to begin an SPI data transfer. This transfer provides another microcontroller with the gyro readings.
Cog 1 is continuously taking measurements from the actual gyro module. It updates a global variable (named "ADC") with the most current gyro measurement.
Cog 2 is continuously reading the most recent gyro measurement stored in the ADC variable and computing rate information (stored in the Rate global variable)

I've adapted my code from a LISY300 gyro demo written by Parallax staff and adapted by Jim Miller on August 25, 2010: http://obex.parallax.com/objects/662/

THE OBSERVATIONS:
When I run this code, my serial terminal only receives the serial statements made before and inside of the Measure method started in Cog 1. The "Completed Measure cognew call" statement is never received.

MY SUSPICIONS:
There's a simple answer that I just never picking up from looking at all the cognew examples. Is there a tricky little problem with my formatting of launching methods into a new cog? Is there a problem of having multiple cogs in a single object only manipulating global variables? Is my serial terminal only responding to the method in Cog 1 although the propeller is in fact running the other methods in the other cogs? How then can I set up the serial terminal to give me accurate feedback? Hopefully the solution is simple. Any advice?

*Please note*: In the code below I've simplified the visual complexity by summing up chunks of code with a description like: '
. I doubt the code in these areas is relevant to my question, however I have attached my raw file, messy comments and everything, to this post. The attached file is named "PropellerController", although it only specifically controls the Gyro. For now. 

[code]
CON                                                   

  _CLKMODE = XTAL1 + PLL16X
  _XINFREQ = 5_000_000
  
CON             
                                       
     '[Declare pin aliases here]
 
VAR                                                    

     '[Declare global variables here, including:]

     long ADC                                              
     long Center, Deg, Rate, Angle                          
     long RateMaxCW, RateMaxCCW, offset

     long MeasureStack[200]     
     long ComputeStack[200]
  
  
OBJ                                                     ' Object References

     pst: "Parallax Serial Terminal"
  
PUB Initialization             

    ' [Initialize port directions here]

    pst.start(115200)
   
    Calibrate                     ' Calibrate gyro by finding center of readings when gyro is at rest
    Main                           ' Main loop in program        

PUB Main  
  
   cognew(Measure, @MeasureStack)                                                       '
  
    pst.str(string("Complete Measure cognew call", 13))

    cognew(Compute, @ComputeStack)       
 
    repeat                                                                                      'Repeats indefinitely
           
         '[Monitor input pin and begin SPI when an input is detected]


PUB Calibrate | Value, Sigma, Minimum, Maximum, Average

     '[Performs calibration using each of the variables listed above]

PRI Measure              
      
    pst.str(string("Measure Start",13))
  
    repeat                                                                                         'Repeats indefinitely
    
          'Performs gyro measurement, updates ADC variable
          pst.str(string("Gyro measurement loop finished",13))
       
 
PRI Compute                     

    pst.str(string("Compute Start",13))

    repeat                                                                                       'Repeats indefinitely  

          Rate := ADC - Center
          '[Compute other stuff depending on value of Rate]
          pst.str(string("Computation loop finished"))


I'm happy to provide clarification if this is still just too confusing.

Many thanks,

Khiya

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2012-07-28 17:46
    Your problem is a simple one. The serial terminal can't cope with multiple writers. A quick fix would be the introduction of a print method which serialises the calls to the terminal by using a lock, e.g.
    CON                                                   
    
      _CLKMODE = XTAL1 + PLL16X
      _XINFREQ = 5_000_000
      
    CON                                                    
         '[Declare pin aliases here]
     '
    VAR                                                    
    
         '[Declare global variables here, including:]
    
         long ADC                                              
         long Center, Deg, Rate, Angle                          
         long RateMaxCW, RateMaxCCW, offset
    
         long MeasureStack[200]     
         long ComputeStack[200]
    
         [COLOR="red"]long lock[/COLOR]
      
    OBJ                                                     ' Object References
    
         pst: "Parallax Serial Terminal"
      
    PUB Initialization             
    
        ' [Initialize port directions here]
        [COLOR="red"]lock := locknew[/COLOR]
        pst.start(115200)
       
        Calibrate                     ' Calibrate gyro by finding center of readings when gyro is at rest
        Main                           ' Main loop in program        
    
    pub Main | position, time_i, time_f  
      
         cognew(Measure, @MeasureStack)                                                       '
      
         [COLOR="#FF0000"]print[/COLOR](string("Complete Measure cognew call", 13))
    
         cognew(Compute, @ComputeStack)       
     
         repeat                                                                                      'Repeats indefinitely
               '[Monitor input pin and begin SPI when an input is detected]
    
    PUB Calibrate | Value, Sigma, Minimum, Maximum, Average
    
         '[Performs calibration using each of the variables listed above]
    
    PRI Measure                    
        [COLOR="#FF0000"]print[/COLOR](string("Measure Start",13))
      
        repeat                                                                                         'Repeats indefinitely
        
              'Performs gyro measurement, updates ADC variable
              [COLOR="#FF0000"]print[/COLOR](string("Gyro measurement loop finished",13))
           
     
    PRI Compute                     
        [COLOR="#FF0000"]print[/COLOR](string("Compute Start",13))
    
        repeat                                                                                       'Repeats indefinitely  
    
              Rate := ADC - Center
              '[Compute other stuff depending on value of Rate]
              [COLOR="#FF0000"]print[/COLOR](string("Computation loop finished"))
    
    [COLOR="red"]PRI print(addr)
    
      repeat while lockset(lock)
      pst.str(addr)
      lockclr(lock)
    [/COLOR]
    DAT
    
    When you post code please wrap it in [noparse]
    
    [/noparse] tags.                        
  • KhiyaKhiya Posts: 6
    edited 2012-07-31 14:43
    Many thanks, kuroneko. That's a great solution!

    -Khiya
Sign In or Register to comment.