Shop OBEX P1 Docs P2 Docs Learn Events
BS2 Spin Object help — Parallax Forums

BS2 Spin Object help

jbalatjbalat Posts: 96
edited 2010-01-23 07:09 in Propeller 1
Hi I am new to the propeller but I have programmed the BS2

I need to use the PULSIN to read a frequency from a square pulse and write the value to memory.. This will run in a continuous loop

On a seperate cog.. I want to read this value and multiply it by a factor and do a PULSOUT in a continuous loop

I understand if the PULSIN gets a zero then it may freeze up the 1st cog. So I think I need a watchdog timer (huh?) on another cog to reset Cog 1 if it freezes..?? Is that right ?

Any tips on how to implement this code using the BS2 object ?
obex.parallax.com/objects/30/

Thanks in advance
JB

Comments

  • JonnyMacJonnyMac Posts: 9,208
    edited 2009-11-26 20:47
    You may be limiting yourself by trying to use the BS2 object; it would be cleaner and more efficient to write a method in Spin that you could launch into its own cog; that method would write to a known global variable that gets picked up by the other cog that reads, modifies, and retransmits. I'd lean toward using one of the counters to measure an incoming pulse (one half of the square wave) and then divide that down as required for your units of measurement.
  • jbalatjbalat Posts: 96
    edited 2009-11-26 22:41
    Efficiency is measured in many ways.. Since I have not done any spin programming the BS2 object looks easier for me at this stage

    The signal ranges from 25Hz to 300Hz so should be easy to measure and output assuming I can do these operations on seperate cogs

    Please post some spin code either way, I need all the help I can get !
  • JonnyMacJonnyMac Posts: 9,208
    edited 2009-11-27 01:10
    Well, then, knock yourself out with the BS2 object. FWIW, you'll learn Spin (or any other language for that matter) more effectively you you break the problem down into small parts and test them before tackling the big picture. Start by learning to send values to a terminal program (FullDuplexSerial will do that for you). Then learn how to measure a pulse and display that in the terminal to make sure you've got it correct. Etc. Etc. Etc.

    Hint: The internal counters are really nice tools for measuring a pulse width; see the App Note (in the Propeller downloads section) for details. I've used them for this purpose many times, but all of my code for that is in PASM, not Spin.
  • jbalatjbalat Posts: 96
    edited 2009-11-27 05:39
    Johnny Mac,
    its not that I want to use the bs2 object..

    I just bought the prop to do one specific task in my car..
    Im not fussed how it works whether I use a propeller or a black box, but when its working it will be permanently mounted in the car and I may or may not buy another one for playing around.

    I am reading the spin manual and Im sure I will come across the commands I want sooner or later..
  • SamMishalSamMishal Posts: 468
    edited 2009-11-27 10:36
    JB,

    The problem with the PULSIN() function causing the cog to hang is that it uses the PULSIN_Clk() method which in turn
    makes use of the WaitPne() and WaitPeq() functions.

    These will wait FOREVER for the required state and if the state never comes then the cog seems to hang.

    What you need is to replace the functions above with a REPEAT loop with a time out condition.

    The function PULSIN_Clk2() below does this. It times out after 1 second. You can change this to more or less by changing the
    line just above each·repeat loop which says T := ClkFreq+cnt to T:=ClkFreq*F+cnt where F is the number of seconds you need
    or to T := ClkFreq/F+cnt· where F is the fraction of seconds you need.

    Notice that the PULSIN_Clk2() function returns 0 if the first two wait loops time out and it returns ClkFreq if the last loop times out.
    Again you can change this as you need.

    So in your object for your needs just change the call to PULSIN_Clk()·in the PULSIN() function to make it call the one below.
    You also may want to check for the 0 condition·if you·need to do some other action in the case of time outs.

    The function below will not cause any hangs and if there is no pulse on the Pin it will return a 0 and·when·pulsing does
    start on the pin it will start reporting the correct PULSE duration which then you can use·in the other actions you mentioned in
    your post.

    I hope this helps.

    Samuel

    PUB PULSIN_Clk2(Pin, State) : Duration | T 
    '' Reads duration of Pulse on pin defined for state, returns duration in 1/clkFreq increments - 12.5nS at 80MHz
    '' Note: Absence of pulse can cause cog lockup if watchdog is not used - See distributed example
    ''  x := BS2.Pulsin_Clk(5,1)
      DIRA[noparse][[/noparse]pin]~
      ctra := 0
      if state
        ctra := (%11010 << 26 ) | (%001 << 23) | (0 << 9) | (PIN) ' set up counter, A level count
      else
        ctra := (%10101 << 26 ) | (%001 << 23) | (0 << 9) | (PIN) ' set up counter, !A level count
      frqa := 1
      'waitpne(State << pin, |< Pin, 0)                         ' Wait for opposite state ready
      T := ClkFreq+Cnt
      repeat
        if Cnt > T
          Return 0
      until (ina[noparse][[/noparse]Pin] <> State) 
      phsa:=0                                                  ' Clear count
      'waitpeq(State << pin, |< Pin, 0)                         ' wait for pulse
      T := ClkFreq+Cnt
      repeat
        if Cnt > T
          Return 0
      until (ina[noparse][[/noparse]Pin] == State) 
      'waitpne(State << pin, |< Pin, 0)                         ' Wait for pulse to end
      T := ClkFreq+Cnt
      repeat
        if Cnt > T
          Return 0
      until (ina[noparse][[/noparse]Pin] <> State) 
      Duration := phsa                                         ' Return duration as counts
      ctra :=0                                                 ' stop counter
    
    

    ·
  • JonnyMacJonnyMac Posts: 9,208
    edited 2009-11-27 15:58
    Using waitpeq or waintpne is only a problem when blocking within the cog you're running -- if you launch a separate cog that can update a known hub address the mainline cog is not blocked if no pulse shows up. The foreground cog can detect a blockage by writing zero to the hub address after picking up the last good measurement -- the zero serves as a flag than no additional measurement has occurred.

    [noparse][[/noparse]Edit] I've attached a demo that launches a PASM cog to measure a positive pulse on the desired pin. The result is written to a global (hub) variable to be picked up by another cog -- this prevents blocking problems. The foreground demo code launches the "background" cog, then creates a simple pulse and displays the result on the terminal; the difference between the value in the waitcnt() instruction and what is displayed is the overhead for two Spin instructions.

    Post Edited (JonnyMac) : 11/27/2009 6:21:53 PM GMT
  • jbalatjbalat Posts: 96
    edited 2009-11-29 22:53
    Jonny Mac,
    I have read the manual and still cant work out exactly how your program works. The text in propterminal is also coming out a bit messy..
    -Do I input my external pulse into Pin 16 ?
    -I have the proto board not the demo board


    Note: That I have emulated a pulse using my stamp and I can feed it into the propeller via a 2.2K resistor..


    Sam...
    I have used the BS2 object with your fix with PULSIn and PULSOUT and this worked. Howevever because I was running both commands in the one procedure I dont get a proper square wave on the PULSOUT.. Any tips on how to launch this on another COg is appreciated. Do I need to lock the Global variable when writing it with the PULSIN incase the pulsout tries to read it at the same time ?
  • jbalatjbalat Posts: 96
    edited 2009-11-30 12:43
    Johnny Mac,
    I have made some progress modifying your program to read a signal on Pin8 and output modified signal on pin0.. Only the MFactor calculation is not working below. Later I want to get MFactor by reading a Pot..

    con
      #0, CLS, HOME, #8, BKSP, TAB, LF, CLREOL, CLRDN, CR           ' PST formmatting control
      TEST_PIN = 8                                              'input pin 
      [b]OUT_PIN = 0                                           'output pin
      MFACTOR = 1.2                                           'Output = MFactor * Input[/b]
      
    obj
      term : "fullduplexserial"
    
    var
      long  cog
      long  pulsewidth
    
    pub main
      term.start(31, 30, %0000, 115_200)                            ' start terminal program
      waitcnt(clkfreq / 100 + cnt)
      term.tx(CLS)
    
      init(TEST_PIN)                                              ' launch measurement cog
      waitcnt(clkfreq / 100 + cnt)                            ' give time to start
    
      [b]dira[noparse][[/noparse]OUT_PIN]~~                                      ' make pin output for test
    
      repeat                                                          ' Toggle Output Pin
        !outa[noparse][[/noparse]OUT_PIN]
        waitcnt( ([color=#990000]MFACTOR[/color] * pulsewidth) + cnt)                       ' wait for half pulse  [/b]
    




    Pls Help.. If Mfactor is 2 then it works, but at 1.2 it doesnt work.. What the ???

    Post Edited (jbalat) : 11/30/2009 12:53:00 PM GMT
  • jbalatjbalat Posts: 96
    edited 2009-11-30 22:46
    Oops...Justs added test back for no signal..

    con
      #0, CLS, HOME, #8, BKSP, TAB, LF, CLREOL, CLRDN, CR           ' PST formmatting control
      TEST_PIN = 8                                              'input pin 
      OUT_PIN = 0                                           'output pin
      MFACTOR = 1.2                                           'Output = MFactor * Input
      
    obj
      term : "fullduplexserial"
    
    var
      long  cog
      long  pulsewidth
    
    pub main
      term.start(31, 30, %0000, 115_200)                            ' start terminal program
      waitcnt(clkfreq / 100 + cnt)
      term.tx(CLS)
    
      init(TEST_PIN)                                              ' launch measurement cog
      waitcnt(clkfreq / 100 + cnt)                            ' give time to start
    
      dira[noparse][[/noparse]OUT_PIN]~~                                      ' make pin output for test
    
      repeat                                                          ' Toggle Output Pin
        !outa[noparse][[/noparse]OUT_PIN]
    
        if (pulsewidth <> 0)                                                                
          MyPulse = MFACTOR  * pulsewidth    '*Updated
          pulsewidth~                                                    ' clear last measurement  
        
        waitcnt( Mypulse + cnt)                       ' wait for half pulse *Updated
    
    
  • jbalatjbalat Posts: 96
    edited 2009-12-01 13:18
    Ok I have made a few small changes and it now works like a charm..

    Next step is to be able to change the value of MFactor with a Pot running on a seperate cog

    Any tips appreciated.

    Modified code is attached if anyone would like to help or comment
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-12-01 15:02
    take a look into the

    Propeller-Education-Kit Labs fundamental manual page 122ff

    best regards

    Stefan
  • jbalatjbalat Posts: 96
    edited 2009-12-17 07:43
    Thanks for that.. I read the whole thing and it has given me a better understanding of programming with different cogs and using the rc decay feature.

    This is my updated program
    '' =================================================================================================
    ''
    ''   File....... PropMaf.spin
    '' 
    '' =================================================================================================
    
    
    con
    
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      
      
    con
      POT_PIN  = 0
      TEST_PIN = 22                                                 'input pin 
      OUT_PIN = 19                                                  'output pin
    
    var
    
      long  cog
      long  pulsewidth
      long  MFactor
      long  MyPulse
      long  stack[noparse][[/noparse]60]
      
    pub main
      MFactor := 100
      MyPulse := 5000
     
      waitcnt(clkfreq / 100 + cnt)
    
      inpin     := TEST_PIN                                         ' pin # used
      widthpntr := @pulsewidth                                      ' hub address for measurement
        
      cognew(@pulsin, 0)  
      cognew(Pot, @stack[noparse][[/noparse]15])
    
      waitcnt(clkfreq / 100 + cnt)                                 ' give time to start
    
      dira[noparse][[/noparse]OUT_PIN]~~                                              ' make pin output for test
    
       repeat                                                       
        !outa[noparse][[/noparse]OUT_PIN]                                             ' Toggle Output Pin   
                                                                           
        if (pulsewidth <> 0)                                       
          MyPulse := MFactor * pulsewidth / 100                    ' Calculate Output pulse 
          pulsewidth~                                              ' clear last measurement  
    
        waitcnt( MyPulse + cnt)                     ' wait for half pulse                                                                     
    
    
    PUB Pot | potTime
    
      ' This sub returns new MFactor based on Pot 101% - 150%
    
      ' Configure counter module.
      ctra[noparse][[/noparse]30..26] := %01000                     ' Set mode to "POS detector"
      ctra[noparse][[/noparse]5..0] := POT_PIN                      ' Set APIN to P0
      frqa := 1                                  ' Increment phsa by 1 for each clock tick
    
      repeat
    
         ' Charge RC circuit.
         dira[noparse][[/noparse]POT_PIN] := outa[noparse][[/noparse]POT_PIN] := 1                 ' Set pin0 to output-high
         waitcnt(clkfreq/100_000 + cnt)          ' Wait for circuit to charge
          
         ' Start RC decay measurement.  It's automatic after this...
         phsa~                                  ' Clear the phsa register
         dira[noparse][[/noparse]POT_PIN]~                               ' Pin to input stops charging circuit
         waitcnt(clkfreq / 5 + cnt)             ' Wait for Decay 1/5 second 
    
         ' Get Time difference
         potTime := (phsa - 624) #> 0                
         MFactor := (potTime / 900) + 101       ' Calculate factor 101-150
         waitcnt(clkfreq / 20 + cnt)            ' Wait 1/20 second -> 10 Hz
    
         
    dat
    
                            org     0
    
    pulsin                  mov     ctra, POS_DETECT                ' setup for postive detection
                            movs    ctra, inpin                     ' assign to inpin
                            mov     frqa, #1
    
                            mov     pmask, #1                       ' create mask for inpin
                            shl     pmask, inpin
    
    waitlo                  waitpne pmask, pmask                    ' wait for low between pulses
                            mov     phsa, #0                        ' clear counter
    waithi                  waitpeq pmask, pmask                    ' wait for leading edge
    waitdone                waitpne pmask, pmask                    ' wait for falling edge
    
                            mov     tmp1, phsa                      ' make copy of pulse width
                            wrlong  tmp1, widthpntr                 ' write pulse width to hub
                            jmp     #waitlo
    
    ' --------------------------------------------------------------------------------------------------
    
    POS_DETECT              long    %01000 << 26                    ' ctr positive detector
    NEG_DETECT              long    %01100 << 26                    ' ctr negative detector
    FREE_RUN                long    %11111 << 26                    ' ctr logic always mode
    
    inpin                   long    0-0                             ' pin # for pulse input
    widthpntr               long    0-0                             ' hub address for pulse width
    
    pmask                   res     1                               ' mask for pin used 
    tmp1                    res     1 
    
                            fit     492
                            
    
    dat
    
    {{
    
      Copyright (c) 2009 Jon McPhalen (aka Jon Williams)
    
      Permission is hereby granted, free of charge, to any person obtaining a copy of this
      software and associated documentation files (the "Software"), to deal in the Software
      without restriction, including without limitation the rights to use, copy, modify,
      merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
      permit persons to whom the Software is furnished to do so, subject to the following
      conditions:
    
      The above copyright notice and this permission notice shall be included in all copies
      or substantial portions of the Software.
    
      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
      INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
      PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
      HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
      CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
      OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
    
    }}
    
  • jbalatjbalat Posts: 96
    edited 2009-12-22 06:09
    Ok this is the final program which is now working properly

    I had to ignore signals that are out of bounds since I must be getting a lot of noise ?

    I also dumped the PASM code because I couldnt figure out how it worked.
  • jbalatjbalat Posts: 96
    edited 2010-01-23 07:09
    jbalat said...
    Ok this is the final program which is now working properly

    I had to ignore signals that are out of bounds since I must be getting a lot of noise ?

    I also dumped the PASM code because I couldnt figure out how it worked.
Sign In or Register to comment.