Shop OBEX P1 Docs P2 Docs Learn Events
Input transition event counter — Parallax Forums

Input transition event counter

MJHanaganMJHanagan Posts: 189
edited 2012-09-19 07:06 in Propeller 1
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:
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

  • ElectricAyeElectricAye Posts: 4,561
    edited 2012-09-18 07:44
    Is your code below REPEAT UNTIL PHSA > 0 supposed to be indented?
  • MJHanaganMJHanagan Posts: 189
    edited 2012-09-18 07:56
    I don't think so. The first REPEAT UNTIL PSHA > 0 is to align the timing to the first transition from low to high. The second REPEAT UNTIL PSHA > 0 should capture the amount of time between transitions.
  • AribaAriba Posts: 2,690
    edited 2012-09-18 08:21
    MJHanagan wrote: »
    ..The output is a nice steady +Vdd/0 signal running at 60 Hz. ...
    Are you sure about that? A Propeller counter will count pos-edges with up to 40 MHz (with 80 MHz clock), so if the output of your comparator oscillates for a short moment at every transition then these oscillations will be counted. Have you included a hysteresis in your comparator circuit? It would help to see a schematic of your zero crossing circuit.

    Andy
  • Mark_TMark_T Posts: 1,981
    edited 2012-09-18 09:24
    Ariba wrote: »
    Are you sure about that? A Propeller counter will count pos-edges with up to 40 MHz (with 80 MHz clock), so if the output of your comparator oscillates for a short moment at every transition then these oscillations will be counted. Have you included a hysteresis in your comparator circuit? It would help to see a schematic of your zero crossing circuit.

    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...
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2012-09-18 09:44
    You mentioned POSDET with feedback. There may be a way to route the feedback output back into your comparator to help make a clean transition.

    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.
  • MJHanaganMJHanagan Posts: 189
    edited 2012-09-18 10:02
    Here is the schematic of the zero crossing circuit.
    ZC Circuit.jpg
    The "ZCP" output is connected to the input of a digital isolator as shown here:
    ZC Circuit 2.JPG


    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?
    1024 x 552 - 78K
    769 x 478 - 62K
  • AribaAriba Posts: 2,690
    edited 2012-09-18 10:25
    Yes I would reduce the value of R16 to 1MOhm or even lower. And if it is not too hard I would also make the pullup resistor R15 a bit more weak, perhaps 4.7 kOhm.

    Andy
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2012-09-18 10:40
    It might be better off with NEGEDGE instead of POSEDGE. Because of the open collector output, the falling edges are going to be faster than the rising edges. A lower resistance value for R16 is good, also a 10pF – 100pF capacitor in parallel with R16.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-09-18 11:02
    MJ,

    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
  • MJHanaganMJHanagan Posts: 189
    edited 2012-09-18 11:46
    My goal is to have the ZCPin transition reflect the true zero crossing point (within reason). I am using this input pin transition as the timing for trigger a random phase TRIAC driver. In one mode I want achive a nice quiet zero crossing on/off of the TRIAC and modulate the power by esentially PWM full or half line cycles of the mains. In the other operating mode I want to control the output power by phase angle triggering the the TRIAC.

    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?
  • jmgjmg Posts: 15,183
    edited 2012-09-18 16:59
    That's a lot of parts for a ZCD, and a rather low value resistor to the mains too...

    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.
  • MJHanaganMJHanagan Posts: 189
    edited 2012-09-18 17:08
    I copied the ZCD circuit out of an LM393 datasheet. Can you provide a schematic for your ZCD circuit?
  • Mark_TMark_T Posts: 1,981
    edited 2012-09-18 17:13
    Ariba wrote: »
    Yes I would reduce the value of R16 to 1MOhm or even lower. And if it is not too hard I would also make the pullup resistor R15 a bit more weak, perhaps 4.7 kOhm.

    Andy

    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.
  • jmgjmg Posts: 15,183
    edited 2012-09-18 17:51
    MJHanagan wrote: »
    I copied the ZCD circuit out of an LM393 datasheet. Can you provide a schematic for your ZCD circuit?
             1nF.HV  22Meg      68pF
    AC  -----||------/\/\/\---+--||--GND
                      VR68    |
                              |
                              +---74HC14--> Prop
    
    

    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.
  • AribaAriba Posts: 2,690
    edited 2012-09-18 18:40
    The simplest possible ZCD circuit:
    10Meg    
    120V AC -------/\/\/\-----> Prop Pin
    
    Without hystersis, but no active component which can amplify the noise, so it may work better then the Comparator circuit.

    Andy
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-09-18 20:50
    Here's a simple circuit that will provide transitions at the zero crossings (plus about 200 uSec) with no false counts at the transition points:

    attachment.php?attachmentid=95714&d=1348026516

    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
    567 x 247 - 3K
  • jmgjmg Posts: 15,183
    edited 2012-09-18 21:01
    Here's a simple circuit that will provide transitions at the zero crossings

    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 Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-09-18 21:04
    jmg wrote:
    Shouldn't those optos be reverse connected ? - so they alternate conduction ?
    Did you look at the schematic?

    -Phil
  • JonnyMacJonnyMac Posts: 9,194
    edited 2012-09-19 07:06
    I built a small, 4-channel AC lighting dimmer with the Propeller that was in fact an upgrade from the SX version I had done about six years ago. The SX inputs could be configured for Schmidt trigger mode which made the circuit easy. I forgot about this when moving to the Propeller and didn't add any circuitry to the ZC input (it's an H11AA1 opto with a pull-up on the output). What I ended up doing is a software debounce of the ZC signal; it's a tad brute force but works. Here's the relevant bit of code:
    ' This code debounces the ZC input to prevent noise from
    ' fouling the frequency detection
                            
    waitlo1                 mov     t1, #DB_CYCLES                  ' wait for low
    :loop                   test    zcmask, ina             wc
            if_c            jmp     #waitlo1
                            djnz    t1, #:loop
    
    waithi1                 mov     t1, #DB_CYCLES                  ' wait for leading edge of ZC
    :loop                   test    zcmask, ina             wc
            if_nc           jmp     #waithi1
                            djnz    t1, #:loop
    
                            neg     period, cnt                     ' start period measurement
    
    waitlo2                 mov     t1, #DB_CYCLES                  ' wait for falling edge of ZC
    :loop                   test    zcmask, ina             wc
            if_c            jmp     #waitlo2
                            djnz    t1, #:loop
    
    waithi2                 mov     t1, #DB_CYCLES                  ' wait for 2nd leading edge
    :loop                   test    zcmask, ina             wc
            if_nc           jmp     #waithi2
                            djnz    t1, #:loop
    
                            add     period, cnt                     ' stop timing
                            sub     period, #4                      ' remove overhead
    
                            wrlong  period, hubphase                ' save to hub        
                            shr     period, #8                      ' divide into 256 segments
    
Sign In or Register to comment.