Shop OBEX P1 Docs P2 Docs Learn Events
Variables between objects — Parallax Forums

Variables between objects

DanicoDanico Posts: 10
edited 2009-05-04 22:30 in Propeller 1
Have searched the manual, forum and wiki, but just cannot see how to pass data between objects and cogs.· Here is an example of what I would like to do;
·
One object running continually·in one cog·evaluating the ambient light level, then once per second storing this level as a variable say "LightLevel" as a number between 1-20.
Another object running in another cog, will once every 10 seconds grab the current value, and send it out serially.· The issue is with this object being able to access 'LightLevel'.
·
Thought that there must be a way to have a global variable that each object could access.··In my searching, I found reference in the forum·to storing this variable·in·'hub ram', but could not find in the manual how to do this (or specific reference to hub ram).·
·
The aim is that both objects run independently, no passing of data between.
·
I guess this is a basic premise of multiple processors, so want to be sure I can get it right.
Any guidance would be greatly appreciated.
·
D

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-04 09:54
    What are we talking about? Diffrent COGs run different SPIN code or different PASM code or maybe both? Let's concentrate on the SPIN side first:

    Variables are local for an instance of the object. So, if you use one object twice, each will have it's own copy of the variables.
    SPIN 1 with filename "MyTest.spin":
     
    var 
      long myValue
    pub init
      myValue := cnt
    pub getValue
      return myValue
     
     
    SPIN 2:
    obj
       ob1: "MyTest"
       ob2: "MyTest"
       ser: "FullDuplexSerial"
    pub
       ser.init( .... )
       ser.rx
     
       ob1.init
       ob2.init
     
       ser.dec( ob1.getValue )
       ser.str(string(13))
       ser.dec( ob2.getValue )
       ser.str(string(13))
       
    


    Data stored in dat section is global for all instances of the object. So, if you use one object twice they work on the same data.
    SPIN 1 with filename "MyTest.spin":
     
    pub init
      myValue := cnt
    pub getValue
      return myValue
    dat
      myValue long 0
     
    SPIN 2 same as above
    
    

    But neither of these myValues will be visible in other code. So, the SPIN2 has no direct access to these variables. If you need access to one variable in more than one objects, you need a piece of central code which creates the variable, pass the adress of this variable to the object and then run the code in a COG.
    SPIN 1 (a writer for the variable):
    var
       long ptrToVar
       long stack[noparse][[/noparse]10]
    pub init(thePtr)
       ptrToVar:=thePtr
       cognew( write, @stack )
    pub write
       repeat
          long[noparse][[/noparse]ptrToVar]:=cnt
     
    SPIN 2 (a reader for the variable):
    var
       long ptrToVar
       long stack[noparse][[/noparse]10]
    pub init(thePtr)
       ptrToVar:=thePtr
       cognew( read, @stack )
    pub read | i
       repeat
          i:=long[noparse][[/noparse]ptrToVar]    ' read the actual value
          ....                 ' do something with the value
     
    SPIN 3 (the Manager ;o)
    obj
        ob1: "Writer"
        ob2: "Reader"
    var
        long theVarForBoth
    pub main
        ob1.init( @theVarForBoth )
        ob2.init( @theVarForBoth )
     
        ...   ' do whatever you wanna do here
          
       
    

    In dirty programming this is of course much easier ;o)
  • dnaddordnaddor Posts: 26
    edited 2009-05-04 12:38
    I don't know if this will help, but I posted a thread on sharing data between COGS and SPIN a couple of months ago.

    http://forums.parallax.com/forums/default.aspx?f=25&m=318611&g=318699#m318699

    Good luck.
  • DanicoDanico Posts: 10
    edited 2009-05-04 14:24
    As always didn't explain the issue too well.· Code always talks...

    This code (although pointless) works fine;
    CON
      _clkmode      = xtal1 + pll16x     'Sets the clock speed to 80 MHz using a times 16 multiplier
      _xinfreq      = 5_000_000          'Crystal speed: 5 MHz
    '
      NewLine = 13
      LineFeed = 10
    OBJ
      serial : "FullDuplexSerial"
    VAR
      long  stack0[noparse][[/noparse]20]
      long GlobalVariable
                                             
    PUB Start
      serial.start(6, 7, 0, 9600)
      
      cognew(Meter, @stack0)   
      repeat
        waitcnt(80000000 + cnt)       ' 1s
        serial.str(STRING("GlobalVariable = "))
        serial.dec(GlobalVariable)
        serial.tx(NewLine)
        serial.tx(LineFeed)
     
      
    PUB Meter 
       GlobalVariable :=0
       repeat                    
          MeterCount
            
    PRI MeterCount
           
      waitcnt(16000000 + cnt)       ' 200ms
      GlobalVariable++
    

    So the variable 'GlobalVariable' is available at all times.
    What I would like to do is have another object with the 'Meter' routines in it, kind of like this;
    CON
      _clkmode      = xtal1 + pll16x     'Sets the clock speed to 80 MHz using a times 16 multiplier
      _xinfreq      = 5_000_000          'Crystal speed: 5 MHz
    '
      NewLine = 13
      LineFeed = 10
    OBJ
      serial : "FullDuplexSerial"
      light : "Lmeter"
    VAR
      long  stack0[noparse][[/noparse]20]
      long GlobalVariable
                                             
    PUB Start
      serial.start(6, 7, 0, 9600)
      
      cognew(light.Meter, @stack0)   
      repeat
        waitcnt(80000000 + cnt)       ' 1s
        serial.str(STRING("GlobalVariable = "))
        serial.dec(GlobalVariable)
        serial.tx(NewLine)
        serial.tx(LineFeed)
    

    ·The the meter object;
    PUB Meter 
       GlobalVariable:=0
       repeat                    
          MeterCount
            
    PRI MeterCount
           
      waitcnt(16000000 + cnt)       ' 200ms
      GlobalVariable++
    

    But of course the variable GlobalVariable is not accessable by the Meter object file.

    This may all look like a strange idea, but the application I am thinking will involve a couple of large free running objects each·in their own cog, with one overarching object and cog picking relevant data from each·object as it needs it.· Sure enough this could be done in one long·object file, but it would be difficult to read and manage.· To have them seperate should make it maintainable.

    I hope I haven't confused the matter further!!

    Any ideas?

    D
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-05-04 14:57
    Hello Danico,

    as you already realized there is no direct access to variables ACROSS objects.

    You can make a big file still maintainable by self defined naming conventions and how you place
    the methods in a well defined order
    first all methods dealing with "task A"
    then all methods dealing with "task b"
    etc. where task means things like serial connection, read in sensor values, drive a display etc.

    all in alphabetical order
    and every method does ONE thing wich is explained by a selfexplaining name of the method itself
    (instead of adding comments all the time) once written copy and paste the longer PUB-Name is faster than copy and paste a short PUB-Name AND a comment

    Now there are different possabilities:

    As long as ONE object starts 1,2...6 cogs from the SAME object (=same *.SPIN-file)
    all variables of THAT object are accessible from EVERY cog.

    If you want to divide your code into multiple *.SPIN-files and still want to have access to the variables
    ACROSS the SPIN-files(=objects) one easy way is to define "SET" and "GET"-methods in the object that holds the variable

    VAR
      long MyVar1
      long MyVar2
      long MyVar2
    
    
    PUB GetMyVar1 : ValOfMyVar1
      result := MyVar1
    
    PUB SetMyVar1(value)
      MyVar1 := value
    
       
    PUB GetMyVar2 : ValOfMyVar2
      result := MyVar2
    
    PUB SetMyVar2(value)
      MyVar2 := value
       
    
    PUB GetMyVar3 : ValOfMyVar3
      result := MyVar3
    
    PUB SetMyVar3(value)
      MyVar3 := value
       
    
    



    this piece of code shows the basic principle.
    If methods running in different cogs and if two methods call one and the same of the SET-Methods
    it can happend that the value gets overwritten before important things are done

    To avoid this you would have to program a lock-mechanism by using the lockxxx-commands
    Here is no general advice possible.
    Some times it is OK to just wait for the variable to become status "unlocked"
    in other cases it is better to have a timeout while waiting
    sometimes just to NOT change the value

    This depends on your application

    best regards

    Stefan

    Post Edited (StefanL38) : 5/5/2009 10:49:44 AM GMT
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-05-04 17:33
    What about an object which only has constants? This can be used by each SPIN object and there each spin object can find the adresses of the variables. The variables are not real variables you can find in the var block, but memory at the end of RAM. Of course you have to watch out that code size never reaches this memory area.

    SPIN 1 named "MemMap.spin":
    con
       lGlobalVar1 $ff00
       lGlobalVar2 $ff04
       wGlobalVar4 $ff08
       ...
     
     
    SPIN 2:
    obj
       mm: "MemMap"
    var
       long aLocal
    pub doSomething
       aLocal:=long[noparse][[/noparse] mm#lGlobalVar1 ]
       word[noparse][[/noparse] mm#wGlobalVar ]:=aLocal>>16
       ....
     
    

    b, w and l can give you a hint what type the variables are. That's what I meant with dirty programming in my first post. But this way all Objects which load MemMap have access to all variables there. Hopefully the compiler is clever enough not to create much object overhead for the constant only object.
  • DanicoDanico Posts: 10
    edited 2009-05-04 22:30
    Thanks very much for the replies, greatly appreciated.

    Need to try the suggestions, and see what works·best -·I suspect one long file, well formatted, would be the easiest solution.

    D.
Sign In or Register to comment.