BS2 Spin Object help
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
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
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 !
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.
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..
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·
[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
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 ?
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
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 *UpdatedNext 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
Propeller-Education-Kit Labs fundamental manual page 122ff
best regards
Stefan
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. }}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.