Shop OBEX P1 Docs P2 Docs Learn Events
Spin questions — Parallax Forums

Spin questions

turbosupraturbosupra Posts: 1,088
edited 2010-06-13 04:50 in Propeller 1
As I'm trying to teach myself the syntax of spin, I figured I'd start with a basic project. If there is a basic example of different programs and code examples that I can look at, all in one pdf, please link me to it.




I'd like to get the framework of the necessities of a spin project (the very basic code) so I can see a template of what is needed for every project.

It appears that you need

CON
_clkmode
_xinfreq


to define your crystal and timing and any other constants


Then you need

VAR

to define any variables needed and reserve a memory address for them, depending on the variable type


and then you need

PUB Main (or multiple pubs)

to define public functions










With all of that being said, I want to have spin count 3 pulses within a third or half second and if it sees that, output a high to turn on a transistor for 1000 milliseconds, so here goes





CON

  _CLKMODE = XTAL1 + PLL16X
  _XINFREQ = 5_000_000

  quartersec_wait = 250         ' counts every 1/4 second
  thirdsec_wait = 333           ' counts every 1/3 second
  halfsec_wait = 500            ' counts every 1/2 second
  twothirdsec_wait = 667        ' counts every 2/3 second
  threequartersec_wait = 750    ' counts every 3/4 second
  fullsec_wait = 1000           ' counts every 1 second





OBJ
  'Reserved


PUB Main


dira[noparse][[/noparse]7] := 0                    ' sets the direction of pin 7 to an input 
ina[noparse][[/noparse]7]  := 1                    ' sets pin 7 to look for a greater than 1.65vDC signal
dira[noparse][[/noparse]8] := 1                    ' sets the direction of pin 8 to an output (may be redundant)
outa[noparse][[/noparse]8] := 1                    ' sets pin 8 to a high output to turn on a transistor



repeat
  if ina[noparse][[/noparse]7] == 1                 ' if pin 7's input is higher than 1.65vDC
    WaitCnt(ClkFreq / 1000 * thirdsec_wait + cnt)   ' wait a 1/3 of a second and poll input pin 7 again
    if ina[noparse][[/noparse]7] == 1               ' if pin 7's input is higher than 1.65vDC a second time
      WaitCnt(ClkFreq / 1000 * thirdsec_wait + cnt) ' wait a 1/3 of a second and poll input pin 7 again
      if ina[noparse][[/noparse]7] == 1             ' if pin 7's input is higher than 1.65vDC a third time
        outa[noparse][[/noparse]8] == 1            ' set output pin 8 to high
        WaitCnt(ClkFreq / 1000 * fulsec_wait + cnt) ' leave pin 8 set to high for a full second
        outa[noparse][[/noparse]8] == 0            ' reset output pin 8 to low






Post Edited (turbosupra) : 6/12/2010 12:09:53 AM GMT

Comments

  • ElectricAyeElectricAye Posts: 4,561
    edited 2010-06-11 22:19
    Check out the differences between = and ==, for example in your IF statements and assignment of values to variables.

    And look at :=, too.

    Post Edited (ElectricAye) : 6/11/2010 10:53:26 PM GMT
  • turbosupraturbosupra Posts: 1,088
    edited 2010-06-11 22:53
    Hi,

    As I understand it

    = is for equal in the CON code block
    == is for is equal to for a variable
    := is for equals when assigning a variable



    I tried to correct my code, did I do it correctly?



    ElectricAye said...
    Check out the differences between = and ==, for example in your IF statements and assignment of variables.

    And look at :=, too.
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2010-06-11 23:59
    your waitcnt's won't work as you likely expect them to. Usually I do this:
    waitcnt(clkfreq / 1000 * msWait + cnt)
    


    This will allow you to put in your constants as you have them.

    ClkFreq / 80000000 will always equate to 1 if you are running at 80MHz (which you are) or above, and 0 if less than 80MHz.
    Clkfreq always contains your current clock speed (80,000,000).

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    April, 2008: when I discovered the answers to all my micro-computational-botherations!

    Some of my objects:
    MCP3X0X ADC Driver - Programmable Schmitt inputs, frequency reading, and more!
    Simple Propeller-based Database - Making life easier and more readable for all your EEPROM storage needs.
    String Manipulation Library - Don't allow strings to be the bane of the Propeller, bend them to your will!
    Fast Inter-Propeller Comm - Fast communication between two propellers (1.37MB/s @100MHz)!
  • turbosupraturbosupra Posts: 1,088
    edited 2010-06-12 00:08
    Hi Bobb,

    Thank you for that, do you mind explaining why you use your method? Also did everything else look ok?


    Bobb Fwed said...
    your waitcnt's won't work as you likely expect them to. Usually I do this:
    waitcnt(clkfreq / 1000 * msWait + cnt)
    


    This will allow you to put in your constants as you have them.

    ClkFreq / 80000000 will always equate to 1 if you are running at 80MHz (which you are) or above, and 0 if less than 80MHz.
    Clkfreq always contains your current clock speed (80,000,000).
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2010-06-12 00:49
    As I said, clkfreq contains the propeller's current frequency.
    _CLKMODE = XTAL1 + PLL16X
      _XINFREQ = 5_000_000
    


    This sets what the propeller understands as the current frequency: _XINFREQ (your XTAL frequency) multiplied by the PLL16X mode. So 5MHz * 16 == 80,000,000Hz. This value is now what clkfreq contains.

    So if you do the math (from my waitcnt) clkfreq / 1000. This derives 80,000. Which happens to be exactly how many cycles the internal clock in the propeller must progress before 1 millisecond passes. So if you then multiply this value by the number of milliseconds you want to wait you have the total number of clock cycles the propeller needs to pause for. For example a quarter second is 250ms. So 250 * 80,000 == 20000000.

    Then you must add cnt which contains the current clock position. It is basically like saying "x milliseconds from now, stop the pause" if you leave out the cnt, it is unclear how long to pause for, it would depend on where the clock currently is. For now, all you need to know is waitcnt always must have + cnt at the end of the parameter (until you get into some advanced stuff).


    As for other things, OUTA's and DIRA's are just like variables (the are actually registers). So you store and access them the same as variables. So assigning 1 to OUTA[noparse][[/noparse]8] is done like this:
    OUTA[noparse][[/noparse]8] := 1
    

    You didn't do that correctly in your REPEAT loop.
    INA is a read-only register, so you cannot assign it (as you did). I will post below what I think you want (though I am unable to test it, you can do that for yourself).

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    April, 2008: when I discovered the answers to all my micro-computational-botherations!

    Some of my objects:
    MCP3X0X ADC Driver - Programmable Schmitt inputs, frequency reading, and more!
    Simple Propeller-based Database - Making life easier and more readable for all your EEPROM storage needs.
    String Manipulation Library - Don't allow strings to be the bane of the Propeller, bend them to your will!
    Fast Inter-Propeller Comm - Fast communication between two propellers (1.37MB/s @100MHz)!
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2010-06-12 00:58
    CON
    
      _CLKMODE = XTAL1 + PLL16X
      _XINFREQ = 5_000_000
    
      quartersec_wait = 250         ' counts every 1/4 second
      thirdsec_wait = 333           ' counts every 1/3 second
      halfsec_wait = 500            ' counts every 1/2 second
      twothirdsec_wait = 667        ' counts every 2/3 second
      threequartersec_wait = 750    ' counts every 3/4 second
      fullsec_wait = 1000           ' counts every 1 second
    
    
    PUB Main
    
    ''no need to set pin 7. by default it is set as an input
      'dira[noparse][[/noparse]7] := 0                    ' sets the direction of pin 7 to an input 
      'ina[noparse][[/noparse]7]  := 1                    ' sets pin 7 to look for a greater than 1.65vDC signal
      dira[noparse][[/noparse]8] := 1                    ' sets the direction of pin 8 to an output (may be redundant)
                    '' this is not redundant, they are default as input
      outa[noparse][[/noparse]8] := 1                    ' sets pin 8 to a high output to turn on a transistor
    
    
    
      repeat
        if ina[noparse][[/noparse]7] == 1                 ' if pin 7's input is higher than 1.65vDC
          WaitCnt(ClkFreq / 1000 * thirdsec_wait + cnt)   ' wait a 1/3 of a second and poll input pin 7 again
          if ina[noparse][[/noparse]7] == 1               ' if pin 7's input is higher than 1.65vDC a second time
            WaitCnt(ClkFreq / 1000 * thirdsec_wait + cnt) ' wait a 1/3 of a second and poll input pin 7 again
            if ina[noparse][[/noparse]7] == 1             ' if pin 7's input is higher than 1.65vDC a third time
              outa[noparse][[/noparse]8] := 1            ' set output pin 8 to high
              WaitCnt(ClkFreq / 1000 * fulsec_wait + cnt) ' leave pin 8 set to high for a full second
              outa[noparse][[/noparse]8] := 0            ' reset output pin 8 to low
    


    You set OUTA[noparse][[/noparse]8] high before the loop, then you set it high again after pin 7 is high three times. Do you want pin 8 to be low to start with, then set it high to turn on whatever for a second? Or is this now doing what you expect?


    Just as a side note, I usually use the tildes to set my pins. So I would do OUTA[noparse][[/noparse]8]~~ or OUTA[noparse][[/noparse]8]~. I find it more readable than numbers, but I know for normal numbers the tilde is slightly slower for setting variables, I don't know about pins though. I am not sure what the general consensus is on how to set pin states. Ultimately, as long as it works, and you are the only one reading the code, it doesn't matter.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    April, 2008: when I discovered the answers to all my micro-computational-botherations!

    Some of my objects:
    MCP3X0X ADC Driver - Programmable Schmitt inputs, frequency reading, and more!
    Simple Propeller-based Database - Making life easier and more readable for all your EEPROM storage needs.
    String Manipulation Library - Don't allow strings to be the bane of the Propeller, bend them to your will!
    Fast Inter-Propeller Comm - Fast communication between two propellers (1.37MB/s @100MHz)!
  • turbosupraturbosupra Posts: 1,088
    edited 2010-06-12 03:00
    Hi Bobb,

    Thanks!

    I'm going to try and explain better what I'd like it to do

    When I wrote
    outa[noparse][[/noparse]8] := 1                    ' sets pin 8 to a high output to turn on a transistor
    


    I thought I was telling the prop that when I called this pin in the future code, I'd like it to output a 3.3v signal

    When I wrote
    outa[noparse][[/noparse]8] := 1            ' set output pin 8 to high
    


    I thought I was telling the prop to put out 3.3vDC at that moment

    And when I wrote
    outa[noparse][[/noparse]8] := 0            ' reset output pin 8 to low
    


    I thought I was telling the prop to put out a DC ground value now in essence turning off the 3.3vDC



    I have a feeling I did the actual 3.3v voltage out code incorrectly. To write in psuedocode, I'd like for pin 7 to count the number of highs it sees and if it sees 3 within 1/3 of a second of each other back to back to back, I'd like for pin 8 to output 3.3v for 1000milliseconds to an NPN transistor base which will control triggering a relay.





    Bobb Fwed said...
    CON
    
      _CLKMODE = XTAL1 + PLL16X
      _XINFREQ = 5_000_000
    
      quartersec_wait = 250         ' counts every 1/4 second
      thirdsec_wait = 333           ' counts every 1/3 second
      halfsec_wait = 500            ' counts every 1/2 second
      twothirdsec_wait = 667        ' counts every 2/3 second
      threequartersec_wait = 750    ' counts every 3/4 second
      fullsec_wait = 1000           ' counts every 1 second
    
    
    PUB Main
    
    ''no need to set pin 7. by default it is set as an input
      'dira[noparse][[/noparse]7] := 0                    ' sets the direction of pin 7 to an input 
      'ina[noparse][[/noparse]7]  := 1                    ' sets pin 7 to look for a greater than 1.65vDC signal
      dira[noparse][[/noparse]8] := 1                    ' sets the direction of pin 8 to an output (may be redundant)
                    '' this is not redundant, they are default as input
      outa[noparse][[/noparse]8] := 1                    ' sets pin 8 to a high output to turn on a transistor
    
    
    
      repeat
        if ina[noparse][[/noparse]7] == 1                 ' if pin 7's input is higher than 1.65vDC
          WaitCnt(ClkFreq / 1000 * thirdsec_wait + cnt)   ' wait a 1/3 of a second and poll input pin 7 again
          if ina[noparse][[/noparse]7] == 1               ' if pin 7's input is higher than 1.65vDC a second time
            WaitCnt(ClkFreq / 1000 * thirdsec_wait + cnt) ' wait a 1/3 of a second and poll input pin 7 again
            if ina[noparse][[/noparse]7] == 1             ' if pin 7's input is higher than 1.65vDC a third time
              outa[noparse][[/noparse]8] := 1            ' set output pin 8 to high
              WaitCnt(ClkFreq / 1000 * fulsec_wait + cnt) ' leave pin 8 set to high for a full second
              outa[noparse][[/noparse]8] := 0            ' reset output pin 8 to low
    


    You set OUTA[noparse][[/noparse]8] high before the loop, then you set it high again after pin 7 is high three times. Do you want pin 8 to be low to start with, then set it high to turn on whatever for a second? Or is this now doing what you expect?


    Just as a side note, I usually use the tildes to set my pins. So I would do OUTA[noparse][[/noparse]8]~~ or OUTA[noparse][[/noparse]8]~. I find it more readable than numbers, but I know for normal numbers the tilde is slightly slower for setting variables, I don't know about pins though. I am not sure what the general consensus is on how to set pin states. Ultimately, as long as it works, and you are the only one reading the code, it doesn't matter.
  • ElectricAyeElectricAye Posts: 4,561
    edited 2010-06-12 03:07
    turbosupra said...
    .....

    
    
            outa[noparse][[/noparse]8] == 1            ' set output pin 8 to high
            WaitCnt(ClkFreq / 1000 * fulsec_wait + cnt) ' leave pin 8 set to high for a full second
            outa[noparse][[/noparse]8] == 0            ' reset output pin 8 to low
    
    
    
    
    
    


    When you want to assign a value to a variable, you should use :=
    When you want to determine if one value is the same as another (for integers only), then use ==

    You are still getting these confused. EDIT: Okay, looks like you fixed those in the previous post.

    Have you worked your way through the Propeller Educational Kit labs yet? These labs will help you understand these basic concepts.
    See this page:

    http://forums.parallax.com/showthread.php?p=617192

    Post Edited (ElectricAye) : 6/12/2010 3:37:14 AM GMT
  • turbosupraturbosupra Posts: 1,088
    edited 2010-06-12 16:48
    Hi,

    I'm going through the prop PM1.1 and the spin code example ebooks now, and that is where these questions stem from.

    Thank you for your help burger.gif



    ElectricAye said...


    When you want to assign a value to a variable, you should use :=
    When you want to determine if one value is the same as another (for integers only), then use ==

    You are still getting these confused. EDIT: Okay, looks like you fixed those in the previous post.

    Have you worked your way through the Propeller Educational Kit labs yet? These labs will help you understand these basic concepts.
    See this page:

    http://forums.parallax.com/showthread.php?p=617192
  • StefanL38StefanL38 Posts: 2,292
    edited 2010-06-12 18:41
    Hello,

    this kind of signal-checking is not expert-niveau but it is already advanced niveau. I will explain why:

    The suggested solution will only work if the pulses arrive VERY exactly.

    The WaitCnt-commands STOPS the cog completely. If the pulses arrive faster then a pulse might be already finished before the polling for the pulse
    is working again.

    Let's say the pulses should arrive within 300 millisecs.
    If you have a pulsetrain of five pulses where the time between the times are as this


    P1--305-msecs---P2----299-msecs---P3----297-msecs---P4----285-msecs---P5----310-msecs---

    The logic will be still in the middle of the checking and will NOT detect the correct pulse-train of pulses no P2-P3-P4

    If the inputpin stays high for a long time this will be detected wrong as three pulses


    If I understand right the time between the three pulses CAN to be much shorter than the timeout
    In the attachment you will find a spin-file that does it that way by measuring the time from low-high to the next low-high-transistion

    best regards

    Stefan
  • turbosupraturbosupra Posts: 1,088
    edited 2010-06-13 02:45
    Hi Stefan,

    I'm going to look at your code and try to figure it out [noparse]:D[/noparse]

    Thank you very much!


    StefanL38 said...
    Hello,

    this kind of signal-checking is not expert-niveau but it is already advanced niveau. I will explain why:

    The suggested solution will only work if the pulses arrive VERY exactly.

    The WaitCnt-commands STOPS the cog completely. If the pulses arrive faster then a pulse might be already finished before the polling for the pulse
    is working again.

    Let's say the pulses should arrive within 300 millisecs.
    If you have a pulsetrain of five pulses where the time between the times are as this


    P1--305-msecs---P2----299-msecs---P3----297-msecs---P4----285-msecs---P5----310-msecs---

    The logic will be still in the middle of the checking and will NOT detect the correct pulse-train of pulses no P2-P3-P4

    If the inputpin stays high for a long time this will be detected wrong as three pulses


    If I understand right the time between the three pulses CAN to be much shorter than the timeout
    In the attachment you will find a spin-file that does it that way by measuring the time from low-high to the next low-high-transistion

    best regards

    Stefan
  • turbosupraturbosupra Posts: 1,088
    edited 2010-06-13 03:34
    Stefan,

    I understand about 75% of your code, but when there are lines such as this

    Time_high_low_high[noparse][[/noparse]TimerNr] := elapsed_time_msec(CntSnapShot[noparse][[/noparse]TimerNr]) 
    
    



    What does that mean when one variable has another variable as an array? Can you use example numerical values?
  • StefanL38StefanL38 Posts: 2,292
    edited 2010-06-13 04:50
    Hi,

    simple example of using an array

    VAR
      long MyArray
      long anotherArray
    
    
    PUB Main
      MyArray[noparse][[/noparse] 0 ] := 10
      MyArray[noparse][[/noparse] 1 ] := 20
      MyArray[noparse][[/noparse] 2 ] := 30
    
      anotherArray[noparse][[/noparse] 0 ] := 100
      anotherArray[noparse][[/noparse] 1 ] := 200
      anotherArray[noparse][[/noparse] 2 ] := 300  
    
    





    now the following would do the same

    VAR
      long MyArray[noparse][[/noparse] 3 ]
      long anotherArray[noparse][[/noparse] 3 ]
    
      long ArrayIndex
    
    PUB Main
      ArrayIndex := 0
      MyArray[noparse][[/noparse] ArrayIndex] := 10 
    
      ArrayIndex := 1
      MyArray[noparse][[/noparse] ArrayIndex] := 20
    
      ArrayIndex := 2
      MyArray[noparse][[/noparse] ArrayIndex] := 30
    
      
      ArrayIndex := 0
      anotherArray[noparse][[/noparse] ArrayIndex] := 100
      
      ArrayIndex := 1
      anotherArray[noparse][[/noparse] ArrayIndex] := 200
    
      ArrayIndex := 2
      anotherArray[noparse][[/noparse] ArrayIndex] := 300  
    
    
      'you can do it even this way
      ArrayIndex := 0
      anotherArray[noparse][[/noparse] ArrayIndex] := MyArray[noparse][[/noparse] ArrayIndex] + anotherArray[noparse][[/noparse] ArrayIndex]
      
      ArrayIndex := 1
      anotherArray[noparse][[/noparse] ArrayIndex] := MyArray[noparse][[/noparse] ArrayIndex] + anotherArray[noparse][[/noparse] ArrayIndex]
    
      ArrayIndex := 2
      anotherArray[noparse][[/noparse] ArrayIndex] := MyArray[noparse][[/noparse] ArrayIndex] + anotherArray[noparse][[/noparse] ArrayIndex]
      
    
    



    result after the last operations
    anotherArray[noparse][[/noparse] 0 ] contains 110
    anotherArray[noparse][[/noparse] 1 ] contains 220
    anotherArray[noparse][[/noparse] 2 ] contains 330


    whenever you use a variable or an expression the variable or expression
    gets evaluated and the evaluated value is used

      ArrayIndex := 0
      MyVar := anotherArray[noparse][[/noparse] ArrayIndex + 1 ] * 5 - 1
    
    



    so MyVar will contain
    'showing the evaluation step by step

      MyVar := anotherArray[noparse][[/noparse] ArrayIndex + 1 ] * 5 - 1
      MyVar := anotherArray[noparse][[/noparse]       0    + 1 ] * 5 - 1
      MyVar := anotherArray[noparse][[/noparse] 1 ]              * 5 - 1
      MyVar :=      220                       * 5 - 1
      MyVar :=      1100                          - 1
    
    



    'result
    MyVar contains value 1009

    best regards

    Stefan

    Post Edited (StefanL38) : 6/13/2010 4:29:57 PM GMT
Sign In or Register to comment.