Shop OBEX P1 Docs P2 Docs Learn Events
accessing 1 object from 2 programs — Parallax Forums

accessing 1 object from 2 programs

TCTC Posts: 1,019
edited 2014-05-06 05:17 in Propeller 1
Hello all,

I am drawing a blank here, and am in need of some advice. I am going to try to explain this the best I can.

My main object (parent) will start 2 cogs. One cog is reading temperature, and the other cog is performing the PID calculation and the simple PWM controlling. What I want is the temperature cog to pass 2 forms of temperature data, one form to the parent(current full temperature data for displaying), and the other form(shorten temperature data) to the PID/PWM cog. But I also must be able to pass values to the PID/PWM cog.

I hope that makes sense.

Thanks
TC

Comments

  • T ChapT Chap Posts: 4,223
    edited 2014-05-04 14:46
    Just start a cog and include a pointer to a var in main/hub.

    Var long temp1, temp2


    Cognew(@stack, @temp1)


    In the cog, access the temp1 data with

    Pub main(tmp)
    long[tmp] := 1. 'Temp1
    Long[tmp+4] := 1. "Temp2

    This assumes it is a long data. Otherwise use word or byte. You can access other data on the same line by indexing using +4 etc.


    Send any cog the same pointer and any cog can read or write the value
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2014-05-04 15:11
    T Chap wrote:
    Cognew(@stack, @temp1)
    I think you meant
    cognew(main(@temp1), @stack)
    

    -Phil
  • T ChapT Chap Posts: 4,223
    edited 2014-05-04 15:27
    Of course. But I am on my cell :)
  • TCTC Posts: 1,019
    edited 2014-05-04 15:53
    This is great! I'm going to learn something new! I personally have not made a object that passes the location of a variable when starting a new cog. I have used what others have made.

    And I just realized I forgot some much needed information in my first post.:innocent:

    Each cog is controlling 2 things. The temperature cog controls 2 MAX31855 with 2 32-bit values. I can make the parent read the 32-bit value, and the adjusted values from the MAX31855 (thermocouple, Cold Junction, and errors). The PID/PWM cog has 2 PID's it runs through, and the output of the PID goes to the PWM that controls the heaters. I can adjust the PWM of the heaters individually from the parent.

    But I need the PID/PWM cog to get the thermocouple values from the MAX31855's and run the PID about once a second. The parent can request the current MAX31855 data at anytime. *edit* But the parent needs to be able to send the "set" temperature to the PID.
  • T ChapT Chap Posts: 4,223
    edited 2014-05-04 16:15
    Var  long  stack[32]
    Var long temp1, temp2, SetTemp, requestTemp    ' do not change the order of longs on this row once set. 
           'Long1,      +4,    +8,     +12    indexing to access other longs on the same row.  
    


    cognew(main(@temp1), @stack) 'start a cog doing something
    cognew(PID(@temp1), @stack2) 'start a cog doing something
    cognew(PID2(@temp1), @stack3) 'start a cog doing something

    In the cog, access the temp1 data with
    Pub main(tmp)
     Repeat
       IF long[tmp+12] == 1    'if the main program sets the RequestTemp flag to 1,  update the temp1 long
           long[tmp]  := TempFromThermocoupler
           long[tmp+12] := 0    'reset the request for tempdata
       SetTheTemp(long[tmp+8])    'run a method to update the temp based on whatever is in SetTemp
    

    There are various ways to do what you want. The above is just examples to show you how you can read or write any variable from any cog. IF you want to write bytes, it will be the same but only use byte[someparamter] := 1 as an example. You can modify any preexisting object to accept a parameter that is a pointer, except that if the object is using PASM, there is more work to do to get the pointer into the PASM code plus have the PASM doing some extra work to rdlong or wrlong.
  • TCTC Posts: 1,019
    edited 2014-05-04 16:32
    Oh, OK. So you are saying "temp1" is the starting variable, and any object(or cog) I pass the location to is able to use that address as an index to the value they need. Is this correct?
  • T ChapT Chap Posts: 4,223
    edited 2014-05-04 16:46
    Exactly. You are passing a position that the cog can use to read/write to and from. Actually, you can pass multiple pointers if you want in the cognew.
    cognew(main(@temp1, @temp2, @setTemp), @stack)
    
    Pub main(tmp1, tmp2, settmp)
     Repeat
       IF long[tmp1] == 1 
         long[tmp2] := 9
         long[setTmp] := 5
    
    
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-04 16:59
    This thread has examples of both passing the an address to a child object and returning an address from a child object.

    Don't tell anyone, but when I have a bunch of variables that need to be shared, I just make a monster parent object and dispense with child objects except for low level drivers.
  • TCTC Posts: 1,019
    edited 2014-05-04 17:00
    Wonderful, thank you so much. Love it when I get to play with something new.
  • TCTC Posts: 1,019
    edited 2014-05-04 17:11
    Duane Degn wrote: »
    This thread has examples of both passing the an address to a child object and returning an address from a child object.

    Don't tell anyone, but when I have a bunch of variables that need to be shared, I just make a monster parent object and dispense with child objects except for low level drivers.

    Those are some good examples, thanks for sharing.

    I wont tell.... many. Muahahah :lol:

    I personally like to have A object for each task. If I need to control an LED, I make an object that its only job is to control the LED. I do that because I can get lost in large amount of code. So I split the code into smaller sections that I do not have to have open if I do not need to look at them. Then I would just call the object from the parent object. This is going to help with the way I do code. Right now I have to tell my child objects to change things. But now I can just have the parent change the RAM value, and the child will just look at the RAM location.
  • T ChapT Chap Posts: 4,223
    edited 2014-05-04 17:18
    You could explore setting and forgetting a counter to manage the LED dimming, may not need objects dedicated.
  • TCTC Posts: 1,019
    edited 2014-05-04 17:22
    T Chap wrote: »
    You don't need an object dedicated to the LED. The counter can get set and forget for the dimmed color.

    I know I don't. I just helps me to stay on tract, and so I don't get lost.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-04 17:58
    TC wrote: »
    I can get lost in large amount of code. So I split the code into smaller sections that I do not have to have open if I do not need to look at them.

    Ideally, one would want to organize code with object but there are times when doing so can create more work than it may be worth.

    A few years ago I was trying to make a GPS logger. The examples I found in the OBEX used cogs very inefficiently. By moving many of the child objects into the parent object, I was able to reduce the number of cogs used by four.

    I left the CON and VAR sections next to the section of code they were used with. These extra CON and VAR sections made it much easier to find my way around in the code. Here's what the "Summary" view looks like when using the smallest font.

    GpsSpinSummary140504a.jpg


    Sure it would have been nice to have the code broken into objects but I decided I would rather spend the time it would require to do so some other way.

    The Propeller Tool also has bookmarks to make sections of code easier to find.
    1024 x 744 - 96K
  • TCTC Posts: 1,019
    edited 2014-05-04 18:11
    Most of my objects don't use another cog. But all the constants, and variables that are needed for that object are within that object. Yes, it adds more spin files for one program. But it makes it so much easier for me to understand. Sometimes I do it thatway, but sometimes I kept runnging into the problem of changing things. I would change the code, and forget to change the constant or variable. Doing it where everything has it's own object, forces me to make sure I have everything fixed.
  • T ChapT Chap Posts: 4,223
    edited 2014-05-04 18:11
    I made my own editor that only allows methods to exist on buttons, you can see up to 25 buttons per view, and you can scroll through blocks of 25. You can click on a button, and move it up or down. Click on the button for the method and it's contents show up on the editor screen above. Scrolling through lines of code in Proptool, bst, etc is a giant waste of time.
    675 x 715 - 157K
    sd.jpg 157.2K
  • TCTC Posts: 1,019
    edited 2014-05-04 18:38
    That's a cool way to do it.

    For the record, I don't leave my code the way I am doing it. I only do it the way I am doing it for creating my program. Once I am happy with what I have, I will open up the child object file, change the name (add underscore before name) then copy and paste the child object to the parent. Then I will change a few things. Most of the time all I have to do is change the dot (name "."name) to a underscore (name"_"name). My way has a large flaw that I know of, it uses a lot of ram. I'm ok with that for getting the program working, but not the final code.
  • TCTC Posts: 1,019
    edited 2014-05-05 18:19
    I need some advice on this.

    I have a total of 19 variables that are being shared between the parent and one child object.
     
      current upper temperature
      current lower temperature
      upper set temperature
      lower set temperature
      upper error
      lower error
      upper last error
      lower last error
      proportional gain
      upper proportional control value
      lower proportional control value
      integral gain
      upper integral control value
      lower integral control value
      integral "anti-windup" max value
      derivative gain
      upper derivative control value
      lower derivative control value
      bias
    
    

    These variables are being used mostly by the child object. But I want to be able to have the parent object to be able to read and write the contents of the variables.

    I am using what everyone has suggested, but I am starting to get lost keeping tract of what pointer I should use (index+4, index+8, index+32, etc..)

    I tried to do
    CON
    
      UpperCurrentTemp    =  index+0 ~>(32-12)   ' the "~>(32-12)" is for separating the 12-bit value from the raw value of the MAX31855
      LowerCurrentTemp    =  index+4 ~>(32-12) 
      Upper_SV                =  index+8                  ' Upper set value
    

    But it does not work since "index" is a variable.

    Does anyone have any ideas that would make my life a lot better with trying to manage all these variables?

    Thanks
    TC
  • T ChapT Chap Posts: 4,223
    edited 2014-05-05 18:30
    I am not understanding what you are describing.
  • TCTC Posts: 1,019
    edited 2014-05-05 19:13
    I have 19 variables that I want to store in my main (parent) object. Because I want the main object to be able to read all 19 variables, and change some of them. But I have another object (child) that needs to be able to read and write the same variables. Both objects will never change the same variable at the same time. The variables listed are for 2 PID's that run in another cog, that in turn there CV (control value) goes to 2 simple (in spin) PWM drivers.

    I am trying to do the 2 PID algorithms, but with all these variables, I am getting lost keeping tract of the offset(I think that what it is called) of the variable I need. Take this for example;
       long[_index+16] := long[_index+8] - (long[_index] ~> (32-12))
    
    

    This line of code is "Upper_error := Upper_Set_Value - Upper_Current_value

    I am use to having variable names I can put in code, not " long[_index+16] ". I am just wondering if there is a better way of doing it.

    Hope that makes more sense.
  • T ChapT Chap Posts: 4,223
    edited 2014-05-05 19:37
    Sure, just send a pointer for each variable. In the object, give the parameter a similar name or same name as the original in Hub.
    pid.start(@pos, @status, @TripLevelBias, @P, @encoderfault, direction[2])     'start a cog with a PID loop
    
    
    PID engine:
    
    PUB start(pos, status, TripLevelBias, propPar, encoderfault, setdirection)
        repeat
            cal(pos, status, TripLevelBias, propPar, encoderfault)
    
    
    PUB cal(pos, status, TripLevelBias, propPar, encoderfault)  | stat
            repeat while ||(long[pos] - (encodercount/10) )
            long[status] := 1
            long[encoderfault] := 3
    
    

    Just a hacked together example of using real names versus indexing.
  • kuronekokuroneko Posts: 3,623
    edited 2014-05-05 19:43
    @TC: Just group all your VARs in a long array, pass its base address and access them by index, e.g.
    VAR
      long  one, two
    
    PUB null
    
      child.init(@one)
    
    In child object:
    PUB init(addr)
    
      base := addr
    
    PUB getSum : s
    
      s := long[base][0]             ' same as one in parent
      s += long[base][1]             ' same as two in parent
    
    Numeric indices can be dressed up as constants for easier access.
  • msrobotsmsrobots Posts: 3,709
    edited 2014-05-05 21:49
    kuroneko wrote: »
    @
    Numeric indices can be dressed up as constants for easier access.

    As usual with kuroneko's post you really need to read the fine print.

    so change
    CON
    
      UpperCurrentTemp    = 0
      LowerCurrentTemp    = 4
      Upper_Set_Value       =  8                  ' Upper set value
    ..
    [B]  Upper_error[/B]             = 16
    

    to get more readability into it
    long[_index+upper_error] := long[_index+  Upper_Set_Value] - (long[_index+UpperCurrentTemp] ~> (32-12))
    

    Enjoy!

    Mike
  • TCTC Posts: 1,019
    edited 2014-05-06 05:17
    I want to thank everyone for helping me with this problem. But I think I am over thinking things. I an going to use the advice, and only worry about 2 variables that will be shared between the 3 objects. The additional variables will be in one of the 2 child objects.

    What I am going to do is, in the parent object I will declare 2 variables that will be shared.
    VAR
    
       long   UpperTemp, LowerTemp
    

    The one child object will just write its values to the variables in the parent object.

    Then in the other child object, I would have
    CON
    
      upper         = 0
      lower         = 1
    
    VAR
    
      long  Pgain
      long  Igain
      long  Dgain
    
      long  Imax
    
      long  SetValue[2]
      long  CurrentValue[2]
      long  Error[2]
      long  LastError[2]
      long  Pterm[2]
      long  Iterm[2]
      long  Dterm[2]
      long  ControlValue[2]
    

    And in this child object, I will have methods that will "return" the contents of a variable that are needed. And it also will have the address of the 2 variables that are in the parent object.
Sign In or Register to comment.