Shop OBEX P1 Docs P2 Docs Learn Events
same objects differents cogs — Parallax Forums

same objects differents cogs

Laurent RLaurent R Posts: 27
edited 2009-04-15 09:05 in Propeller 1
I'm using an ADC (max1270) I have an object who read the convert value and it works well.

I want to launch a second cog within an infinite loop and this cog 'll read the converted value every 2 seconds (to manage an alarm).

So the "main" cog 'll be able to receive commands and read the converted value when I ask him.

I wonder as both cogs need to control the max1270 , they need the same object. Is it good or I have to write a second max1270 control object?


When the second cog is enable and run max1270 control, both cogs convert's results = 0 but if only the first is active the conversion is ok...

If I call the alarm method on the first cog, the result of the convertion is good too but I can't send him new commands...

Thanks for ideas

Laurent

Post Edited (Laurent R) : 4/10/2009 1:24:10 PM GMT

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2009-04-10 13:37
    I guess your problem is that you start the object twice. There is no need to do so, because usually the driver of a device is started in a separate COG. Either it waits for commands (like the FullDuplexSerial) or the driver runs endlessly to do it's job (like the TV/VGA drivers). As your COG which reads the MAX is working and repeatingly reading the voltage value, there should be a variable where you can find that value.
    All your second COG program needs to know is the adress of this variable. It should not start the ADC object again! Because of the internal rules for driving the I/Os of the propeller, it's unpredictable what happens when both COGs drive the same PINs.
    Maybe the Object has to be enhanced a bit with a function that returns the adress of the variable.
  • Mike GreenMike Green Posts: 23,101
    edited 2009-04-10 13:38
    This is too complicated a description. Please provide a copy of your source code as an attachment to your message.

    In general, if you have two cogs and each cog needs to access some device (like a MAX1270), you probably need to
    have each cog request exclusive use of the device just before using it, then release it when done. This is done with
    the LOCKxxx statements. The chapters on these statements in the Propeller Manual have examples of this.
  • Greg LaPollaGreg LaPolla Posts: 323
    edited 2009-04-10 13:43
    You cannot put an object into a cog. You can create a method and put that method into a cog like this:


    PRI main
      cog := cognew(@readadc, @stack)
    
    PRI readadc
    
    REPEAT
      adc read code here
      waitcnt(clkfreq * 2 + cnt) 
    
    



    Something like this is what you need to do. You could use a pointer to point to a variable in hub ram and update that from readadc and then you could just access that variable at anytime to get the value.


    Greg
  • localrogerlocalroger Posts: 3,452
    edited 2009-04-10 13:45
    @Laurent -- you should only have one cog directly controlling the ADC. It should leave the conversion result in Hub RAM where other cogs can read it. If other cogs need to exert some control over the ADC, they should leave "requests" in a Hub RAM variable which the cog that is actually controlling the ADC can check as a part of its loop and perform requested operations.
  • Laurent RLaurent R Posts: 27
    edited 2009-04-10 14:04
    Here is my code...

    As the max 1270 is alone, I thought it was good using the chip select pin to know when the max1270 is already at work... And so I wait that he not busy but maybe it's not the good way ...

    Thanks for the help

    Laurent
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-04-10 20:42
    Hello Laurent,

    I took a quick look into your code
    pretty long loop with a lot of commands in it

    you putted some comments in between. I want to make a suggestion:
    What do you think about the idea to divide these 640 ! lines of code in several methods
    and give each method a selfexplaining name ?

    When I learned programming I was told to do it straight structured. Every method does ONE thing


    Imagine phoning with TWO people at the same time. You would not understand anything if they are talking at the same time to you
    for the 1270 it is the same.
    Did you check if the busy-pin is signalising busy REALLY ALL the time until the request is done.
    As two cogs run completely independant from each other only the shortest time of the busy-pin signalising NOT busy is enough to
    make the second cog shout into the request if te´he first cog from time to time.


    The suggestion of localroger is the way to go. ONE cog talking dircktly to the ADC. All other cogs que requests via this cog.

    Do you have an idea how you can code the ADC-result to be stored in a global variable or how it can be given back over a method
    from the ADC-object ?

    If you are performing different commands towards the ADC. Would it still be fast enough to do ALL possible requests to the ADC ALL the time
    and provide the results in variables ?

    best regards

    Stefan
  • Laurent RLaurent R Posts: 27
    edited 2009-04-14 08:17
    I understand your suggestions but actually enable the alarm method fail...

    If the alarm method is the only one running, and if I add "serial.dec(value)" to display the result of the convertion

    It display a "0"

    So I think there is a problem when I use the adc method in a second cog...


    I'm confused

    Laurent


    EDIT :

    I try to start alarm method in the same cog and it display the right value ...

    But as soon as I start it in a new cog it display 0 ... Even if alarm is the only method running

    Post Edited (Laurent R) : 4/14/2009 9:34:29 AM GMT
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-04-14 10:42
    Hello Laurent,

    you have your main-object and this object defines some other objects.

    OBJ
        
      ser :         "Extended_FDSerial"    'For debug and serial com
      'ser :        "SerialMirror"
      max1270:      "Max1270"           'ADC interface
      fmt:          "Format"
      Alarm:        "Alarm"
    
    




    then you start the method Alarm in the object "Alarm"

    in the variable "val" you read in the ADC. This variable "val" is ONLY accessesible within the object "Alarm"
    in other words everywhere from INSIDE the file "alarm.spin" you can access the variable "val" directly

    OUTSIDE from the file "alarm.spin" you can NOT access the variable "val"

    you could write a method in the file "Alarm.spin"

    by the way: you are using the same name for THREE different things filename, object and method have the name "alarm"

    here MY "write maintainable code-ALARM" starts yelling at double-red !
    take 10 minutes and think about what could be DIFFERENT and senseful names for the filename, object and the method

    (maybe even some of your own confusion is caused by the same names)

    OK back to the main thing:
    you can write a method in the file "Alarm.spin" named "Get_value" wich returns the value of variable "val"

    If this is not the problem give a detailed info of what is going wrong

    I mean attach a program-version which "start alarm-method in the same cog"
    and add a mark something like "<
    here i get the right value" at the interesting line of code
    and a programversion where it does not work

    another thing you start Extended_FDSerial inTWO cogs with the same pins 31,30
    every command ser.start(31, 30, 0, 9600) starts a NEW cog !

    as cogs run independent from each other both can send at the same time and will mix up their signals

    Maybe you could write something about what your whole program should do

    It takes much more time if I re-engineer your code than you to write a description

    best regards

    Stefan
  • Laurent RLaurent R Posts: 27
    edited 2009-04-14 11:31
    Hi Stefan

    Here are 3 differents codes where you could see where the things gone wrong...

    I put some comment to help you to understand my problem...

    here is the goal of my code :

    I want to run in a "main" cog a method who receive comands on a serial link, do a task and send back an answer.

    One of thoses task is reading an ADC, the MAX1270.

    But I also want to use the MAX1270 in a second method running in a second cog. This second method is a infinite loop who get result of conversion wait few seconds and get result again (for debugging I send value to serial terminal). The result is used to set an alarm or not.

    While the alarm method is running, I should be able to get new commands on the serial link (reason for the second cog ...)

    For the serial object, pin 31,30 are just used fro debug, the other object is running with RS_RO and RSDI (pin 3 and 6)

    Thanks



    Laurent
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-04-14 20:27
    Hello Laurent,

    the cognew command should be done INSIDE the object

    I have a quick guessing. You are setting the CS-pin high in the main-method
    if you start another cog for RunAlarm the CS-IO-pin is switched in this OTHER cog

    as long as ONE cog has an IO-PIN HIGH the PIN will STAY high even if all other cogs
    switch it to low as the IO-Pin-state of all cogs are ORed with each other

    to test this simply send back a harcoded value for millivolts

    instead of

    PUB RunAlarm(ValAlarmHi,High_Pos,ValAlarmLo,Low_Pos,Latch_Alarm)| signe '
      ser.start(31, 30, 0, 9600)
      'dira[noparse][[/noparse]OTOR1] ~~
      repeat
     
        val:=max1270.get_millivolts(0, false, false) ' canal 0  / range : -10 +10
        HIGH(CS) 
        ser.dec(val)
        waitcnt(clkfreq*10 +cnt)
    
    



    code

    PUB RunAlarm(ValAlarmHi,High_Pos,ValAlarmLo,Low_Pos,Latch_Alarm)| signe '
      ser.start(31, 30, 0, 9600)
      'dira[noparse][[/noparse]OTOR1] ~~
      repeat
      
        val:=max1270.get_millivolts(0, false, false) ' canal 0  / range : -10 +10
        HIGH(CS) 
        'ser.dec(val)
        ser.dec(123)
        waitcnt(clkfreq*10 +cnt)
    
    



    and see if you get back 123 when alarm.startalarm is used

    This bug is caused or maybe I should say "supported" by your way of coding

    Your way of coding is to do MORE than one thing in ONE method and spreading functionality over several places
    here a High(CS) and there a outa[noparse][[/noparse]CS]~ and already catched a bug !

    I highly recommend to RE-code your program in a way that ONE method does ALL the details belonging to ONE thing

    this means there is one object max1270 which does EVERYTHING for the max1270:
    - initialisation of ALL pins related to the max1270
    - bitbanging of ALL pins related to the max1270 HIGH(CS) included and NO other places that switch ANY IO-pin related to the max1270

    then add a start-method "Start_Max1270" inside the object Max1270
    this method starts a cog with another method that has an infinite running loop and reads in the value ALL the time
    and stores it into a global variable "ActualVal" defined in the Max1270-object


    then add a method "Get_Max1270_Value" inside the object Max1270 which simply is

    PUB Get_Max1270_Value 
      result := ActualVal
    
    
    



    then you can call the method Get_Max1270_Value
    from everywhere you want to do that
    with

      val := alarm.Get_Max1270_Value
    
    



    and always get the actual value of the max1270

    best regards

    Stefan

    Post Edited (StefanL38) : 4/14/2009 8:33:57 PM GMT
  • Laurent RLaurent R Posts: 27
    edited 2009-04-15 07:51
    Thanks stefan, I'll try what you said ...

    I already try to ser.dec(123) and it works ...

    So I'll try to clean up all this mass and do something better and more simple ...

    Hope it 'll be good

    Laurent
  • Laurent RLaurent R Posts: 27
    edited 2009-04-15 09:05
    Stefan you are a god to me [noparse]:)[/noparse]

    I restart a blank project and made everything you said and tadaaam

    I'm now able to read the value from the first cog and from the second...

    Thanks again

    I hope that 'll be good now [noparse]:)[/noparse]

    Laurent
Sign In or Register to comment.