Shop OBEX P1 Docs P2 Docs Learn Events
Expert help is needed — Parallax Forums

Expert help is needed

grasshoppergrasshopper Posts: 438
edited 2008-09-27 12:26 in Propeller 1
I am running several cogs and trying to figure out why this is not working.

I simply have dedicated one cog to measure temperature. It also takes some 200 samples and averages it. This is in turn given to my main cog that sends it to a computer program every secound.

This is the main cog running code *note not all the code is given due to length but i am sure the problem is in the
  
OBJ

  Ser           : "FullDuplexSerial"                    '1 cog 
  Ft            : "FloatMath"
  Strings       : "FloatString"
  TempObj       : "Temps"                               '1 cog + 1cog
  PID           : "PIDf"                                '2 cog
  
Pub Init


  ConfigProp                    ' Set up pins
  StartCogs                     ' Start up cogs
  Main
  

Pub ConfigProp 

  Error_Report := "0"  
  Stir_On :=  "-"
  Temp_Con  := "-"
  Status := "C"
  
  Kp := 14.0
  Ki := 0.0
  Kd := 0.0
  
  maxArea := 0.0
  minArea := 0.0
  
  OffSet := 0.0
  
  TargetTemp := 20.00

  Ct_Time := 15
  
  timer1 := cnt 'make inital snapshot of systemcounter
   
  
Pub StartCogs 

  TempObj.start

  Ser.Start(31,30,0,baud)

  Pid.init(Kp, Ki, Kd, TargetTemp, offset, maxArea, minArea)
    

Pub Main |   Value, eTime1, Control 


  Control := 0

  repeat
        
         
          IF (ser.rxcheck == $5B) 
                          Value :=  getcom 
                                                
          Case Value                                    'Checking for changes made from program 
                                1 : Temp_Con := "+"
                                    Control := 1                                                        
                                                        
                                2 : Temp_Con := "-"
                                    Control := 2
                                    
                                3 : Pid.Update(3,TargetTemp)

          Temperature :=  TempObj.OneShot    '''''''''''''''''''''''''''''''''''''<--------------------------------------Problem area
                                                                                           
          IF (eTime1 => Ct_Time * Secound)              'Check time in sec/s
                                                     
                                timer1 := cnt                                                                                                          
                                ser.str(string("[noparse][[/noparse]Current Temperature "))         
                                ser.str(strings.FloatToFormat(Temperature,8,4))
                                ser.str(string("]"))                                 
                            





And this is the code that measures temperatures can be downloaded

Any help would be great thanks

Comments

  • TimmooreTimmoore Posts: 1,031
    edited 2008-09-25 16:49
    You need to describe what "not working" is.
    But there is 1 quesiton I have, TempObj.start starts a cog that runs OneShot which takes a temp reading averaged, ignores the calculated temp and returns shuting the cog down.
    You then call TempObj.OneShot from your main code directly which gets a temp value and returns it. The tempobj cog has no purpose - why?
  • StefanL38StefanL38 Posts: 2,292
    edited 2008-09-25 18:39
    hello Grashopper,

    as you wrote only it is not working the forum has to guess what

    from the code you have posted it is not clear if
    variable etime1 is updated regurlarly

    it's not clear what's the result of Ct_Time * Secound


    The averaging goes about the 30 samples inside Oneshot
    with every new loop and call of method TempObj.OneShot
    the old value of variable Temperature will be overstored

    you always get the average of the last 30 sample from the last
    Temperature := TempObj.OneShot

    I think you are using my elapsed_time_msec-method
    you have to code

      etime1 := elapsed_time_msec(timer1) 'INSIDE the loop
    
    
    



    or directly

      IF (elapsed_time_msec(timer1) => Ct_Time * Secound)
        timer1 := cnt
        '...
    
    



    If the problem is something else you have to describe it

    to give the forum a good chance to write a useful problem-solving answer
    you should check your posting about
    can somebody - who does NOT know anything about the specialties of my project -
    understand what is going on ?

    decide for posting even more than even less of information.

    If you have a suspect about the part where the error is
    make it easy to find in your code be '''<<<====== MARKING IT
    like you did it here. But attach your complete project

    please please please I have seen it SO MANY TIMES over all the years:

    making a quick and short posting then the time to get a SOLVING answer is much longer than
    if you take yourself the time for a well written FIRST posting

    best regards

    Stefan
  • grasshoppergrasshopper Posts: 438
    edited 2008-09-25 20:53
    Sorry fellas. I was in a hurry and forgot. Anyhow the part that is not working clearly is when I am running the "main code" and try to get the temperature reading from the other cog. When i get the temperature variable.

    Temperature :=  TempObj.OneShot 
    
    



    Pub Main |   Value, eTime1, Control 
    
    
      Control := 0
    
      repeat
            
             
              IF (ser.rxcheck == $5B) 
                              Value :=  getcom 
                                                    
              Case Value                                    'Checking for changes made from program 
                                    1 : Temp_Con := "+"
                                        Control := 1                                                        
                                                            
                                    2 : Temp_Con := "-"
                                        Control := 2
                                        
                                    3 : Pid.Update(3,TargetTemp)
    
              Temperature :=  TempObj.OneShot  
                                                                                               
              IF (eTime1 => Ct_Time * Secound)              'Check time in sec/s
                                                         
                                    timer1 := cnt                                                                                                          
                                    ser.str(string("[noparse][[/noparse]Current Temperature "))         
                                    ser.str(strings.FloatToFormat(Temperature,8,4))
                                    ser.str(string("]"))                                 
    
    



    It seems that the main code running in the repeat loop will wait for this variable to update. This is a real big bottle neck when i use the PID object that calculates this temp reading.

    Post Edited (grasshopper) : 9/25/2008 8:58:44 PM GMT
  • TimmooreTimmoore Posts: 1,031
    edited 2008-09-25 21:33
    if you look at temps.spin Start it starts the math cog, then starts a cog running Oneshot. Its this second bit I dont understand and doesn't seem to do anything.
    Well depending on how long Oneshot takes it could be still running when you call Oneshot form the main cog, the results of 2 cogs talking to the device will be "interesting"
  • StefanL38StefanL38 Posts: 2,292
    edited 2008-09-25 22:02
    Hello Grashopper,

    I still do NOT fully understand what your description of the error means.

    To be honest: I get a little upset by your way of hurry AGAIN in the postings above !

    So I will ask concrete questions to make it clear:

    Do you KNOW how you can DEBUG codeline execution ?
    Do you KNOW how you can DEBUG values of variables?

    Did you debug the method main, how often the loop is executed in time ?

    Did you debug what values are stored in the variable Temperature ?

    What values do you EXPECT to be displayed when using the commands

    ser.str(string("[noparse][[/noparse]Current Temperature "))
    ser.str(strings.FloatToFormat(Temperature,8,4))
    ser.str(string("]"))

    What values do you REALLY GET when using these commands?

    Inside temp.spin the method "start" starts method OneShot in a new cog. Let's say this cog has ID-No "2".
    Then method OneShot runs down ONLY ONE TIME in cog "2". After that cog 2 does NOTHING ANYMORE !

    In your PUB Main you call TempObj.OneShot. This makes cog "1" ATTENTION ! cog "1" NOT cog "2" execute method OneShot

    So from this I can see that you have a lack of understanding what are cogs and what are objects and when is running what
    in which cog and how often.

    It might be that the position of the error is somewhere else.
    So where is the problem to attach your COMPLETE code to a posting ?
    Are you not allowed to do so from the chief of your company ?
    Are you afraid of let others see your style of programming ?
    Are you afraid of this could be too much for the forum-members ?

    If you write a posting that will answer my questions and has your project attached I will calm down
    and will analyze yor code. Otherwise I simply will not.

    regards

    Stefan
  • grasshoppergrasshopper Posts: 438
    edited 2008-09-26 14:18
    Stefan,
    Please no need to get upset with me. I am not the best writer so ill try again. My code is so long, this is the reason don't send it all. I am not embarrassed, hell only last week I went ridding nude on my bike. Ok that was a bit of the stretch of the truth. I am have no clue how to debug except running small pieces of code and checking for the expected result. Not sure if this is the correct approach.

    Perhaps you could help me getting my New object - Temps to measure temperature and hold the value in a variable. All I wish it to do is constantly measure temperature and average it (as a filter). The code works as far as measureing temperature, however I am not familuar with running a seperate cog that recieves the temperature from - Temps object.
  • TimmooreTimmoore Posts: 1,031
    edited 2008-09-26 16:04
    Still think you have a problem with cogs. I dont know what the main cog is calling - FilterTemp?. But if the main cog is calling FilterTemp then you still have the same problem of 2 cogs accessing the device. The problem is FilterTemp is accesing hardware via pins. Having 2 cogs - the 1 started by Start and the main cog accessing the same pins is going to give you a problem.
    If you want a cog running getting averaged temp and having the main cog getting the current average temp. Then you want
    FilterTemp to have a repeat loop, storing Value in a VAR variable and adding a routine (GetTemp) that returns this variable.
    Then FilterTemp will running updating the average temp and the main cog calls GetTemp.
  • grasshoppergrasshopper Posts: 438
    edited 2008-09-26 16:23
    Timmoore said...
    Still think you have a problem with cogs. I dont know what the main cog is calling - FilterTemp?. But if the main cog is calling FilterTemp then you still have the same problem of 2 cogs accessing the device. The problem is FilterTemp is accesing hardware via pins. Having 2 cogs - the 1 started by Start and the main cog accessing the same pins is going to give you a problem.
    If you want a cog running getting averaged temp and having the main cog getting the current average temp. Then you want
    FilterTemp to have a repeat loop, storing Value in a VAR variable and adding a routine (GetTemp) that returns this variable.
    Then FilterTemp will running updating the average temp and the main cog calls GetTemp.

    Can you post and example of how I address this.
  • TimmooreTimmoore Posts: 1,031
    edited 2008-09-26 16:46
    Take a look at this version. Change the main cog to call tempobj.GetTemp, this returns a variable which is being updated in the backgroound by th Filtertemp cog int he background. Dont call Filtertemp from the main cog

    Now, only the cog started from Start is accessing the hardware.
  • grasshoppergrasshopper Posts: 438
    edited 2008-09-26 16:58
    Thanks ill give it a run after lunch. Looks like you have opened my eyes.
  • grasshoppergrasshopper Posts: 438
    edited 2008-09-26 18:31
    This code you modified did not work correctly (Temps object) In my main cog i ran the following
    Pub Main |   Value, eTime1, Control 
      Control := 0
    
      repeat
            
             
              IF (ser.rxcheck == $5B) 
                              Value :=  getcom 
                                                    
              Case Value                                    'Checking for changes made from program 
                                    1 : Temp_Con := "+"
                                        Control := 1                                                        
                                                            
                                    2 : Temp_Con := "-"
                                        Control := 2
                                        
                                    3 : Pid.Update(3,TargetTemp)
    
             
               [b]Temperature := TempObj.GetTemp[/b]
                                                                                               
              IF (eTime1 => Ct_Time * Secound)              'Check time in sec/s
                                                         
                                    timer1 := cnt                                                                                                          
                                    ser.str(string("[noparse][[/noparse]Current Temperature "))         
                                    ser.str(strings.FloatToFormat(Temperature,8,4))
                                    ser.str(string("]")) 
    
    
    


    The data that i get is some string of numbers that is not correctly sent to the computer program. Hum... I think having the Temps object running in its own cog in a continuous loop is not possible?
  • TimmooreTimmoore Posts: 1,031
    edited 2008-09-26 19:08
    One problem I just noticed is you call math.start on the main cog, it needs to be moved to the FilterTemp cog. Move the Math.start to the first line in filtertemp (before the repeat)
  • grasshoppergrasshopper Posts: 438
    edited 2008-09-26 19:33
    I don't see how that can help, i did it and no such luck. Perhaps I cant store floating point numbers in the variable "averagetemp" and pass that to my main cog?
  • StefanL38StefanL38 Posts: 2,292
    edited 2008-09-26 19:44
    Hello Grasshopper,

    you still have NOT understand what is an object and what runs inside a cog

    The Temps-1.spin-file from Timmoore does the following

    in method start there is a command

      okay := cog := cognew(FilterTemp,@Stack) + 1          'Starting up this cog
    
    
    



    this command starts a new cog. Let's say this is cog No "2"

    Now what is running inside THIS cog No "2" ?

    Just the method FilterTemp NOTHING MORE !

    PUB FilterTemp has a infinite repeat-loop. So just THIS loop is running all the time

    PUB FilterTemp averages the temperature-values
    and STORES the averaged temperature in variable averagetemp
    PUB FilterTemp is ONLY WRITING to variable averagetemp

    the PUB GetTemp
    is ONLY READING variable averagetemp
    by this way of programming only ONE cog does the bitbanging with the serial interface of the temperature-sensor


    I discovered a bug in PUB FilterTemp from Timmoore.
    As you don't want to ATTACH your complete code to a posting I will NOT tell you where the bug is, - and because this would keep your programming-skills on the level of "have to ask for almost everything"

    Just a hint: To find the bug - DEBUG Pub FilterTemp by sending the values of ALL variables used by FilterTemp
    to a PC within every repeat of the loops and take a close look how the values change

    best regards

    Stefan
  • grasshoppergrasshopper Posts: 438
    edited 2008-09-26 19:52
    Stefan Thanks for the information. Your right I am still learning and need to learn more. Ill try my best to discover the error, but how do i debug when the propeller programmer has no debugging function?

    Or did i miss that also?

    Thanks for the help and the razzing ^^
  • TimmooreTimmoore Posts: 1,031
    edited 2008-09-26 20:02
    The changes I did to temps would fix the cog fighting of the device issue. If you have algorithmic mistakes in your averaging code I didn't look at that
  • grasshoppergrasshopper Posts: 438
    edited 2008-09-26 20:13
    Thanks for the help Timm, but now I am real interested in the issues that my new friend Stefan has brought to my attention. There are no calculation errors because i have ran the numbers for months now. The problem still remains that I can not receive data from a running cog that is in an infinite loop. All the examples that i have seen just toggle leds and set up cogs to run forever with out sending data to other cogs. This is unfortunate for me and illustrating at the same time. If I must post all of the source code I will do so i just feel that I wont learn from it and waste time.

    Hum .. Back to Stefan's post.

      okay := cog := cognew(FilterTemp(@averageTemp),@Stack) + 1      
    
    



    perhaps this may help ???
  • JasonDorieJasonDorie Posts: 1,930
    edited 2008-09-26 20:50
    I'm kind of new to this myself, but I think I understand enough to explain at least some of the problems Stefan pointed out.

    Calling 'TempObj.Start' is launching the function 'Temps.OneShot' on a new cog. That function will run, and eventually generate a computed value, but it won't 'go' anywhere, because cognew's only return value is which cog it started on. That means your computed value is lost. You could fix this by setting a global VAR to some known (but impossible) number, like -999 or something, and then setting it to the computed temperature in OneShot when it's ready. Your main program could wait until Temps.ReturnValue was not -999 and then display the answer.

    The other problem is that your main function is ALSO calling the Temps.OneShot function directly. So here's what your program flow looks like:

    Init:
    calls StartCogs : Launches Temps.OneShot on a new cog. This will run, produce a result, and then do nothing
    (does some other setup)
    calls Main

    Main: calls Temps.OneShot directly, from the main cog, probably in parallel with the one that's already running, but a little behind it.

    I'm not sure what the behavior of calling the OneShot function from the main cog will be, since it depends on the Math object. Having two cogs trying to access the same math object at the same time might be your problem. The Float32 functions set a global variable and then wait for a result from some assembly code running on another cog. Calling those functions from two cogs at the same time might corrupt the state and cause the functions to wait indefinitely. Changing the code as I suggested above should correct this as well.

    Jason
  • TimmooreTimmoore Posts: 1,031
    edited 2008-09-26 20:57
    A generic spin comment, the result is initialized to 0 but other local variables are not initialized.

    I would have a test program that calls CalcTemp(1) and make sure that returns the correct result
    then test the average code as a standalone piece of code and make sure it works. Then run it within a seperate cog.


    Post Edited (Timmoore) : 9/26/2008 9:04:23 PM GMT
  • TimmooreTimmoore Posts: 1,031
    edited 2008-09-26 21:05
    I am pretty sure that the problem isn't in the data access across cogs but in your average code. Look at my previous post.
  • grasshoppergrasshopper Posts: 438
    edited 2008-09-26 21:08
    Yea ill test it again, but it was working great till i made it into its own cog. Then again it was fine till i needed it to run continuously (i.e. repeat for ever)
  • StefanL38StefanL38 Posts: 2,292
    edited 2008-09-26 21:09
    Hello Grasshopper,

    your gueesing was right out of the fog into the fog

    if you read very carefully I wrote "IN" the PUB FilterTemp NOT at the cognew of FilterTemp


    the debugging works like this:

    you are already using a serial com-object

      ser.str(string("[noparse][[/noparse]Current Temperature ")) 
    
    




    now the debugging is to use serial output to trace what ever you like

    here is the code with added debugging via serial output
    Pub FilterTemp | Temperature , X, Temp1, Temp2, Temp3 , Nub
      ser.str(string("start of PUB FilterTemp - value of Temp1= "))
      ser.dec(Temp1)
      ser.tx(13)
       
      repeat
        ser.str(string("inside infinite repeat value of Temp1= "))
        ser.dec(Temp1)
        ser.tx(13)
        
        Nub := math.Ffloat(250)                             'making this a floating point number    
        Repeat X from 1 to 250                              ' Get temp 250 times loop         
          Temperature := CalcTemp(1)                      ' Measure AtoD convertor 16bit        
          Temp1 := Temperature + Temp1                    ' Add it up         
    
          ser.str(string("value of X= "))
          ser.dec(X)
          
          ser.str(string(" value of Temp1= "))
          ser.dec(Temp1)
          ser.tx(13)
    
        Temp2 := Math.Ffloat(Temp1)                         ' Float the total       
        Temp3 := Math.Fdiv(Temp2, Nub)                      ' total / 250
        
        averagetemp := Calc_Slope(Temp3)                    ' Final AVG> result
    
    



    running this version of FilterTemp and analyzing the debugoutput will guide you to the bug

    best regards

    Stefan
  • grasshoppergrasshopper Posts: 438
    edited 2008-09-26 22:01
    Well no noticeable errors at this point in time. Hum perhaps I know more than the "Fog" as you put it. I can run the code in my main code here is the difference.

      repeat
               
              IF (ser.rxcheck == $5B)                                
                                    Value :=  getcom                                                 
                                    Case Value
                                                            1 : Temp_Con := $2B  '+                                                                                                            
                                                            
                                                            2 : Temp_Con := $2D   '-                                                         
                                        
                                                            3 : SetPoint:= TargetTemp
                                                                                                                                                                                     
                                                            4 : Stir_On := $2B
                                                                    Pwme.SetDuty(Stir_Speed)
                                          
                                                            5 : Stir_On := $2D
                                                                    Pwme.SetDuty(0)
                                    
                                                            6 : If (Stir_On == $2B)
                                                                    Pwme.SetDuty(Stir_Speed)
                                  
                                                                                                         
              eTime1 := elapsed_time_msec(timer1)
                                                                                                                    
              IF (eTime1 => Ct_Time * Secound)&(Hault == $00)                                           
                                    timer1 := cnt                                                                                                                                          
                                    ser.str(string("[noparse][[/noparse]F1 CT "))         
                                   [b] ser.str(FloatToFormat(TempO.GetTemp,8,4)) [/b]
                                    ser.str(string("]"))
                                   
    
    



    That --^ works fine

    Pub Main |   Value, eTime1 , Temperature
    
      repeat
               
              IF (ser.rxcheck == $5B)                                
                                    Value :=  getcom                                                 
                                    Case Value
                                                            1 : Temp_Con := $2B  '+                                                                                                            
                                                            
                                                            2 : Temp_Con := $2D   '-                                                         
                                        
                                                            3 : SetPoint:= TargetTemp
                                                                                                                                                                                     
                                                            4 : Stir_On := $2B
                                                                    Pwme.SetDuty(Stir_Speed)
                                          
                                                            5 : Stir_On := $2D
                                                                    Pwme.SetDuty(0)
                                    
                                                            6 : If (Stir_On == $2B)
                                                                    Pwme.SetDuty(Stir_Speed)
                                  
                                                                                                         
              eTime1 := elapsed_time_msec(timer1)
             [b] Temperature := TempO.GetTemp [/b]                                                                                                     
              IF (eTime1 => Ct_Time * Secound)&(Hault == $00)                                           
                                    timer1 := cnt                                                                                                                                          
                                    ser.str(string("[noparse][[/noparse]F1 CT "))         
                              [b]   ser.str(FloatToFormat(Temperature,8,4))  [/b]
                                    ser.str(string("]"))
                                
    
    



    and this --^ wont. I am thinking that the timing is off or something
  • TimmooreTimmoore Posts: 1,031
    edited 2008-09-27 02:48
    In FilterTemp Temp1 is not intialized to 0, either in the version I sent you or before. In my version it should be zeroed everytime round the repeat loop, before it should have been initialized at the start of the routine.
    I commented that local variables are not initialized and your average assumes that locals are initialized to 0.
  • StefanL38StefanL38 Posts: 2,292
    edited 2008-09-27 06:06
    hello Grasshopper,

    Without RESETTING variable temp1 in PUB FilterTEMP inside the outer and infinite loop
    temp1 is counting up much too far because it is not resetted to zero and this gives strange results.


    I hope you can see from this example that GUESSING where the bug might be can lead you in a COMPLETE WRONG DIRECTION
    And the only two ways to find the bug are:

    1.) knowing a programing-language VERY WELL and be experienced enough to SEE the bug from reading the code

    2.) CAREFUL debugging STEP by STEP.
    You can start where you GUESS where the bug might be
    But ! - GUESSING oh I'm sure the bug is NOT there. I can drop checking this IS STRONGLY FORBIDDEN

    If you drop it, there will be cases where you will ran around in circles again and again and again maybe trying wild things
    until you decide to check the dropped point

    (and by doing 2.) going along the way to 1.)

    Grasshopper - please do me a favor and post the results that you get from your first and the second version of main

    Be sure that the PC-terminalsoftware is ready to receive the very first characters of ser.str(FloatToFormat(...
    by
    1.) loading the program to the EEPROM
    2.) open the comport in the PC-terminalsoftware
    3.) reset the propeller to let the prop start NEW while the comport is already opened

    best regards

    Stefan
  • hippyhippy Posts: 1,981
    edited 2008-09-27 12:26
    Just using Temperature as an intermediate variable doesn't seem to be a problem in itself, but
    what happens if you move that closer to your ser.str() ? Does that improve things ? How about
    just sending the values of Temp0.GetTemp and Temperature in a readable format to see what
    differences there are with minimal extra processing ?
Sign In or Register to comment.