Shop OBEX P1 Docs P2 Docs Learn Events
Is it possible — Parallax Forums

Is it possible

bboy8012bboy8012 Posts: 153
edited 2008-06-05 15:06 in Propeller 1
Is it possible to have the prop take input on one cog, and execute it on another. And if so where would I get guidance to get started. I have the input on one cog already, its just get the input from that cog, and having it excute on another is where I am coming up with problems. All ideas are greatly appreciated. Thanks

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Hunger hurts, starvation works!

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2008-05-31 00:45
    What exactly do you mean by executing input? Do you e.g. sample a pin and want to do anything with it? What is the nature of your input and what do you want to do with it?
  • bboy8012bboy8012 Posts: 153
    edited 2008-05-31 01:02
    Let me be more specific, take input for hyperterminal to control a ESC. I want to input a value send it to the ESC, and then be able to change it again. So have the hyperterm input loop, and update the speed that I input. I have a ESC object, and am using Full_Duplex serial.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • kuronekokuroneko Posts: 3,623
    edited 2008-05-31 01:24
    bboy8012 said...
    Let me be more specific, take input for hyperterminal to control a ESC. I want to input a value send it to the ESC, and then be able to change it again. So have the hyperterm input loop, and update the speed that I input. I have a ESC object, and am using Full_Duplex serial.

    Not knowing the ESC object, I simply assume it has an API which allows it to take the input value obtained by other means. So the easiest solution would be your main program reading the input value in whatever form it is delivered by the terminal and send it to the ESC object. You said that you have the input part ready. Is your current problem related to conversion (e.g. ASCII/binary) or more general? I mean once you started your objects (input, ESC) they (usually) run on their own cog anyway, so all you have to do is link them.
  • bboy8012bboy8012 Posts: 153
    edited 2008-05-31 02:10
    Here is the code that I have, its rough and am just getting a feeling for spin again.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • kuronekokuroneko Posts: 3,623
    edited 2008-05-31 02:40
    bboy8012 said...
    Here is the code that I have, its rough and am just getting a feeling for spin again.

    The main loop looks fine to me. You get a decimal value and deliver it to the ESC object.

    You might want to check you repeat until condition. I assume you want to exit when throttle is 0 (throttle == 0). ATM you assign 0 (FALSE) to throttle which makes that an endless loop.

    Also, in the ESC object, I assume the methods fullbrake/fullthrottle should use dira[noparse][[/noparse]pin]~~ rather than dira[noparse][[/noparse] 4 ]~~.
  • bboy8012bboy8012 Posts: 153
    edited 2008-05-31 20:29
    I seem having problems with the repeat loop. Once·the throttle value is passed to the ESC object it doesnt repeat like supposed to?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • kuronekokuroneko Posts: 3,623
    edited 2008-05-31 23:17
    The throttle method never returns. All the other methods use repeat 150 for the pulse setup. Method throttle uses repeat only which makes it an endless loop.
  • bboy8012bboy8012 Posts: 153
    edited 2008-06-01 16:00
    Ok i guess my question would be if theres a way to have the loop continuing and return to the main object·so a new value·could be·input? I was thinking of a if statement, but would there be any other options?
    PUB throttle(pulseWidth)
      ctra[noparse][[/noparse]30..26] := %00100                                'Configure counter A to NCO mode
      ctra[noparse][[/noparse]8..0] := pin
      frqa := 1
      dira[noparse][[/noparse]pin]~~
      tC := ((clkfreq/ 100_000) * 2000)
      tHa := ((clkfreq/ 100_000) * pulseWidth)
      t := cnt
      repeat
        phsa := -tHa
        t += tC
        waitcnt (t)
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • Mike GreenMike Green Posts: 23,101
    edited 2008-06-01 17:06
    What you want is to fork off another cog (using COGNEW) that would continue setting the counter periodically.

    Instead of calling "throttle", you would use a COGNEW to call it. You would need some kind of interface routine
    that would either check for an existing cog running throttle and stop it before starting a new one or you'd have to
    slightly rewrite "throttle" so it gets its pulse width from a common variable and reinitializes itself if the pulse width
    changes.
  • bboy8012bboy8012 Posts: 153
    edited 2008-06-01 20:43
    ok thanks for the point of direction Mike

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • bboy8012bboy8012 Posts: 153
    edited 2008-06-01 22:43
    So i took the option of cognew and followed as best i could the prop manual, but once it hits the throttle method, it doesnt return to give me an oppourtunity to enter in a new value?
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      pin = 21
    VAR
      long throttle, throttleStack[noparse][[/noparse]24]
      byte Cog
    OBJ
      debug : "FullDuplexSerialPlus"
      esc   : "ElectronicSpeedControl"
    PUB main
       debug.start(31, 30, 0, 9600)                         'Sets serial params for terminal use
       esc.delay(3500)
       debug.Str(String("Please wait while calibrating the ESC....")) 
       esc.initialize                                       'Call initialize the ESC
       debug.Str(String(10, 13,"ESC calibrated"))
       
       'Loop for speed change
       repeat 
        debug.Str(String(10, 13,"Enter throttle speed: "))  
        throttle := debug.getDec
        
        debug.Str(String(10, 13, "Going to throttle speed: "))
        debug.Dec(throttle)
        
          Stop
          cognew(esc.throttle(throttle), @throttleStack)
    PUB Stop
      if Cog
        cogstop(Cog~ -1)
    

    heres my·ESC object
    CON
      pin = 21
      
    VAR
      long tC, tHa, t
    PUB initialize
      fullBrake                                       'Fullbrake
      Delay(500)                                      'Delay 500 mS
      fullThrottle                                    'Fullthrottle
      Delay(500)                                      'Delay 500 mS
      fullBrake                                       'Fullbrake
      Delay(500)
    PRI fullBrake
      ctra[noparse][[/noparse]30..26] := %00100                                'Configure counter A to NCO mode
      ctra[noparse][[/noparse]8..0] := pin
      frqa := 1
      dira[noparse][[/noparse]pin]~~
      tC := ((clkfreq/ 100_000) * 2000)                     ' Set up cycle and high times 20ms
      tHa := ((clkfreq/ 100_000) * 100)                     ' 1.0ms pulse
      t := cnt                                              'Mark counter time
      
      repeat 150
        phsa := -tHa                                        ' Set up the pulse
        t += tC                                             ' Calculate next cycle repeat
        waitcnt(t)
    PRI fullThrottle
      ctra[noparse][[/noparse]30..26] := %00100                                'Configure counter A to NCO mode
      ctra[noparse][[/noparse]8..0] := pin
      frqa := 1
      dira[noparse][[/noparse]pin]~~
      tC := ((clkfreq/ 100_000) * 2000)                     ' Set up cycle and high times 20ms
      tHa := ((clkfreq/ 100_000) * 220)                    ' 2.2ms pulse
      t := cnt                                              'Mark counter time
      
      repeat 150
        phsa := -tHa                                        ' Set up the pulse
        t += tC                                             ' Calculate next cycle repeat
        waitcnt(t)
    PUB throttle(pulseWidth)
      ctra[noparse][[/noparse]30..26] := %00100                                'Configure counter A to NCO mode
      ctra[noparse][[/noparse]8..0] := pin
      frqa := 1
      dira[noparse][[/noparse]pin]~~
      tC := ((clkfreq/ 100_000) * 2000)
      tHa := ((clkfreq/ 100_000) * pulseWidth)
      t := cnt
      repeat
        phsa := -tHa
        t += tC
        waitcnt (t)
        
    PUB Delay(mS)
      waitcnt((clkfreq / 1000 * mS) + cnt)
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • Mike GreenMike Green Posts: 23,101
    edited 2008-06-01 22:52
    Take a look at the Servo4 and Servo32 objects from the Propeller Object Exchange. The Servo4 object in particular will show you how this sort of thing can be done.

    Basically, you can't do it the way you tried. The cog that you start has its own counter and I/O registers so all of the initialization and counter manipulation code has to be running in that cog.
  • bboy8012bboy8012 Posts: 153
    edited 2008-06-01 23:04
    I have just decided to rewrite throttle, and am in the process.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • bboy8012bboy8012 Posts: 153
    edited 2008-06-02 03:50
    So I got it to work using cognew. But it only takes in a few pulses and then quits can someone tell me why?
    {{
    EDF ESC spedd control via hyperterm
    Frank Shearer v.01
    }}
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      pin = 21
    VAR
      long throttlePulse, tC, tHa, t, Stack[noparse][[/noparse]100] 
      byte Cog
      
    OBJ
      debug : "FullDuplexSerialPlus"
    PUB Main
      debug.start(31, 30, 0, 9600)                         'Sets serial params for terminal use
      delay(3500)
      debug.Str(String("Please wait while calibrating the ESC...."))
      initialize
      debug.Str(String(10, 13,"ESC calibrated"))
      repeat
        getinput
      'Stop                          'Stopping previous cog
      'cognew(getInput, @stack)      'Starting a new cog to update throttle method
      
    PUB getInput | prevPulse
      repeat 
        debug.Str(String(10, 13,"Enter throttle speed: "))  
        throttlePulse := debug.getDec
        prevPulse := throttlePulse
        debug.Str(String(10, 13, "Going to throttle speed: "))
        debug.Dec(throttlePulse)  
        Stop
        cognew(throttle(throttlePulse), @stack)
        
    PUB initialize
      fullBrake                                       'Fullbrake
      Delay(500)                                      'Delay 500 mS
      fullThrottle                                    'Fullthrottle
      Delay(500)                                      'Delay 500 mS
      fullBrake                                       'Fullbrake
      Delay(500)
    PRI fullBrake
      ctra[noparse][[/noparse]30..26] := %00100                                'Configure counter A to NCO mode
      ctra[noparse][[/noparse]8..0] := pin
      frqa := 1
      dira[noparse][[/noparse]pin]~~
      tC := ((clkfreq/ 100_000) * 2000)                     ' Set up cycle and high times 20ms
      tHa := ((clkfreq/ 100_000) * 100)                     ' 1.0ms pulse
      t := cnt                                              'Mark counter time
      
      repeat 150
        phsa := -tHa                                        ' Set up the pulse
        t += tC                                             ' Calculate next cycle repeat
        waitcnt(t)
    PRI fullThrottle
      ctra[noparse][[/noparse]30..26] := %00100                                'Configure counter A to NCO mode
      ctra[noparse][[/noparse]8..0] := pin
      frqa := 1
      dira[noparse][[/noparse]pin]~~
      tC := ((clkfreq/ 100_000) * 2000)                     ' Set up cycle and high times 20ms
      tHa := ((clkfreq/ 100_000) * 220)                    ' 2.2ms pulse
      t := cnt                                              'Mark counter time
      
      repeat 150
        phsa := -tHa                                        ' Set up the pulse
        t += tC                                             ' Calculate next cycle repeat
        waitcnt(t)
    PUB throttle(pulseWidth)
      ctra[noparse][[/noparse]30..26] := %00100                                'Configure counter A to NCO mode
      ctra[noparse][[/noparse]8..0] := pin
      frqa := 1
      dira[noparse][[/noparse]pin]~~
      tC := ((clkfreq/ 100_000) * 2000)
      tHa := ((clkfreq/ 100_000) * pulseWidth)
      t := cnt
      repeat 
        phsa := -tHa
        t += tC
        waitcnt (t)
        
    PUB Delay(mS)
      waitcnt((clkfreq / 1000 * mS) + cnt)
    PUB Stop
      if Cog
        cogstop(Cog~ -1)
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • kuronekokuroneko Posts: 3,623
    edited 2008-06-02 04:09
    I'm not sure what the exact reason is, but the variable Cog is never set to the cog number. So the stop method call (in getInput) does effectively nothing. The subsequent cognew will consume all available cogs which will at least result in undefined behaviour. You probably want something like

    stop
    Cog := cognew(throttle(throttlePulse), @stack) + 1
    


    Anyway, starting a cog for every function call is overkill (and adds unnecessary delay). You should exchange parameters through some defined hub location.
  • bboy8012bboy8012 Posts: 153
    edited 2008-06-02 04:17
    and how would I go about your suggestion? I updated my code but still the same problem. Also I do not think I am getting the correct pulsewidth when entering my values. Well that is how it looks on the oscope atleast.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • hippyhippy Posts: 1,981
    edited 2008-06-02 14:15
    @ bboy8012 : Take a step back and start with something simpler.

    Get a Propeller controlling the rate of flashing a LED, put that in its own Cog and then control the rate of flashing from the main Cog. Upgrade that main Cog so you can change the rate of flashing via serial or whatever.

    Once you've got the notion of parallel processing understood with data passed between the two working it will all become a lot easier than trying to crowbar what you have into shape.

    Basically, you don't want to keep executing CogNew as has already been said. Get a second Cog running at the start of the program the hand the data it needs to it. That created cog should initialise once then run in a loop reading the data handed to it and doing whatever it needs to. Beyond that, there should be no other ongoing interaction between the two cogs.

    Untested, but something like ...

    
    CON
      PIN_NUMBER = 0
    
    PUB CogPrimary | timePeriodMs
    
      CogNew( CogSecondary( PIN_NUMBER ), @stack )
      
      timePeriodMs := 1000
      repeat
        sharedData := timePeriodMs
        WaitCnt( CLKFREQ + CNT
        timePeriodMs -= 100
        if timePeriodMs == 0
          timePeriodMs := 1000    
    
    PUB CogSecondary( pinNumber ) | timePeriodMs
      DIRA[noparse][[/noparse] pinNumber ] := 1
      repeat
        timePeriodMs := sharedData
        WaitCnt( CLKFREQ / 1000 * timePeriodMs + CNT )
        ! OUTA[noparse][[/noparse] pinNumber ] 
    
    
    

    Post Edited (hippy) : 6/2/2008 2:27:03 PM GMT
  • Erik FriesenErik Friesen Posts: 1,071
    edited 2008-06-02 16:30
    I think you need to rethink your code also. Working with the ctr modes can be difficult enough with a little experience. It seems to me that you could do what you want in simple spin routines that use the waitpeq and waitpne or even the (repeat until pin==??)that update to a central program in the (main) cog. With a project of mine I am reading the pulse width from a fuel injector and I am using spin only. It is plenty fast enough in my opinion. One problem with using the ctr modes to do what you want is that they are exact and will count every thing even if it is just noise. There is no way to buffer your signal in software. Also Spin slows it down enough in my experience that with a slightly noisy input it gets it right where assembly is so fast that you for sure have to debounce or filter your input somehow.(for example the VSS signal).
  • bboy8012bboy8012 Posts: 153
    edited 2008-06-02 20:58
    Yes I have started researching and am going to take your advice of starting out simple with the flashing light. I believe there is one in the tutorials that will help me, and am also going to use your code as well hippy. I should of did that right away instead of jumping back into learning spin and getting all advanced. Hopefully I will get a gainfull knowledge by this weekend so I can continue. Thanks guys for the steer of direction.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • hippyhippy Posts: 1,981
    edited 2008-06-02 21:29
    Good luck; I went down quite a few wrong routes while learning and got into some very compilcated messes. Turned out to be much easier to build from the ground up. When you get nice clean, easy to follow code you know you're on the right track smile.gif
  • bboy8012bboy8012 Posts: 153
    edited 2008-06-05 02:04
    Ok in the process i have also learned about the timing of the propeller as well. I have followed your example hippy and understand the parrallel processing, with passing using a global variable. My next question is I have tried passing with parameters and it is not working for me. This is an example that I have been using. Can someone elighten me?
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      pin = 27
     
    VAR
      long pulseMS, stack[noparse][[/noparse]20]
      
    PUB Main | SharedP
      cognew(ThrottleControl(SharedP), @stack)            'Throttle control on seperate cog
      SharedP := GetInput
     
    PUB GetInput : sp
      sp := 1_500
    
    PUB ThrottleControl(pulseS) | pulse_MS 
      dira[noparse][[/noparse]pin]~~
      outa[noparse][[/noparse]pin]~
      repeat
        pulse_MS := PulseS
        outa[noparse][[/noparse]pin]~~                                         'pin on
        waitcnt((clkfreq / 1_000_000 * pulse_MS) + cnt)      'pulseMS on time between 1ms and 2.2ms
        outa[noparse][[/noparse]pin]~                                          'pin off
        waitcnt(clkfreq / 1_000 * 20 + cnt)                 '20ms Pause time
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • bboy8012bboy8012 Posts: 153
    edited 2008-06-05 02:06
    nevermind I found the problem, I was assigning the value after I started the new cog. By the way thanks for your help guys, I am getting back into the flow of spin.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • hippyhippy Posts: 1,981
    edited 2008-06-05 02:49
    You're not actually using a shared variable here though. You're reading a value and then passing it as a parameter ( pulseS ) into your ThrottleControl routine and then using that local variable. The ThrottleControl routine will only use the throttle setting specified when the Cog was started up; change SharedP as much as you want after that and the ThrottleControl routine will still be using the original value as first placed into 'pulseS'.
  • bboy8012bboy8012 Posts: 153
    edited 2008-06-05 02:57
    I just figured that out after testing it. Man just when I think I have it. Back to the manual! But when using a global variable will those update when I change the values?


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • bboy8012bboy8012 Posts: 153
    edited 2008-06-05 03:06
    LOL i answered my own question. But I dod have one what if I dont want the control in the same object. Say have a throttle object, gps object, and so on. But have them controlled by a Top level object. Is it possible to pass parameters between objects that way?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • Paul_HPaul_H Posts: 85
    edited 2008-06-05 05:17
    bboy - I guess this answers my Q in the other thread - You also have a RC plane too smile.gif

    Yes, you can run a master object that starts, modifies and send data to other objects. Take a look at my Pnav project. It is a work in progress
    Maybe this will help you in the theory. I have been slow-rolling an autopilot (...for the last year...) and you are welcome to use any of my code for you project.

    www.PNav.net I'll be posting a newer rev of code there on Friday ( Jury duty tomorrow!)

    Please share - You seem to be coding much faster than me!

    Paul

    Post Edited (Paul_H) : 6/5/2008 5:23:27 AM GMT
  • bboy8012bboy8012 Posts: 153
    edited 2008-06-05 12:47
    Thanks Paul actually your code is what made me want to try my UAV. I having been doing it for about 8months now, hard will school and other things. I want to try and make my code as easy as possible for new commers to the prop like myself, its just hard because I am keep getting my structure mixed up with java. I believe I am going to start a thread for UAV's with the forums approval, and continually update my project I am hoping to have it done fairly soon the first version of it anyways. Thanks for the answer too. I was looking through one of the P.E.s and found an example so hopefully I can get that potion going. But Now I am going to focus my attention to my parallax GPS module and get that going as well.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
  • hippyhippy Posts: 1,981
    edited 2008-06-05 14:46
    To use a shared variable in another object from the one you're setting it from you would use a pointer ...

    Main Object :
    OBJ
      subObject : "YourSubObject"
    
    VAR
      long sharedData
    
    PUB Main
      subObject.Start( @sharedData )
      repeat
        sharedData := someInputSource
    
    
    



    Sub Object :
    VAR
      long sharedDataPtr
      long stack[noparse][[/noparse] 100 ]
    
    PUB Start( pointerToSharedData )
      sharedDataPtr := pointerToSharedData
      CogNew( SubObjectLoop, @stack )
    
    PUB SubObjectLoop | sharedData
      repeat
        sharedData := long[noparse][[/noparse] sharedDataPtr ]
        DoWhatever
    
    
    
  • bboy8012bboy8012 Posts: 153
    edited 2008-06-05 15:06
    Thanks hippy for the esaier visual explanation, I have been looking at the P.E. for methods and cogs and was going off that.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hunger hurts, starvation works!
Sign In or Register to comment.