Shop OBEX P1 Docs P2 Docs Learn Events
Propeller programming help for project — Parallax Forums

Propeller programming help for project

raleigh747raleigh747 Posts: 13
edited 2010-05-05 00:13 in Propeller 1
Howdy all. I'm pretty new to Propeller and programing in general. I have a school project in which we have to design, build and program a robot to autonomously move around on a board and determine the heights of 20 dhow rods. The rods range from 50 mm tall to 250 mm at 10 mm and no height is used more than once (Yes, I know that means there are 21 possible heights but I am simply relaying the rules). My team and I have decided to use 40 whiskers (20 per side of our robot) to accomplish this task. 20 whiskers will be connected to a single 40 pin DIP Propeller chip and should be able to determine the heights of any rod.

Here is my current problem.

In my current code, I'm running an IF statement that checks to see if the lowest whisker has contacted the rod. Until it has, nothing is done. If the lowest whisker comes into to contact, the program checks all the whiskers above it. The code then takes the number location of the highest pin that's in contact and converts it into the corresponding height. An issue arising from this is that not all the whiskers may contact at the same time meaning a single run of the line of may not yield the right value. So, I will have the code be repeated several times to make sure that the correct height is recorded. What I can't figure out how to do is make my value an array and then take the greatest value recorded in that array as the value.

Basically, I want to record a height for a1 through a500. Then I want to take the maximum height that was recorded and assign it to a.

Here's my current code:

CON

  _clkmode      = xtal1 + pll16x                                   'Feedback and PLL multiplier
  _xinfreq      = 5_000_000                                        'External oscillator = 5 MHz

  sensors_start = 8                                                'Define lowest whisker port
  sensors_end   = 15                                               'Define highest whisker port

OBJ

pst:"Parallax Serial Terminal"                                     'Start Terminal for visual output

  
PUB  WhiskerTest | a,b,c,d,e                                       'Title and variable defintion of a through e

pst.start(9600)                                                    'Define Terminal communication rate

repeat 
  repeat 500                                                       'Start loop for "tree a"
   if ina[noparse][[/noparse]8] == 0                                                  'If whisker on Port 8 contacts tree, begin whisker check             
    a:= (>|(ina[noparse][[/noparse]sensors_end..sensors_start]^$ff)*10+40)            'Variable a is equal to the highest port value multipled by 10 plus 40
   else                                                            'If whisker on Port 8 does not come into contact,
    a:= 0                                                          'a is 0 and do not check reamining whiskers
                                                                   'Port value:  Port 8 = 1, Port 15 = 8
  pst.dec(a)                                                       'Define display units of a in Terminal visual window
  pst.newline



Eventually, I need to generate a table where I can say Location 1.4 (column and row designation) corresponds with a (my rod height)

Thanks guys for helping with posting code. That's a new one on me.

Post Edited (raleigh747) : 4/11/2010 4:12:03 PM GMT

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2010-04-11 04:42
    Use the [noparse][[/noparse] code ] and [noparse][[/noparse] /code ] markers (without the extra spaces) to delimit your code. This will keep the indentation, but other markers in square brackets may be interpreted by the forum software, in particular [noparse][[/noparse] i ], but also some others.

    You can always include extra spaces after the opening square bracket to disable this interpretation.
  • ElectricAyeElectricAye Posts: 4,561
    edited 2010-04-11 04:44
    To post your code, you need to paste it between the following tags except take out ALL the spaces that I've put inside the brackets:

    [noparse][[/noparse] code ]

    [noparse][[/noparse] / code ]

    By doing that, your code will look like this, with all indentations preserved for eternity.
    



    I hope that helps.
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-04-11 09:02
    Why don't you check all inputs in parallel?

    chkval := ina[noparse][[/noparse] sensor_start .. sensor_end ]

    This stores the state of the input in chkval, moving bit sensor_start from ina to bit 0 of chkval ...
    So chkval has a value between 2 to the power of 0 to 2 to the power of (sensor_end-sensor_start) - 1.
    Now you can use a list of expected values and do a lookdown. Lookdown will return the index of chkval in the list.
    The list would be:
    %00000000, %00000001, %00000011, %00000111 .....
  • Cluso99Cluso99 Posts: 18,069
    edited 2010-04-11 10:10
    Your inputs are P8..P15 so as others have said you can read all in one step.

    Here is a simple way to start with... Check it works and then you can simplify things.
      whiskers := ina[noparse][[/noparse]15..8]       'bits 7..0 = P15..P8
      whiskers := whiskers ^ $FF   'invert to 1=active (because you indicated 0=sensed)
     
    'now you have 8 bits with the top bit the highest bit so this is good...
    'so you can decode as follows...
     
      if (whiskers => 128)
        a := 8
      elseif (whiskers => 64)
        a := 7
      elseif (whiskers => 32)
        a := 6
      elseif (whiskers => 16)
        a := 5
      elseif (whiskers => 8)
        a := 4
      elseif (whiskers => 4)
        a := 3
      elseif (whiskers => 2)
        a := 2
      elseif (whiskers => 1)
        a := 1
      else
        a := 0
     
    'now you can multiply a by the value of each increment (i.e. *10)
     
      a := a * 10                   
    
    




    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Links to other interesting threads:

    · Home of the MultiBladeProps: TriBlade,·RamBlade,·SixBlade, website
    · Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
    · Prop Tools under Development or Completed (Index)
    · Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) ZiCog (Z80) , MoCog (6809)·
    · Prop OS: SphinxOS·, PropDos , PropCmd··· Search the Propeller forums·(uses advanced Google search)
    My cruising website is: ·www.bluemagic.biz·· MultiBlade Props: www.cluso.bluemagic.biz
  • raleigh747raleigh747 Posts: 13
    edited 2010-04-11 16:23
    The line:

    a:= (>|(ina[noparse][[/noparse]sensors_end..sensors_start]^$ff)*10+40)

    Looks at all the inputs at once and finds the highest bit that is a 0 (because the whiskers ground the input). It then multiplies the pin number (so if 8 was the lowest pin with a 0, it would be converted to a 1) by 10 and adds 40 to get the height of the rod (for this example, it would be 50). So it currently checks all the whiskers in a single step. I'm just afraid that not all the whiskers will hit at once and the wrong height will be recorded.

    @Cluso99, I was going to use a bunch of if statements until I got a little help and found the code I'm currently using. So I think they do the same thing.

    @MagIO2, that looks like another way to record the height that I didn't think of. But what I need, is to define an array(i.e. a1-a500, fill it (using the repeat command or something else), and then pick out the maximum value of that array to be recorded as my height (variable "a" for table referencing).
  • Cluso99Cluso99 Posts: 18,069
    edited 2010-04-11 17:44
    @raleigh747: My apologies. I didn't fully read your question.

    var
      long ax[noparse][[/noparse]500]  'define a long array length 500 i.e ax[noparse][[/noparse]0] .. ax[noparse][[/noparse]499]
     
    PUB...
      i := 0
      .....
     
      ax[noparse][[/noparse]i] := ....
      i++
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Links to other interesting threads:

    · Home of the MultiBladeProps: TriBlade,·RamBlade,·SixBlade, website
    · Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
    · Prop Tools under Development or Completed (Index)
    · Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) ZiCog (Z80) , MoCog (6809)·
    · Prop OS: SphinxOS·, PropDos , PropCmd··· Search the Propeller forums·(uses advanced Google search)
    My cruising website is: ·www.bluemagic.biz·· MultiBlade Props: www.cluso.bluemagic.biz
  • kuronekokuroneko Posts: 3,623
    edited 2010-04-12 00:35
    raleigh747 said...
    But what I need, is to define an array(i.e. a1-a500, fill it (using the repeat command or something else), and then pick out the maximum value of that array to be recorded as my height (variable "a" for table referencing).
    Why don't you record the maximum while you read the values (check the #> and <# operators)? This way you save memory and time.
  • raleigh747raleigh747 Posts: 13
    edited 2010-04-12 03:32
    That's a great idea. I'm just not sure how I'm going to integrate that into the program.
  • kuronekokuroneko Posts: 3,623
    edited 2010-04-12 04:11
    raleigh747 said...
    That's a great idea. I'm just not sure how I'm going to integrate that into the program.
    This will measure (as fast as possible) count times and report the maximum value. You might want to add a delay if necessary.

    PRI measureAndReport(count)
    
      repeat count
        result #>= (>|(ina[noparse][[/noparse]sensors_end..sensors_start]^$ff)*10+40)
    
  • raleigh747raleigh747 Posts: 13
    edited 2010-04-13 03:30
    Kuroneko, do I insert that section of code before my public? Do I still need what I currently have written in the Public section or will that need to change? Can I assign result to a specific variable I can call later or does your code act like a subroutine?

    As you can see, I'm pretty lost...
  • kuronekokuroneko Posts: 3,623
    edited 2010-04-13 03:44
    This should do. You only update a (manually initialised to 0) if the whiskers report a higher value and as long as the lowest whisker has contact. Also, to avoid issues later I'd suggest replacing ina[noparse][[/noparse]8] with ina[noparse][[/noparse]sensors_start].

    repeat 
      a:= 0                                                       'locals are not pre-cleared
      repeat 500                                                  'Start loop for "tree a"
       if ina[noparse][[/noparse]8] == 0                                             'If whisker on Port 8 contacts tree, begin whisker check             
        a#>= (>|(ina[noparse][[/noparse]sensors_end..sensors_start]^$ff)*10+40)      'Variable a is equal to the highest port value multipled by 10 plus 40
       else                                                       'If whisker on Port 8 does not come into contact,
        a:= 0                                                     'a is 0 and do not check reamining whiskers
                                                                  'Port value:  Port 8 = 1, Port 15 = 8
      pst.dec(a)                                                  'Define display units of a in Terminal visual window
      pst.newline
    


    One more thing, you probably only want to start the 500-cycle scan loop IF the lowest whisker has contact.

    Post Edited (kuroneko) : 4/13/2010 3:50:23 AM GMT
  • raleigh747raleigh747 Posts: 13
    edited 2010-04-20 18:21
    Sorry it has taken me so long to reply. I've been busy with a bunch of school stuff.

    Anyways, Kuroneko, I did get that code to work. I was having problems with it displaying the values in the Terminal but I figured it out.

    Here's my code so far:

    CON
    
      _clkmode      = xtal1 + pll16x                                   'Feedback and PLL multiplier
      _xinfreq      = 5_000_000                                        'External oscillator = 5 MHz
    
      sensors_start = 8                                                'Define lowest whisker port
      sensors_end   = 15                                               'Define highest whisker port
      
    OBJ
    
    pst:"Parallax Serial Terminal"                                     'Start Terminal for visual output
      
    
    PUB WhiskerTest|a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t
    
    pst.start(9600) 
                                                           
    repeat until a#>=0                                                 'Repeat code segement until variable has a value > 0                                                   
      if ina[noparse][[/noparse]sensors_start] == 0                                       'If pin[noparse][[/noparse]sensors_start] is grounded (= 0)                                                       
          repeat 10_000                                                'Repeat whisker check 10,000 times
            a#>= (>|(ina[noparse][[/noparse]sensors_end..sensors_start]^$ff)*10+40)       'Assign lowest pin a value of 1 and the highest pin 20
                                                                       'Multiple pin value by 10 and add 40 for height
                                                                       'Record maximum value of 10,000 trials as variable             
          pst.dec(a)                                                   'Dsiplay variable
          pst.newline                                                  'Start a new line in display
      else                                                             'If pin[noparse][[/noparse]sensors_start] is not grounded
        a:= 0                                                          'Variable = 0
    
    if a#>0                                                            'See if previous variable was detected
      repeat until b#>=0                                               'Repeat code segement until variable has a value > 0                                                   
        if ina[noparse][[/noparse]sensors_start] == 0                                     'If pin[noparse][[/noparse]sensors_start] is grounded (= 0)                                                       
          repeat 10_000                                                'Repeat whisker check 10,000 times
            b#>= (>|(ina[noparse][[/noparse]sensors_end..sensors_start]^$ff)*10+40)       'Assign lowest pin a value of 1 and the highest pin 20
                                                                       'Multiple pin value by 10 and add 40 for height
                                                                       'Record maximum value of 10,000 trials as variable             
          pst.dec(b)                                                   'Dsiplay variable
          pst.newline                                                  'Start a new line in display
        else                                                           'If pin[noparse][[/noparse]sensors_start] is not grounded
          b:= 0
    
    



    So basically, it sees if the pin designated as sensors_start is grounded, checks all the whiskers if it is and reports the maximum value recorded for a. Then it goes to b only if a is not 0 and repeats the process until b is finished and so on all the way to t (20 heights).

    Now I need to figure out how to add a slight delay in the measuring (currently, my repeat is acting as my delay but they may cause memory problems) and build a table. I need to display a row x column positon (which I figured I could assign manually) with the correspondibng height. Then, I've got to transfer the table via bluetooth to a computer. So far, I have no idea how to do any of this. Any thoughts?
  • Mike GreenMike Green Posts: 23,101
    edited 2010-04-20 18:54
    1) Adding delays is easy with WAITCNT. Read the description of this in the Propeller Manual. Basically, it causes the program to wait until the system clock counter (CNT) reaches a specified value. For example, if you want a 100ms delay, you can calculate how many system clock cycles it takes and add that to the current value of CNT. CLKFREQ is the number of system clock cycles in one second. CLKFREQ/10 is the number of system clock cycles in 100ms, so you'd do "WAITCNT(CLKFREQ/10 + CNT)" to wait 100ms.

    2) Spin (using the Propeller Tool) only has single subscripts. You have to calculate the subscript from row and column. If you have "rowSize" rows and "colSize" columns, you can use "x * rowSize + y" as your subscript for row "x" and column "y". You'd declare your array as having "rowSize * colSize" elements.

    3) You'd use one of the Easy Bluetooth adapters for the Bluetooth serial link to your PC. There's documentation and sample code available. Once initialized, this looks just like a wired serial port between the Propeller and the PC. On the Propeller side, you can use any serial driver (there are several in the Object Exchange and FullDuplexSerial comes with the Propeller Tool). On the PC side, you'll need to write your own program or use some kind of existing serial data capture program. You could probably use PLX-DAQ or StampPlot Pro which are available under the Stamp Downloads link on the Downloads webpage on Parallax's website.
  • raleigh747raleigh747 Posts: 13
    edited 2010-04-22 18:14
    I appreciate your help Mr. Green, but I have some questions and comments:

    My department is supplying some bluetooth modules for use in transmitting but I am not sure which one they will have for us. Once I know, I will see what the device's manual can help me with.

    As for the delay, I'm not quite follwoing your calculations Mr. Green. Are you saying that no matter what, if I divide CLKFREQ by 10, I will wait 100ms? If I'm following the Propeller manual right, when xinfreq is set to 5 MHz and my clkmode has a 16x in it, my clkfreq should be 80 MHz. So wouldn't my wait be 800 ms?

    For the table, I have to display my data in a row, column table, but I know my rod location already. Essentially, We know where each rod is and simply need to associate a rod height with each location. For instance, at location 1,4 (it has to be displayed as row, column corresponding to the test field) I will measure my rod height to be 200 mm tall. So I need to display the text "1,4" in the lcoation cell and to the right the measured height which will be "a," the first height recorded by the program I posted previously.

    If I have 20 rows (rowSize) and 2 columns (colSize), my first cell in the table (1,1) will have a subscript of 21 (22 for my height cell), right? So do I need to have 21 = "1,4" my rod's grid location and and have 22 = "a" my rod height? Then, how would I actually display it in table format such that "1,4" and 240 are the only values displayed in their respective cells?
  • kuronekokuroneko Posts: 3,623
    edited 2010-04-23 01:20
    raleigh747 said...
    Are you saying that no matter what, if I divide CLKFREQ by 10, I will wait 100ms? If I'm following the Propeller manual right, when xinfreq is set to 5 MHz and my clkmode has a 16x in it, my clkfreq should be 80 MHz. So wouldn't my wait be 800 ms?
    The important bit here is that you wait clock cycles (check the manual re: waitcnt). Meaning at 80MHz you'd wait for 8_000_000 clock cycles, each lasting 12.5ns ...
  • raleigh747raleigh747 Posts: 13
    edited 2010-04-29 00:19
    Alright, I got it now. So if use

    waitcnt(clkfreq*2+cnt)
    



    I will wait 2 seconds. is each cycle always 12.5ns?

    Also, I figured out how I will display my measurements. Thanks for the help guys! I will post again if I have any problems.
  • kuronekokuroneko Posts: 3,623
    edited 2010-04-29 00:23
    raleigh747 said...
    Alright, I got it now. So if use

    waitcnt(clkfreq*2+cnt)
    


    I will wait 2 seconds. is each cycle always 12.5ns?
    Yes and no. If you run at 20MHz then each cycle will be 50ns, however, waitcnt(clkfreq*2+cnt) will still wait 2 seconds (20_000_000*2*50ns).
  • Steph LindsaySteph Lindsay Posts: 767
    edited 2010-04-29 17:05
    raleigh747,

    You might find the "I/O and Timing" section of the Propeller Education Kit Labs: Fundamentals book helpful, starting on page 49. The PDF and sample code for this book are bundled in the Propeller Tool software· v1.2.7, you can open it from the Help menu.

    Best wishes for your project!

    -Steph
  • raleigh747raleigh747 Posts: 13
    edited 2010-05-04 06:30
    It seems I have encountered another, major problem. Here's the code:

    CON
    
      _clkmode      = xtal1 + pll16x                                   'Feedback and PLL multiplier
      _xinfreq      = 5_000_000                                        'External oscillator = 5 MHz
    
      sensors_start = 0                                                'Define lowest whisker port
      sensors_end   = 8                                               'Define highest whisker port
      
    OBJ
    
    pst:"Parallax Serial Terminal"                                     'Start Terminal for visual output
      
    
    PUB WhiskerTest|a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t
    
    pst.start(9600) 
                                                           
    repeat until a#>=0                                                 'Repeat code segement until variable has a value > 0                                                   
      if ina[noparse][[/noparse]sensors_start] == 0                                       'If pin[noparse][[/noparse]sensors_start] is grounded (= 0)                                                       
          repeat 10_000                                                'Repeat whisker check 10,000 times
            a#>= (>|(ina[noparse][[/noparse]sensors_start..sensors_end]^$ff)*10+40)       'Assign lowest pin a value of 1 and the highest pin 20
                                                                       'Multiple pin value by 10 and add 40 for height
                                                                       'Record maximum value of 10,000 trials as variable
      else                                                             'If pin[noparse][[/noparse]sensors_start] is not grounded
        a:= 0                                                          'Variable = 0
    
    if a#>0                                                            'See if previous variable was detected
      waitcnt(clkfreq*2+cnt)                                           'Delay whisker check by 2 seconds
      repeat until b#>=0                                               'Repeat code segement until variable has a value > 0                                                   
        if ina[noparse][[/noparse]sensors_start] == 0                                     'If pin[noparse][[/noparse]sensors_start] is grounded (= 0)                                                       
          repeat 10_000                                                'Repeat whisker check 10,000 times
            b#>= (>|(ina[noparse][[/noparse]sensors_end..sensors_start]^$ff)*10+40)       'Assign lowest pin a value of 1 and the highest pin 20
                                                                       'Multiple pin value by 10 and add 40 for height
                                                                       'Record maximum value of 10,000 trials as variable
        else                                                           'If pin[noparse][[/noparse]sensors_start] is not grounded
          b:= 0
    



    When I set sensors_start = 0 and sensors_end = 7, run the program and ground pin 0, the PST reports a value of 50. However, if I change sensors_end = 7 to 8, run and ground pin 0, the PST reports a value of 130. If I ground both pin 0 and 8, the PST reports a value of 50. I have no idea what is going on. Any thoughts?

    Note: If I set sensors_start = 8 and sensors_end = 15, run and ground pin 8, the PST reports a value of 50.
  • kuronekokuroneko Posts: 3,623
    edited 2010-05-04 06:56
    ' sensors_start pin grounded, others assumed to read high
    
    7..0: >| ($0FE ^ $FF) == >| $001 == 1, *10+40 ->  50
    8..0: >| ($1FE ^ $FF) == >| $101 == 9, *10+40 -> 130
    
  • raleigh747raleigh747 Posts: 13
    edited 2010-05-04 14:24
    Yeah, that's what is happening, except, I want to read low pins. When it looks at 8..0, pin 0 should be the only low pin and value of 50 should be determined, but that is not the case. For some reason it's counting pin 8 even though it's high and reporting a value of 130. But when pin 8 is grounded (low) it calculates a value of 50. I dunno why, but once the program has to look at more than 8 pins, it is giving me some crazy values.
  • kuronekokuroneko Posts: 3,623
    edited 2010-05-05 00:13
    What do you expect? Your make-pins-low-mask (^$FF) only covers 8 pins. If you want more you'd have to extend the mask (or generate it based on the start/end values).

    Post Edited (kuroneko) : 5/5/2010 12:18:36 AM GMT
Sign In or Register to comment.