Problem counting pulses
I am attempting to get my prop to count pulses on a pin. I started with the Motor Minder spin code and read the ctra and associated passages in the manual about 15 times and I think I understand what it going on. I extracted out a part of the code that should (I think) monitor pulses on pin 7 and accumulate them in phsa. I have an optocoupler that is putting out a 60Hz square(ish) wave as my pulse source from an A/C input. In principle, this code works. If I turn the A/C on, it begins counting, off and it stops. The problem is that the count is growing at a much faster rate than 60 per second.

I was assuming that it would only increment phsa once per positive edge. Is it incrementing every clock cycle that the pin is high? or?? I ran it for 10 seconds (using my watch, not code) and the count was just over 38,000, where it should have been 600.
Does anyone have any ideas? Does the pulse source need to be cleaner? Is it a simple coding problem?
PUB Main
LCDStart
LCD.tx($11) ' backlight on
LCD.tx($16) ' LCD on; cursor off, blink off
LCD.tx($0C) ' clear LCD
cognew(ClockInput, @ClockInputStack)
repeat
LCD.tx($94)
LCD.dec(pulsecount)
PUB ClockInput
dira[7]~ ' set ClockPulsePin to input
'start A/C Hz counter in counter A
frqa := 1
ctra := 0 ' stop counter
phsa := 0 ' zero counter
ctra := (%01010 << 26 ) | (7) ' start counting positive edges in counter A
repeat
pulsecount := phsa

I was assuming that it would only increment phsa once per positive edge. Is it incrementing every clock cycle that the pin is high? or?? I ran it for 10 seconds (using my watch, not code) and the count was just over 38,000, where it should have been 600.
Does anyone have any ideas? Does the pulse source need to be cleaner? Is it a simple coding problem?
Comments
I have to be honest and say I don't fully understand the counters so debugging them is hard for me, but the following code works for me and I think we're doing similar things. I want to watch the number of pulses on 2 input pins, then once a second write out the values. I think all you need to do is remove the accumulator reset and 1 second delay stuff.
Comparing your code to mine the only difference I see is a "+" instead of an "|" when setting up ctra which seem to be the same thing in this instance.
What about editing your stuff to only run for 10 seconds then output?
Sorry I'm not more helpful. Hopefully someone else can chime in.
Peter
'Set up the counters for freq measurements to be used below. ctra := %01010 << 26 + LRCLK1 'counter A in POSedge mode ctrb := %01010 << 26 + BCLK1 'counter B in POSedge mode frqa := frqb := 1 'increment 1 per pulse 'pulse count loop repeat phsa := 0 'reset count registers phsb := 0 DELAY_MS(1_000) 'accumulate data for 1 second. lrPulses := phsa 'read the puls counts bPulses := phsb uarts.str(DEBUG,string("LRCLK (hz): ")) uarts.decf(DEBUG,lrPulses,8) uarts.str(DEBUG,string(" BCLK (hz): ")) uarts.decf(DEBUG,bPulses,8) uarts.putc(DEBUG,CR)
I hope that helps
Try posting all of your code either within the code brackets or using the ( File->Archive->Project...) from the Propeller IDE and attaching it.
The Counter mode that you are using is correct ... %01010 - POSEDGE detector which compares the input delayed by 1 clock with the inverted input delayed by 2 clocks. A logical AND is performed within the counter logic and if the result is "1" then a transition from LOW to HIGH occurred and phsa is incremented by the amount specified in frq. This way it doesn't accumulate phsa on every single clock when the input is HIGH.
Here is some code that is basically the core of what you posted, but modified to display on the Parallax Serial Terminal. The test setup for the code below: Pin 5 is connected to Pin 7 via a 330 Ohm resistor. In this code, it runs for 10 seconds, and the final displayed output is 600 as you indicated in your first post.
'[B]Version 1[/B] CON _CLKMODE = XTAL1 + PLL16X _XINFREQ = 5_000_000 OBJ PST : "Parallax Serial Terminal" Freq : "Synth" VAR long ClockInputStack[100],pulsecount,counter PUB start Freq.Synth("A", 5, 60) PST.Start(19200{<- Baud}) PST.Char(0) ' clear cognew(ClockInput, @ClockInputStack) counter := (clkfreq*10)+cnt repeat until cnt > counter PST.dec(pulsecount) PST.Char(13) repeat PUB ClockInput dira[7]~ ' set ClockPulsePin to input 'start A/C Hz counter in counter A frqa := 1 ctra := 0 ' stop counter phsa := 0 ' zero counter ctra := (%01010 << 26 ) | (7) ' start counting positive edges in counter A repeat pulsecount := phsa
'[B]Version 2 - There is no need to launch a cog for the counter[/B] CON _CLKMODE = XTAL1 + PLL16X _XINFREQ = 5_000_000 OBJ PST : "Parallax Serial Terminal" Freq : "Synth" PUB start|temp,counter Freq.Synth("B", 5, 60) ' send a 60Hz square wave out on pin 5 PST.Start(19200{<- Baud}) ' start Parallax Serial Terminal at 19200 baud 'start A/C Hz counter in counter A ctra := (%01010 << 26 ) | (7) ' start counting positive edges in counter A on pin 7 frqa := 1 phsa := 0 ' zero counter counter := (clkfreq*10)+cnt repeat until cnt > counter ' repeat for 10 seconds PST.dec(phsa) PST.Char(13)
can you show your schematic? It can be a hardware proplem if the voltage at the input pin rises too slow and is noisy then the fast pos-detector counts more than 1 edge.
You can try to replace the ClockInput routine with this code:
PUB ClockInput | t1,t2 t1 := ina[7] repeat t2 := t1 t1 := ina[7] if (t1^t2) & t1 'detect pos edge pulsecount++
it does the same as the counter but much slower (with Spin speed).Andy
and all of the code:
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 cntMin = 400 ' Minimum waitcnt value to prevent lock-up TX_PIN = 0 ' For Debug LCD BAUD = 19_200 ' For Debug LCD ClockPulsePin = 7 VAR long pulsecount,cntholder,ms long ClockInputStack[128] OBJ LCD : "FullDuplexSerial.spin" ' For Debug LCD PUB Main ms:= clkfreq / 1_000 LCDStart cognew(ClockInput, @ClockInputStack) repeat LCD.tx($94) LCD.dec(pulsecount) PUB ClockInput pulsecount := 0 ' initialize oldcount dira[ClockPulsePin]~ ' set ClockPulsePin to input 'start A/C Hz counter in counter A frqa := 1 ctra := 0 ' stop counter phsa := 0 ' zero counter ctra := (%01010 << 26 ) + ClockPulsePin ' start counting positive edges in counter A cntholder := cnt repeat until cnt >= (cntholder + 800_000_000) pulsecount := phsa PUB PAUSEms(Duration) | clkCycles clkCycles := Duration * ms-2300 #> cntMin ' duration * clk cycles for ms ' - inst. time, min cntMin waitcnt( clkCycles + cnt ) ' wait until clk gets there PUB LCDStart LCD.start(TX_PIN, TX_PIN, %1000, 19_200) waitcnt(clkfreq / 100 + cnt) ' Pause for FullDuplexSerial.spin to initialize LCD.tx($11) ' backlight on LCD.tx($16) ' LCD on; cursor off, blink off LCD.tx($0C) ' clear LCD PAUSEms(1000)
Ariba, your code works with or without the current limiting resistor. On the one hand, I'm inclined to just go with it, but would also like to know why my code doesn't work.
Andy
[Edit] I see Andy suggested the same thing.
Your code works, so the problem 'must' be in hardware. The Scope image that you attached, was that off of P7 of your circuit?
The 330 Ohm series resistor was for DEBUG only and was meant to be tied between P5 and P7... the example I posted provided a 60Hz square wave reference from P5.
You can eliminate needing to use a cog for the counter function (see code below)
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 cntMin = 400 ' Minimum waitcnt value to prevent lock-up '≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈ TX_PIN = 0 ' For Debug LCD ' TX_PIN = 31 ' For Debug Terminal window ' RX_PIN = 30 ' For Debug Terminal window '≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈ BAUD = 19_200 ' For Debug LCD ClockPulsePin = 7 VAR long cntholder,ms OBJ LCD : "FullDuplexSerial.spin" ' For Debug LCD Freq : "Synth" ' For Debug signal generation PUB Main ms:= clkfreq / 1_000 LCDStart '≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈ ' Freq.Synth("B", 5, 60) ' send a 60Hz square wave out on pin 5 '≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈ 'start A/C Hz counter in counter A ctra := (%01010 << 26 ) + ClockPulsePin ' start counting positive edges in counter A frqa := 1 phsa := 0 ' zero counter cntholder := cnt repeat until cnt >= (cntholder + 800_000_000) LCD.tx($94) LCD.dec(phsa) PUB PAUSEms(Duration) | clkCycles clkCycles := Duration * ms-2300 #> cntMin ' duration * clk cycles for ms ' - inst. time, min cntMin waitcnt( clkCycles + cnt ) ' wait until clk gets there PUB LCDStart '≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈ LCD.start(TX_PIN, TX_PIN, %1000, 19_200) 'Setup for LCD ' LCD.start(TX_PIN, RX_PIN, %0000, 19_200) 'Setup for Terminal '≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈ waitcnt(clkfreq / 100 + cnt) ' Pause for FullDuplexSerial.spin to initialize LCD.tx($11) ' backlight on LCD.tx($16) ' LCD on; cursor off, blink off LCD.tx($0C) ' clear LCD PAUSEms(1000)
I am going to try a schmitt trigger next if I can get my hands on one.
Tracy, 120V. I don't have an output resistor, unless you are talking about the 4.7k. If so, would I put the positive on the collector side and the negative on the P7 side? or the positive on the collector and negative on ground?
and change the counter initialization to:
dira[ClockPulsePin]~ dira[AuxPin]~~ dira[FB_Pin]~~ ctra := %01011<<26 + AuxPin<<9 + ClockPulsePin 'start counting positive edges ctrb := %01011<<26 + FB_pin<<9 + AuxPin 'generate pos Feedback for ST
A schmitt trigger needs a positive feedback to the input. The Counters have only a negative feedback in PosEdge mode, so you can use an auxiliary pin and a second counter to generate a positive feedback. This is not ideal because the feeback is delayed by 2 clock pulses, I hope the noise is not at so high frequencies that this matters. Otherwise a little filter as Tracey Allen described would help.Andy
...where the Prop Threshold would be switching, the signal looks absolutely fine. A Schmitt Trigger in my honest opinion would only be necessary if there were a lot of noise, and that I don't see.
Benj,
Can you zoom in any closer to one of the pulses, and post that image?
Also, just a wild guess, what does the supply voltage noise look like? ... by the numbers that you are reporting it seems that there is a frequency component of about 3.8 kHz ... 4 kHz coming from somewhere, most likely not the AC line. What else do you have connected to the Propeller?