Input transition event counter
MJHanagan
Posts: 189
I am trying to use the CTRA function to count the number of positive edge transitions on an input pin. The pin is connected to the output of a comparator on a zero crossing voltage detector circuit. The output is a nice steady +Vdd/0 signal running at 60 Hz. I want the PHSA register to index by 1 for each transition from 0 to 1 on the input pin (i.e. FRQA=1). From reading the CTRA section in the manual (p 95-98) it looks like I should be using a CTRMODE of %01001 (POSEDGE detector) or %01011 (POSEDGE detector w/feedback). Instead of PSHA being indexed by 1 it seem is be indexing by 6, 7, 8 or 9 with each input transition. Am I missing something here?
Here is the test code I am using:
Here is the test code I am using:
CON _clkmode = xtal1 + pll16x 'Must stay with the 16x (80 MHz for IR to work reliably) _xinfreq = 5_000_000 ' serial terminal baud rate (default I/O pins are 30 and 31): PSTBaud = 115200 ZCPin = 5 OBJ pst : "Parallax Serial Terminal" VAR LONG HzCounter, HZMode PUB Main | i, j, k, l, m, n pst.Start( PSTBaud ) pst.Clear pst.Beep pst.str(String("Initializing...")) 'Set zero cross pin as input DIRA[ ZCPin ]~ 'Start the CTRA counter to count 60 Hz pulses off the zero cross detector input pin. ' HzMode := %01010 << 26 'POSEDGE detector HzMode := %01011 << 26 'POSEDGE detector w/feedback HzMode += ZCPin 'Encode the zero cross pin number into the mode pst.str( String( pst#NL, "HzMode: %" ) ) pst.bin( HzMode, 32 ) FRQA := 1 ' add 1 to the PHSA register for each input edge change detected detected. CTRA := HzMode PHSA := 0 ' Clear the counter pst.str( String( pst#NL, "Testing 60 Hz counter... " ) ) repeat 5 i := PHSA waitcnt( cnt + clkfreq ) j := PHSA pst.str( String( pst#NL, "PHSA start: " ) ) pst.dec( i ) pst.str( String( " end: " ) ) pst.dec( j ) pst.str( String( " delta: " ) ) pst.dec( j-i ) pst.str(String( pst#NL, "Done.")) pst.str( String( pst#NL, "PHSA change counter... " ) ) REPEAT 5 PHSA := 0 REPEAT UNTIL PHSA > 0 i := CNT PHSA := 0 REPEAT UNTIL PHSA > 0 i := CNT - i j := PHSA pst.str( String( pst#NL, "PHSA change CNT: " ) ) pst.dec( i ) pst.str( String( " PHSA end: " ) ) pst.dec( j ) {{ End of code}}
Comments
Andy
Comparators come with a small amount of hysteresis built-in, but perhaps the signal is too noisy for this? Simple low-pass filtering the input to the comparator might help with that. Or more positive feedback.
The comparator has good decoupling I hope...
If the comparator is slow, in combination with ground bounce noise and layout issues, it can detect multiple transitions as it hovers in the region of the Prop switching threshold. On the other hand, if the comparator is fast, in combination with layout issues, the comparator itself can oscillate as it passes through its transition point. Either way, multiple counts that call for more hysteresis or layout or bypassing changes.
I used a scope to verify the output and it looked nice and clean - however I don't think I have enough resolution in the scope to see if the signal was chattering faster than ~1 MHz at the transition points. Perhaps a larger hysterisis is in order by reducing the value of R16?
Andy
Do you need to know the exact point in time at which the zero-crossing occurs? Or is it only necessary to count them? In the former case, you have to be wary of adding too much hysteresis, as this will delay the reading of the zero-crossing. I would be much more inclined to use a software-mediated technique that looks for the first edge, then waits before setting up to detect another one.
-Phil
The reason for the counter is becuase I want to time various other on/off and timeout events with intervals exceeding the ~26.3 second limit of using the CNT timing method. Thus a 60 Hz counter would extend the integer rollover time to something like 414 days which is plenty. I am tring to do this without minimal code and consuming a cog to keep track of the ZCPin transistions.
Perhaps there is another more simple or more elegant way of accomplishing this?
If your earth falls off, thats 100K straight to the mains...
Look at VR37/VR68 high voltage resistors and use some meg ohms (10M+), to feed a ZCD.
A simple ZCD will use a Schmitt Buffer, and you can add a series CAP, to the series resistor, (gives phase lead) to allow a shunt cap to filter spikes, (gives phase lag) without adding phase errors,
OR you can skip the series cap, and simply know what the filter phase delay is, and correct that in SW.
SW can also compensate for slight DC offsets in ZCD, or +/- skews.
Indeed a 20M resistor is pretty weak there (perhaps if one added a few tens of pF in parallel it wouldn't be so bad). Certainly a percent or so of hysteresis is more usual and more inline with the kind of noise spikes that are likely to be superimposed on the inputs on a digital PCB. Again LPF on the input to the comparator might help, but I don't think extreme accuracy is needed in this circuit - extra hysteresis is a robust defence to false triggering.
Spice says the 1nf has ~ 30V pk across it, and the 68pF shunt gives a nominal zero crossing phase correction, and noise filter.
The HC14 clamp diodes will clamp the 8uA current from the 22Meg.
Andy
The output waveform is virtually symmetrical. On my bench, the duty cycle was 49.55%. And, most importantly, the Propeller is completely isolated from the mains.
-Phil
Shouldn't those optos be reverse connected ? - so they alternate conduction ?
Now I look again, I see they are reverse connected, my eyes are playing tricks...
-Phil