Shop OBEX P1 Docs P2 Docs Learn Events
Passing Vars to multiple cogs and back — Parallax Forums

Passing Vars to multiple cogs and back

W9GFOW9GFO Posts: 4,010
edited 2009-07-15 20:51 in Propeller 1
I think I figured a way to read pulse widths on 6 pins using counters on three cogs.

I've created an object called RX which launches the three cogs. I need to pass the the pins and the pulseWidth variables to the object, they are both arrays.

RX.start(pins, @pulseWidth)



When the new cogs are started they each need two pins for the counters and two variables in which to put the values.

Here is what I tried...
PUB Start (pins, pulsewidth)

  cog[noparse][[/noparse] 0] := (cog := cognew(readPins(pins, pulsewidth), @ stack) + 1)
  cog[noparse][[/noparse] 1] := (cog := cognew(readPins(pins[noparse][[/noparse] 2], pulsewidth[noparse][[/noparse] 2]), @ stack[noparse][[/noparse]100]) + 1)
  cog[noparse][[/noparse] 2] := (cog := cognew(readPins(pins[noparse][[/noparse] 4], pulsewidth[noparse][[/noparse] 4]), @ stack[noparse][[/noparse]200]) + 1)



PUB readPins (pins, pulsewidth)

  ctra[noparse][[/noparse]31..26] := %01000                     ' set mode to pos detector
  ctra[noparse][[/noparse]5..0] := pins

  ctrb[noparse][[/noparse]31..26] := %01000
  ctrb[noparse][[/noparse]5..0] := pins[noparse][[/noparse] 1]

  frqa := 1
  frqb := 1

  dira[noparse][[/noparse]pins]~
  dira[noparse][[/noparse]pins[noparse][[/noparse] 1]]~

  repeat
   repeat while pins
   phsa~
   waitcnt(clkfreq/200)
   pulsewidth := phsa/(clkfreq/1_000_000)

   repeat while pins[noparse][[/noparse] 1]
   phsb~
   waitcnt(clkfreq/200)
   pulsewidth[noparse][[/noparse] 1] := phsb/(clkfreq/1_000_000)



It is not working on any pins. I suspect that the pulseWidth variable is not getting written to properly, it is not clear to me if I need to use "@" before each "pulseWidth" or something else.
I'm pretty sure I could just write out the code for each cog and each variable but I am trying to figure out how to do it with minimal clutter.

Also, I am not sure if I am passing the pin values to each cog properly...

Rich H

Post Edited (W9GFO) : 7/12/2009 7:34:16 AM GMT

Comments

  • SamMishalSamMishal Posts: 468
    edited 2009-07-12 12:52
    There are a few problems with your code

    The line
    ···· RX.start(pins,·@pulseWidth)
    should be
    ···· RX.start(@pins,·@pulseWidth)

    the lines
    ··ctra[noparse][[/noparse]5..0]·:=·pins
    and
    ··ctrb[noparse][[/noparse]5..0]·:=·pins[noparse][[/noparse]·1]
    and
    ··dira[noparse][[/noparse]pins]~
    ··dira[noparse]/noparse]pins[noparse][[/noparse][color=white]·[/color]1~


    should be assuming pins is an array of longs....if it is bytes(more efficient) then change to byte
    ··ctra[noparse][[/noparse]5..0]·:=·long[noparse][[/noparse]pins][noparse][[/noparse]0]
    and
    ··ctrb[noparse][[/noparse]5..0]·:=·long[noparse][[/noparse]pins][noparse][[/noparse]·1]
    and
    ··dira[noparse]/noparse]long[noparse][[/noparse]pins][noparse][[/noparse]0~
    ··dira[noparse]/noparse]long[noparse][[/noparse]pins][noparse][[/noparse][color=white]·[/color]1~


    the line
    ···repeat·while·pins
    and
    ···repeat·while·pins[noparse][[/noparse]·1]


    should be
    ···repeat·while·long[noparse][[/noparse]pins][noparse][[/noparse]0]
    and
    ···repeat·while·long[noparse][[/noparse]pins][noparse][[/noparse]·1]


    but also look at the commands WaitPEQ and WaitPNE that do what you are trying to do more efficiently

    the lines
    ···pulsewidth·:=·phsa/(clkfreq/1_000_000)
    and
    ···pulsewidth[noparse][[/noparse]·1]·:=·phsb/(clkfreq/1_000_000)


    should be
    ···long[noparse][[/noparse]pulsewidth][noparse][[/noparse]0]·:=·phsa/(clkfreq/1_000_000)
    and
    ···long[noparse][[/noparse]pulsewidth][noparse][[/noparse]·1]·:=·phsb/(clkfreq/1_000_000)


    Also you are using WAY TOO much stack to each cog....10 to 15 should be OK

    Sam
  • SamMishalSamMishal Posts: 468
    edited 2009-07-12 13:01
    Oh also



    the lines

    ··cog[noparse][[/noparse]·0]·:=·(cog·:=·cognew(readPins(pins,·pulsewidth),·@·stack)·+·1)
    ··cog[noparse][[/noparse]·1]·:=·(cog·:=·cognew(readPins(pins[noparse][[/noparse]·2],·pulsewidth[noparse][[/noparse]·2]),·@·stack[noparse][[/noparse]100])·+·1)
    ··cog[noparse][[/noparse]·2]·:=·(cog·:=·cognew(readPins(pins[noparse][[/noparse]·4],·pulsewidth[noparse][[/noparse]·4]),·@·stack[noparse][[/noparse]200])·+·1)

    should be

    ··cog[noparse][[/noparse]·0]·:=·(cog·:=·cognew(readPins(@Long[noparse][[/noparse]pins][noparse][[/noparse]0],·@long[noparse][[/noparse]pulsewidth][noparse][[/noparse]0]),·@·stack)·+·1)
    ··cog[noparse][[/noparse]·1]·:=·(cog·:=·cognew(readPins(@Long[noparse][[/noparse]pins][noparse][[/noparse]·2],·@long[noparse][[/noparse]pulsewidth][noparse][[/noparse]·2]),·@·stack[noparse][[/noparse]100])·+·1)
    ··cog[noparse][[/noparse]·2]·:=·(cog·:=·cognew(readPins(@log[noparse][[/noparse]pins][noparse][[/noparse]·4],·@long[noparse][[/noparse]pulsewidth][noparse][[/noparse]·4]),·@·stack[noparse][[/noparse]200])·+·1)
  • W9GFOW9GFO Posts: 4,010
    edited 2009-07-12 16:59
    Thanks Sam. it is still not working unfortunately. I do have something displayed other than zeros now but the numbers don't makes sense. I expected one number (1520) and the other five fields zero. What I get, after about one minute, is 733805, 0, 7357XX, 0, 735260, 0. The "XX" is because the number runs off the display. The number will be different each time the program is run and it stays the same value.

    In case it changes anything, the pins and pulsewidths are declared thusly,

    VAR
    
      long pulsewidth[noparse][[/noparse] 6]
    
    DAT
    
      pins  LONG 1, 2, 3, 4, 5, 6
    



    In the top level object;
    PUB RXinput
    
      repeat until pressed == 0                                  ' Don't proceed until button let go
        ButtonCheck
    
      LCD.clear
    
      RX.start(@pins,@pulseWidth)
    
      repeat
    
        ButtonCheck
        debug(pulsewidth[noparse][[/noparse] 0], 4, 1, false, 4, 0)                        ' (value, X, Y, decimal?, digits, places)
        debug(pulsewidth[noparse][[/noparse] 1], 10, 1, false, 4, 0)
        debug(pulsewidth[noparse][[/noparse] 2], 16, 1, false, 4, 0)
        debug(pulsewidth[noparse][[/noparse] 3], 4, 2, false, 4, 0)
        debug(pulsewidth[noparse][[/noparse] 4], 10, 2, false, 4, 0)
        debug(pulsewidth[noparse][[/noparse] 5], 16, 2, false, 4, 0)
    
        out(7,pulsewidth[noparse][[/noparse] 0])
        out(8,pulsewidth[noparse][[/noparse] 1])
        out(9,pulsewidth[noparse][[/noparse] 2])
        out(10,pulsewidth[noparse][[/noparse] 3])
        out(11,pulsewidth[noparse][[/noparse] 4])
        out(12,pulsewidth[noparse][[/noparse] 5])
    



    The RX object;
    VAR
    
      byte cog[noparse][[/noparse] 3]
      long stack[noparse][[/noparse]60]
    
    PUB Start (pins, pulsewidth)
    
      cog[noparse][[/noparse] 0] := cognew(readPins(@long[noparse][[/noparse]pins][noparse][[/noparse] 0], @long[noparse][[/noparse]pulsewidth][noparse][[/noparse] 0]), @ stack) + 1
      cog[noparse][[/noparse] 1] := cognew(readPins(@long[noparse][[/noparse]pins][noparse][[/noparse] 2], @long[noparse][[/noparse]pulsewidth][noparse][[/noparse] 2]), @ stack[noparse][[/noparse]20]) + 1
      cog[noparse][[/noparse] 2] := cognew(readPins(@long[noparse][[/noparse]pins][noparse][[/noparse] 4], @long[noparse][[/noparse]pulsewidth][noparse][[/noparse] 4]), @ stack[noparse][[/noparse]40]) + 1
    
    PUB readPins (pins, pulsewidth)
    
      ctra[noparse][[/noparse]31..26] := %01000                     ' set mode to pos detector
      ctra[noparse][[/noparse]5..0] := long[noparse][[/noparse]pins][noparse][[/noparse] 0]
    
      ctrb[noparse][[/noparse]31..26] := %01000
      ctrb[noparse][[/noparse]5..0] := long[noparse][[/noparse]pins][noparse][[/noparse] 1]
    
      frqa := 1
      frqb := 1
    
      dira[noparse][[/noparse]long[noparse][[/noparse]pins][noparse][[/noparse] 0]]~
      dira[noparse][[/noparse]long[noparse][[/noparse]pins][noparse][[/noparse] 1]]~
    
      repeat
       repeat while long[noparse][[/noparse]pins][noparse][[/noparse] 0]
       phsa~
       waitcnt(clkfreq/200 + cnt)
       long[noparse][[/noparse]pulsewidth][noparse][[/noparse] 0] := phsa/(clkfreq/1_000_000)
    
       repeat while long[noparse][[/noparse]pins][noparse][[/noparse] 1]
       phsb~
       waitcnt(clkfreq/200 + cnt)
       long[noparse][[/noparse]pulsewidth][noparse][[/noparse] 1] := phsb/(clkfreq/1_000_000)
    
    PUB Stop
      if cog
        cogstop(cog[noparse][[/noparse] 0]~ -1)
        cogstop(cog[noparse][[/noparse] 1]~ -1)
        cogstop(cog[noparse][[/noparse] 2]~ -1)
    

    Post Edited (W9GFO) : 7/12/2009 5:57:54 PM GMT
  • SamMishalSamMishal Posts: 468
    edited 2009-07-12 17:23
    Rich,



    from a first look there are STILL plenty of errors.....but I am busy rght now and I will

    be back home in a few hours...I will point a few just now but there are MANY more....

    I will do later

    CON

    ··_clkmode·=·xtal1·+·pll16x
    ··_xinfreq·=·5_000_000

    should be in the TopLevel object

    ···repeat·while·long[noparse][[/noparse]pins][noparse][[/noparse]·0]
    ····phsa~
    ····waitcnt(clkfreq/200)
    ····long[noparse][[/noparse]pulsewidth][noparse][[/noparse]·0]·:=·phsa/(clkfreq/1_000_000)

    I think you did not mean to have the three lines under the repeat indented.....no??·

    Also the line
    ····waitcnt(clkfreq/200)

    should be·(there two of these)
    ····waitcnt(clkfreq/200+cnt)

    Your Stop method is erroneous....the line
    ···· if cog

    is wrong since cog is pointer and will always be non-zero.....


    These lines
    ··cog[noparse][[/noparse]0]·:=·(cog·:=·cognew(readPins(@long[noparse][[/noparse]pins][noparse][[/noparse]·0],·@long[noparse][[/noparse]pulsewidth][noparse][[/noparse]·0]),·@·stack)·+·1)
    ··cog·:=·(cog·:=·cognew(readPins(@long[noparse][[/noparse]pins][noparse][[/noparse]·2],·@long[noparse][[/noparse]pulsewidth][noparse][[/noparse]·2]),·@·stack[noparse][[/noparse]20])·+·1)
    ··cog·:=·(cog·:=·cognew(readPins(@long[noparse][[/noparse]pins][noparse][[/noparse]·4],·@long[noparse][[/noparse]pulsewidth][noparse][[/noparse]·4]),·@·stack[noparse][[/noparse]40])·+·1)

    should be

    ··cog[noparse][[/noparse]0]·:=·cognew(readPins(@long[noparse][[/noparse]pins][noparse][[/noparse]·0],·@long[noparse][[/noparse]pulsewidth][noparse][[/noparse]·0]),·@·stack)·+·1
    ··cog[noparse][[/noparse]1]·:=·cognew(readPins(@long[noparse][[/noparse]pins][noparse][[/noparse]·2],·@long[noparse][[/noparse]pulsewidth][noparse][[/noparse]·2]),·@·stack[noparse][[/noparse]20])·+·1
    ··cog[noparse][[/noparse]2]·:=·cognew(readPins(@long[noparse][[/noparse]pins][noparse][[/noparse]·4],·@long[noparse][[/noparse]pulsewidth][noparse][[/noparse]·4]),·@·stack[noparse][[/noparse]40])·+·1



    I will look for more later



    Sam




  • W9GFOW9GFO Posts: 4,010
    edited 2009-07-12 17:53
    Sheesh what a mess! So much for the great idea late last night...

    The top level object is working well, this RX thing is something I'm trying to add.

    The indentations were unintentional.
    The missing " + cnt" has been fixed.

    I changed the cog thing.

    Now I get all zeros....

    Im having trouble grasping how each cog will know to use different pins and pulseWidth locations.

    The initial call passes the addresses to the start method.

    RX.start(@pins, @pulsewidth)

    The start method then passes those to the three cognews

    cog[noparse][[/noparse] 0] := cognew(readPins(@long[noparse][[/noparse]pins][noparse][[/noparse] 0], @long[noparse][[/noparse]pulsewidth][noparse][[/noparse] 0]), @ stack) + 1
    cog[noparse][[/noparse] 1] := cognew(readPins(@long[noparse][[/noparse]pins][noparse][[/noparse] 2], @long[noparse][[/noparse]pulsewidth][noparse][[/noparse] 2]), @ stack[noparse][[/noparse]20]) + 1
    cog[noparse][[/noparse] 2] := cognew(readPins(@long[noparse][[/noparse]pins][noparse][[/noparse] 4], @long[noparse][[/noparse]pulsewidth][noparse][[/noparse] 4]), @ stack[noparse][[/noparse]40]) + 1

    Each cog is running the same readPins method

    readPins (pins, pulsewidth)
    " "
    ctra[noparse][[/noparse]5..0] := long[noparse][[/noparse]pins][noparse][[/noparse] 0]

    How does the first cog know that long[noparse][[/noparse]pins][noparse][[/noparse]0] should be a "1" and the second cog know that long[noparse][[/noparse]pins][noparse][[/noparse]0] should be a "3"?

    Rich H

    Post Edited (W9GFO) : 7/12/2009 7:06:50 PM GMT
  • SamMishalSamMishal Posts: 468
    edited 2009-07-13 00:35
    W9GFO said...

    How does the first cog know that long[noparse][[/noparse]pins][noparse][[/noparse]0] should be a "1" and the second cog know that long[noparse][[/noparse]pins][noparse][[/noparse]0] should be a "3"?

    Rich H
    Rich,

    I am looking at your code now....but I wanted to answer your question.

    When you say for example
    ····· cog[noparse][[/noparse] 1] := cognew(readPins(@long[noparse][[/noparse]pins][noparse][[/noparse] 2], @long[noparse][[/noparse]pulsewidth][noparse][[/noparse] 2]), @ stack[noparse][[/noparse]20]) + 1
    the variable pins holds an address to the FIRST number in the list of numbers.

    So when you say @long[noparse][[/noparse]pins][noparse][[/noparse]2] you are saying the address of the 3rd number in the list of numbers that
    start at the address whose value is in pins. So now since readpins() expects an adress this is perfectly RIGHT.....and then
    when you later say inside readpins()

    ··· ctra[noparse][[/noparse]5..0] := long[noparse][[/noparse]pins][noparse][[/noparse] 0]

    the value in pins is now the address of the third number in the list of numbers
    and Long[noparse][[/noparse]pins][noparse][[/noparse]0] is the value of that number

    the next line
    ·· ctrb[noparse][[/noparse]5..0] := long[noparse][[/noparse]pins][noparse][[/noparse]1]
    means the next long that follows the one that resides at the address that is pointed to by pins which is the 4th number

    so you see that the function readpins() will now not care where pins points it will take the long that is at the
    address pointed to by pins and the next one. So what you need is to make sure that for each cog to pass it the address
    of the 1st of the pairs of numbers. So the first time you are passing the address of the 1st and readpins() will calculate
    the address of the second. For the next call you are going to pass the address of the 3rd number and for the third call
    you pass it the address of the 5th number and so on.


    So knowing the address of the FIRST number (@pins) and you pass it along to the Start method it now can call the
    readpins() but each time with the address of the 1st in the pair and
    ·· @long[noparse][[/noparse]pins][noparse][[/noparse]0]· is the address of the first number·in the 1st pair
    ·· @long[noparse][[/noparse]pins][noparse][[/noparse]2]· is the address of the first number in the 2nd pair
    ·· @long[noparse][[/noparse]pins][noparse][[/noparse]4]· is the address of the first number in the 3rd pair

    and inside readpins() the address is de-referenced by using
    ·· Long[noparse][[/noparse]pins][noparse][[/noparse]0] and long[noparse][[/noparse]pins][noparse][[/noparse]1]

    REMEMEBER pins in the Start method is not the same as the pins in the readpins() method....the confusion is
    that you have named them the same name.....I usually prefer to name a variable that will hold an address rather than a value
    as e.g. pinsaddress·· or··· pinspointer··· or something similar.

    Sam



    Post Edited (SamMishal) : 7/13/2009 12:42:39 AM GMT
  • SamMishalSamMishal Posts: 468
    edited 2009-07-13 01:42
    Hi Rich,

    Here is a suggested code that I hope works.....the problem I think is the way you wait for the count....I do not think it
    correct·to wait for clkfreq/200· which is 5 milliseconds....now that might count too many pulses or no pulses depending
    on the frequency of the signal.....the way I have it is a better way.....you may have difficulty with the |< operator....read about it.
    It is basically saying give me a binary value with 1 at the bit which is the Pin number and the rest of the bits are 0.

    Another source of confusion might be the use of SPR register......read about it but basically
    ··· SPR[noparse]/noparse]8] is the same as saying[color=white]·[/color]CTRA and SPR[noparse][[/noparse]9] is the same as CTRB but with the SPR[noparse][[/noparse you can use a for-loop
    ··· so SPR[noparse][[/noparse]8+i] := .....····· is the same as saying CTRA :=.....· when i is 0 and CTRB := .... when i = 1

    Also notice how the mode and pin are set in one expression.....this is necessary since SPR cannot be addressed bit by bit

    Here is my suggested code.....I think this would work.....as I said the only REAL difference from your final code is the way it
    waits for a pulse.

    VAR
      byte cog[noparse][[/noparse] 3]
      long stack[noparse][[/noparse]60]
      long uS
     
    PUB Start (pins_array_address, pulsewidth_array_address)|i
      uS := clkfreq/1_000_000
      Stop   'call the stop method to stop cogs tha may be already started
      repeat i from 0 to 2
         cog[noparse][[/noparse]i] := cognew(readPins(@long[noparse][[/noparse]pins_array_address][noparse][[/noparse]i*2], @long[noparse][[/noparse]pulsewidth_array_address][noparse][[/noparse]i*2]), @ stack[noparse][[/noparse]i*20]) + 1
     
    PUB readPins (pins_address, pulsewidth_address)| i,p1,p2
      repeat i from 0 to 1
         spr[noparse][[/noparse]8+i]  := %01000 << 26 + long[noparse][[/noparse]pins_address][noparse][[/noparse]i]   'set the mode and pin for ctra/b
         spr[noparse][[/noparse]10+i] := 1                                      ' set frqa/b
         
      p1 := long[noparse][[/noparse]pins_address][noparse][[/noparse]0]
      p2 := long[noparse][[/noparse]pins_address][noparse][[/noparse]1]
      dira[noparse][[/noparse]p1]~
      dira[noparse][[/noparse]p2]~
      
      repeat
         waitPEQ(0    , |< p1,0)          'wait for low state
         phsa~
         waitPEQ(|< p1, |< p1,0)          'wait for high state ie pulse start on Pin1
         waitPEQ(0      , |< p1,0)        'wait for low state i.e. pulse ended
         long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse]0] := phsa/uS
         
         waitPEQ(0    , |< p2,0)          'wait for low state
         phsb~
         waitPEQ(|< p2, |< p2,0)          'wait for high state ie pulse start on Pin2
         waitPEQ(0    , |< p2,0)          'wait for low state i.e. pulse ended
         long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse]1] := phsb/uS
     
    PUB Stop | i
        repeat i from 0 to 2
          if cog[noparse][[/noparse]i]
            cogstop(cog[noparse][[/noparse]i]~ -1)
    
    

    Post Edited (SamMishal) : 7/13/2009 2:17:59 AM GMT
  • SamMishalSamMishal Posts: 468
    edited 2009-07-13 02:21
    Hi Rich,



    I have changed the code a little since I posted it.....so please copy it again if you have
    copied before you got this message.



    I missed a few things.....oops....

    Sam
  • W9GFOW9GFO Posts: 4,010
    edited 2009-07-13 03:19
    Thanks Sam, I just got back but will surely study it closely later on.

    The idea for the wait clkfreq/200 was that the pulses will go high for between 500 and 2500 uS. The frequency is 50 hz.

    My intention was that if the signal was high it was to remain in the repeat loop until it went low. If it was low then start counting but not for more than 5 mS (3 mS would be better) because I wanted to count only one pulse each time through. If nothing was connected to that pin it would not go high, would not increment the counter and would not hang. It is important that it not wait for the high state for more than a few mS because the high state might not happen.

    I loaded the code, I get 1517 on the first three and 1516 on the other three pins, no matter what the input - even with no input. It's a step in the right direction.

    I'm gonna dig into it tomorrow.

    Rich H

    Post Edited (W9GFO) : 7/13/2009 4:39:48 AM GMT
  • SamMishalSamMishal Posts: 468
    edited 2009-07-13 10:09
    Hi Rich,

    OK....getting there....·the reason you are getting counts on the other ones is I think that you are not using a Pullup or pull down
    (pullup is usually better) resistors on the pins. The propeller does not have internal pullups/downs.

    When an input pin is floating the pin will get noise and usually a signal on a neighbouring pin will show up on the floating pin.

    What you need is a pullup resistor (10K) on the pins. Then the pins that are not connected will always have a
    high on them............................but then you have a problem with the code since it will hang...........

    Since each cog counts the first pin then the second you will get a problem since if either is not connected
    the cog will sit there forever wating (waitPQE) for the pin to go low and since you have a pull up it will not
    even if you had a pull down the next waitpeq is waiting for high so it will still hang.

    The problem is not with cogs that have both pins not connected since the cog will just sit there doing nothing
    and that does not matter since you are not using it. Just make sure you always Zero the pulsewidth before you
    start counting. Add these line before the repeat statement.
    ····· Long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse]0]~
    ····· Long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse]1]~

    This way you always know the pins are not connected since the corresponding pulsewidth pair of values will be zero.

    The real problem is with a cog that has one of the pins connnected but not the other.

    One solution is to connect the other pin to the same signal. this way both pair will count the same signal.
    So always either connect both pair to different signals or to the same signal.

    Another (better) solution is to use this code instead.....make sure you have pullup resistors.
    The red text is new stuff.
    VAR
      byte cog[noparse][[/noparse] 3]
      long stack[noparse][[/noparse]60]
      long uS[color=red], WaitTime[/color]
     
    PUB Start (pins_array_address, pulsewidth_array_address)|i
      uS := clkfreq/1_000_000
      [color=red]WaitTime := clkfreq/200   'choose this time carefully[/color]
      Stop   'call the stop method to stop cogs tha may be already started
      repeat i from 0 to 2
         cog[noparse][[/noparse]i] := cognew(readPins(@long[noparse][[/noparse]pins_array_address][noparse][[/noparse]i*2], @long[noparse][[/noparse]pulsewidth_array_address][noparse][[/noparse]i*2]), @ stack[noparse][[/noparse]i*20]) + 1
     
    PUB readPins (pins_address, pulsewidth_address)| i,p1,p2
      repeat i from 0 to 1
         spr[noparse][[/noparse]8+i]  := %01000 << 26 + long[noparse][[/noparse]pins_address][noparse][[/noparse]i]   'set the mode and pin for ctra/b
         spr[noparse][[/noparse]10+i] := 1                                      ' set frqa/b
         
      p1 := long[noparse][[/noparse]pins_address][noparse][[/noparse]0]
      p2 := long[noparse][[/noparse]pins_address][noparse][[/noparse]1]
      dira[noparse][[/noparse]p1]~
      dira[noparse][[/noparse]p2]~
      [color=red]long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse]0]~          'add these lines to the code to make sure the count is zeroed
      long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse]1]~
    [/color]  repeat
         [color=red]if not WaitSignalState(0,P1,WaitTime)    'assuming you have pullups[/color] 
            phsa~
            waitPEQ(|< p1, |< p1,0)       'wait for high state ie pulse start on Pin1
            waitPEQ(0   , |< p1,0)        'wait for low state i.e. pulse ended
            long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse]0] := phsa/uS
         
         [color=red]if not WaitSignalState(0,P2,WaitTime)    'assuming you have pullups[/color] 
            phsb~
            waitPEQ(|< p2, |< p2,0)       'wait for high state ie pulse start on Pin2
            waitPEQ(0 , |< p2,0)          'wait for low state i.e. pulse ended
            long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse]1] := phsb/uS
             
    [color=red]Pri WaitSignalState(State,PinNo,TimeOut):TimedOut|T
      T := TimeOut+cnt
      repeat until ina[noparse][[/noparse]PinNo] == State or cnt => T
      if Cnt => T
         TimedOut := True
    [/color]      
    PUB Stop | i
        repeat i from 0 to 2
          if cog[noparse][[/noparse]i]
            cogstop(cog[noparse][[/noparse]i]~ -1)
     
    

    If you use the WaitSignalState subroutine to replace the other WaitPEQ statements you will not get an accurate
    pulsewidth measurement due to the time it takes the code to execute....with a 50 Hz signal it does not matter much
    since the propeller is VERY fast but waitpeq is the best way to go for more accuracy and to be able to capture
    faster frequencies.

    Samuel


    Post Edited (SamMishal) : 7/13/2009 10:21:17 AM GMT
  • W9GFOW9GFO Posts: 4,010
    edited 2009-07-13 20:39
    Hmmm, needing pull up/pull down resistors completely escaped me. I have 4k7 ohm resistors on each pin to the header but that doesn't help with floating eh? Pull ups would be easier for me to add but I think pull downs are more appropriate. These six pins that I am using are the same six which are otherwise used for servo outputs. If they are pulled high I think that would interfere with the servo signals. If I pulled them low with a high value resistor that should allow outgoing servo pulses to do their thing. Would a 470 k ohm resistor be too high for a pull down?

    I ran the above code, without adding any resistors and the results were identical to last time. The first 2 pins are getting a solid signal, the rest are floating. Shouldn't at least the first two pins be reporting the correct pulse width even though the rest of the pins are floating?

    Rich H
  • SamMishalSamMishal Posts: 468
    edited 2009-07-13 21:56
    W9GFO said...
    ·but I think pull downs are more appropriate. These six pins that I am using are the same six which are otherwise used for servo outputs. If they are pulled high I think that would interfere with the servo signals.
    Yes I should say so....pull downs would be better in this case.....but watch out for the logic of the operation...
    it waits for low then high then low......if there is no signal then the low will be there anyway due to the pull down.....

    So you will have to wait for low using WaitPEQ since that is guranteed....but then use the subroutine WaitSignalState using
    the high state then wait for low using WaitPEQ......I will show code below.
    W9GFO said...
    ·Would a 470 k ohm resistor be too high for a pull down?
    I don't think so...I always use 10K....but 470K should be fine.....
    W9GFO said...

    I ran the above code, without adding any resistors and the results were identical to last time. The first 2 pins are getting a solid signal, the rest are floating. Shouldn't at least the first two pins be reporting the correct pulse width even though the rest of the pins are floating?
    So you are saying that you connected signals to the first two pins and left the others unconnected?
    And you are saying that they did not report the correct pulse width?....what were the results?


    Anyway I think you should put the pull downs and then try again.....replace the lines of the repeat block with the following
    (since now you have pull downs)

      repeat
         waitPEQ(0 , |< p1,0)                     'wait for low state
         phsa~
         if not WaitSignalState(1,P1,WaitTime)    'wait for high with time out assuming you have pulldowns 
            waitPEQ(0   , |< p1,0)                'wait for low state i.e. pulse ended
            long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse]0] := phsa/uS
         
         waitPEQ(0   , |< p2,0)                   'wait for low state
         phsb~
         if not WaitSignalState(1,P2,WaitTime)    'wait for high with time out assuming you have pulldowns 
            waitPEQ(0   , |< p2,0)                'wait for low state i.e. pulse ended
            long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse]1] := phsb/uS
    
    

    ·Samuel
    ·
  • W9GFOW9GFO Posts: 4,010
    edited 2009-07-14 05:45
    Ok, I decided to take a step back and get the function working on one cog before trying to get all three going. I started a fresh program, all in one object.

    The code below is working quite nicely. I had to add (3) to the pulsewidth value to make it correct.

    Interestingly enough, if I disconnect one of the leads - the last reading remains. If it is started up with a lead disconnected it will read zero. That's good news for me, I really didn't want to have to add pull downs. However if there is a cable connected - which doesn't have the other end connected - then the readings go crazy. Touching the pin also makes the reading erratic, even coming close to touching it does ~ 2mm away. Since it seems to be steady otherwise, I don't think I'll bother with the pull downs at this point.

    Now to add the other four counters...


    PUB main  | p1,p2
    
      uS := clkfreq/1_000_000
      WaitTime := uS * 20000
    
      ctra[noparse][[/noparse]31..26] := %01000                     ' set mode to pos detector
      ctra[noparse][[/noparse]5..0] := pin[noparse][[/noparse] 1]                            ' Pin 1
    
      ctrb[noparse][[/noparse]31..26] := %01000
      ctrb[noparse][[/noparse]5..0] := pin[noparse][[/noparse] 2]                            ' Pin 2
    
      frqa := 1
      frqb := 1
    
      dira[noparse][[/noparse]pin[noparse][[/noparse] 1]]~
      dira[noparse][[/noparse]pin[noparse][[/noparse] 2]]~
    
      p1 := pin[noparse][[/noparse] 1]
      p2 := pin[noparse][[/noparse] 2]
    
      LCD.str(string("Counters set! "))
      waitcnt(clkfreq + cnt)
      LCD.clear
    
      repeat
         waitPEQ(0 , |< p1,0)                     'wait for low state
         phsa~
         if not WaitSignalState(1,P1,WaitTime)    'wait for high with time out assuming you have pulldowns
            waitPEQ(0   , |< p1,0)                'wait for low state i.e. pulse ended
            pulsewidth[noparse][[/noparse]0] := phsa/uS  + 3
    
         waitPEQ(0   , |< p2,0)                   'wait for low state
         phsb~
         if not WaitSignalState(1,P2,WaitTime)    'wait for high with time out assuming you have pulldowns
            waitPEQ(0   , |< p2,0)                'wait for low state i.e. pulse ended
            pulsewidth := phsb/uS  + 3
    
         debug(pulsewidth[noparse][[/noparse] 0], 4, 1, false, 4, 0)                   '(value, X, Y, decimal?, digits, places)
         debug(pulsewidth[noparse][[/noparse] 1], 10, 1, false, 4, 0)           
    
    Pri WaitSignalState(State,PinNo,TimeOut):TimedOut|T
      T := TimeOut+cnt
      repeat until ina[noparse][[/noparse]PinNo] == State or cnt => T
      if Cnt => T
         TimedOut := True
    
    



    Rich H

    Post Edited (W9GFO) : 7/14/2009 6:08:27 AM GMT
  • W9GFOW9GFO Posts: 4,010
    edited 2009-07-14 07:31
    This is weird. It works right up to the point where it displays "Cogs started" then just stays there. The display doesn't clear and it doesn't display the next string.

    Whoa... wait a minute! After almost two minutes the screen clears, then 50 seconds later "No worky!!!" appears. Then, almost two more minutes pass and the "N" vanishes... Another minute goes by and the "o" disappears... Another couple goes by and I get a zero in place of the "w"...... At the 12 minute mark I get another zero in place of the 2nd "!"... zzzzzzzzzzzzzzzzz

    I'm at 16 minutes into this program and the 3rd zero just showed up. That would be the third debug in the repeat loop.

    Seems like something funny going on in the LCD object but I haven't even opened that file in weeks. Nope, I loaded another program that uses that object and it is fine.

    It's like the cnt has to rollover before it executes each instruction. It took nearly thirty minutes to make it's way through the repeat loop for the first time.

    The entire code is below for your amusement.

    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
    
    VAR
      long  pulsewidth[noparse][[/noparse]6]
      long uS, WaitTime
      long stack[noparse][[/noparse]60]
      byte cog
    DAT
      pin  LONG 1, 2, 3, 4, 5, 6
    
    OBJ
      LCD        : "LCD_16X2_8BIT"
    
    PUB Init
    
      LCD.start
      waitcnt(clkfreq/4 + cnt)
      LCD.clear
      LCD.str(string("RX test v 0.2 "))
      waitcnt(clkfreq + cnt)
      LCD.clear
    
      main
    
    PUB main  | i
    
      uS := clkfreq/1_000_000
      WaitTime := uS * 20000
    
      Stop   'call the stop method to stop cogs that may be already started
      repeat i from 0 to 2
         cog[noparse][[/noparse] i] := cognew(readPins(@long[noparse][[/noparse]pin][noparse][[/noparse]i*2], @long[noparse][[/noparse]pulsewidth][noparse][[/noparse]i*2]), @ stack[noparse][[/noparse]i*20]) + 1
    
      LCD.str(string("Cogs started"))   ' ********** here is where it slows waaaaaaay down **************
      waitcnt(clkfreq + cnt)
      LCD.clear
      LCD.str(string("No worky!!!!"))
    
      repeat
        debug(pulsewidth[noparse][[/noparse] 0], 4, 1, false, 4, 0)                   '(value, X, Y, decimal?, digits, places)
        debug(pulsewidth[noparse][[/noparse] 1], 10, 1, false, 4, 0)
        debug(pulsewidth[noparse][[/noparse] 2], 16, 1, false, 4, 0)
        debug(pulsewidth[noparse][[/noparse] 3], 4, 2, false, 4, 0)
        debug(pulsewidth[noparse][[/noparse] 4], 10, 2, false, 4, 0)
        debug(pulsewidth[noparse][[/noparse] 5], 16, 2, false, 4, 0)
    
    PUB readPins (pins_address, pulsewidth_address)| i,p1,p2
    
      repeat i from 0 to 1
         spr[noparse][[/noparse]8+i]  := %01000 << 26 + long[noparse][[/noparse]pins_address][noparse][[/noparse] i]   'set the mode and pin for ctra/b
         spr[noparse][[/noparse]10+i] := 1                                      ' set frqa/b
    
      p1 := long[noparse][[/noparse]pins_address][noparse][[/noparse] 0]
      p2 := long[noparse][[/noparse]pins_address][noparse][[/noparse] 1]
      dira[noparse][[/noparse]p1]~
      dira[noparse][[/noparse]p2]~
      long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse] 0]~          'add these lines to the code to make sure the count is zeroed
      long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse] 1]~
      repeat
         waitPEQ(0 , |< p1,0)                     'wait for low state
         phsa~
         if not WaitSignalState(1,P1,WaitTime)    'wait for high with time out assuming you have pulldowns
            waitPEQ(0   , |< p1,0)                'wait for low state i.e. pulse ended
            long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse] 0] := phsa/uS
    
         waitPEQ(0   , |< p2,0)                   'wait for low state
         phsb~
         if not WaitSignalState(1,P2,WaitTime)    'wait for high with time out assuming you have pulldowns
            waitPEQ(0   , |< p2,0)                'wait for low state i.e. pulse ended
            long[noparse][[/noparse]pulsewidth_address][noparse][[/noparse] 1] := phsb/uS
    
    
    PUB Stop | i
        repeat i from 0 to 2
          if cog[noparse][[/noparse] i]
            cogstop(cog[noparse][[/noparse] i]~ -1)
    
    Pri WaitSignalState(State,PinNo,TimeOut):TimedOut|T
      T := TimeOut+cnt
      repeat until ina[noparse][[/noparse]PinNo] == State or cnt => T
      if Cnt => T
         TimedOut := True
    
    PUB debug(value, X, Y, dec, digits, places)  | divisor, number, spaces               ' uS, 1, 12 true, 3
    
        divisor := 1
        number := 10
    
        if dec
    
          repeat places
             divisor *= 10                           ' calculate divisor based upon decimal places
    
          repeat digits - 1
            IF value/divisor > number -1             ' figure out how many digits are in number
              x--                                    ' move x left to accomodate number if needed - keeping decimal in the same place
            number *= 10                             ' digits must be high enough to handle largest possible number or else number will get
                                                     ' shifted when printed
    
          LCD.move(X, Y)                             ' Position Cursor
          LCD.dec(value / divisor)                   ' Print Whole Part
          LCD.str(string("."))                       ' Print Decimal Point
    
          number := 10
          repeat places - 1
    
            IF value//divisor < divisor/number
              LCD.dec (0)
            number *= 10
    
          LCD.dec (value//divisor)
    
        else
          spaces := 1
    
          repeat digits - 1
            IF value > number -1
              spaces ++
            number *= 10
          LCD.move(X - digits + 1, Y)
          repeat digits - spaces
            LCD.str(string(" "))
          LCD.dec(value)
    

    Post Edited (W9GFO) : 7/14/2009 7:45:05 AM GMT
  • SamMishalSamMishal Posts: 468
    edited 2009-07-14 09:28
    W9GFO said...
    Ok, I decided to take a step back and get the function working on one cog before trying to get all three going. I started a fresh program, all in one object.
    Always a goood idea....start small.....build up gradually....debug each step along the way
    W9GFO said...
    The code below is working quite nicely. I had to add (3) to the pulsewidth value to make it correct.
    ·That is because the time it takes the SPIN code to do its work....also the signal itself may not be as accurate as you
    ·think if you have rounded values as you normally have to do with the NCO modes.
    W9GFO said...
    Interestingly enough, if I disconnect one of the leads - the last reading remains. If it is started up with a lead disconnected it will read zero.
    ·The setting of the pulsewidth fields to zero happens only once outside of the repeat loop and thus if it reads for a while and then you disconnect the
    ·signal the clearing will not happen again since it is now inside of the repeat loop and will never clear the pulsewidths again.
    W9GFO said...
    Interestingly enough, if I disconnect one of the leads - the last reading remains. If it is started up with a lead disconnected it will read zero. That's good news for me, I really didn't want to have to add pull downs. However if there is a cable connected - which doesn't have the other end connected - then the readings go crazy. Touching the pin also makes the reading erratic, even coming close to touching it does ~ 2mm away. Since it seems to be steady otherwise, I don't think I'll bother with the pull downs at this point.
    ·What you are describing is a CLASSIC situation of what happens when you have a floating input. The capacitance of the extra lead and your fingers
    ·can make it read 1 and zeros.....this is why you REALLY should have pullup/down resistors.....

    But at least you have demonstrated that the code works and that the PRINCIPLE of the algorithm works and counts correctly.

    .....now to go on to the weird stuff you are getting below......I will look at it later but I now have to go out......

    For now try the program without the call to Stop....see what happens....Let me know


    Sam


    Post Edited (SamMishal) : 7/14/2009 9:43:58 AM GMT
  • SamMishalSamMishal Posts: 468
    edited 2009-07-14 11:14
    W9GFO said...
    PUB main  | i
    
      uS := clkfreq/1_000_000
      WaitTime := uS * 20000
    
      Stop   'call the stop method to stop cogs that may be already started
      repeat i from 0 to 2
         cog[noparse][[/noparse] i] := cognew(readPins[color=red](@long[noparse][[/noparse]pin][noparse][[/noparse]i*2], @long[noparse][[/noparse]pulsewidth][noparse][[/noparse]i*2][/color]), @ stack[noparse][[/noparse]i*20]) + 1
    
      LCD.str(string("Cogs started"))   ' ********** here is where it slows waaaaaaay down **************
      waitcnt(clkfreq + cnt)
      LCD.clear
    
    

    The problem is the line marked in red......
    You are not any more passing the address of the address......so the line should now be like this
    ···· cog[noparse][[/noparse]i] := cognew(readPins(@pin[noparse][[/noparse]i*2], @pulsewidth[noparse][[/noparse]i*2]), @ stack[noparse][[/noparse]i*20]) + 1

    The previous format was if you were passing the address of pin and pulsewidth to the "main" method........since now you are
    not doing that and main has access to the arrays then you pass each cog the address of the pairs directly.......

    Try the change and see....

    The reason for the delays you were seeing is that in fact the whole program was being reset continously
    and was being restarted all over again......that is because ......well too complicated to explain....but it is due
    to the wrong address was being passed to the cogs.....


    Sam


    Post Edited (SamMishal) : 7/14/2009 11:29:13 AM GMT
  • W9GFOW9GFO Posts: 4,010
    edited 2009-07-14 16:13
    Ahhh, much better now. Thanks.

    Still confused about the slow behavior, it didn't appear to be resetting...

    I'm heading out now, later on I want to add some code to zero the pulsewidths if they are out of range (or with pulldowns, a wire is disconnected) and make this into a separate object. I'll refer to previous code to see if I can get the "@Long" in the right places.

    Rich H
  • W9GFOW9GFO Posts: 4,010
    edited 2009-07-15 20:29
    Hey Sam, I was going to PM you with this but I can't send attachments in a PM.

    Here is the RX object and a "RX_demo" to show how it works.

    Thanks for all your help!

    The problem I had before where it would show 1516 and 1517 turned out to be because the servo32 object was still sending pulses to those pins. I've learned that the servo 32 object isn't perfect in that the pulses it sends out are not exactly the same on all pins, even when they are supposed to be.

    I added a few lines of code to deal with the floating inputs when they are not connected.

    I'd like to upload this to the Obex, take a look at it and see if I have acknowledged you properly.

    Thanks,

    Rich H
  • SamMishalSamMishal Posts: 468
    edited 2009-07-15 20:51
    W9GFO said...
    Thanks for all your help!


    I'd like to upload this to the Obex, take a look at it and see if I have acknowledged you properly.

    Hi Rich,

    You are very welcome and THANKS A LOT for acknowledging me, you did not have to do that.....I am extremely· happy to have been
    of help....just repaying my debt to others who have helped me.....

    I am glad it is all working well.

    It seems like an interesting and useful tool, you have done good work!

    Best wishes

    Samuel
    ·
Sign In or Register to comment.