Measuring duty cycle of short duration pulses with long period


Closed Thread
Results 1 to 13 of 13
  1. #1
    Join Date
    Jun 2005
    Location
    West Australia
    Posts
    116

    Default Measuring duty cycle of short duration pulses with long period

    Hi All,

    I want to measure the Duty Cycle of piezo automotive (in particular diesel) injectors where typical idle on-time is 500us and full load is 1000us. Results will be used in a feedback loop to control other parameters. The clincher is shortest period will be around 20ms or 50hz frequency at maximum revs so the pulses are far between noting only one cylinder's injector needs to be monitored.

    With gasoline solenoid injectors this is easy as their on-time is measured in ms so DC math follows the traditional (on-time*100)/off-time.

    I can probably rig up some analog stuff to integrate the pulses and then scale the output voltage in A2D measurement but the varying frequency component will have major effects and is totally devoid of digital precision in the acquisition section.

    I can't think of any way to measure/calculate DC without first defining what 100% DC is in microseconds - can this be done otherwise in real time? PIC of choice is 16F88 but can be changed if required.

    All suggestions appreciated.

    Regards,
    Bill

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,518


    Did you find this post helpful? Yes | No

    Default Re: Measuring duty cycle of short duration pulses with long period

    What sort of resolution do you need and what is the longest period (minimum rpm) you're expecting?

    On rising edge of signal, start timer.
    On falling edge of signal, read timer, this is the "on-time".
    On next rising edge of signal, stop timer, this is the period time. While waiting here you need to keep track of the number of overflows that occurs and add up the total time.

    /Henrik.

  3. #3
    Join Date
    Jun 2005
    Location
    West Australia
    Posts
    116


    Did you find this post helpful? Yes | No

    Default Re: Measuring duty cycle of short duration pulses with long period

    Hi Henrik,

    Thanks for the reply - I knew I could count on you for some helpful advice.

    I understand the concept you've mentioned and have this working with good results - if I state 100% DC is 1000us. I'm using a 12F683 with 2 pots to emulate the engine, one for variable frequency (5-55hz = 600-6600rpm) the other for variable pulse width (0-1000us) and a switch for pulse polarity choice. Resolution needs to be 10us (equivalent to 1% DC).

    How do I track the overflows? I've not delved into timers before this.

    Thanks for your help as always,
    Bill

  4. #4
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,518


    Did you find this post helpful? Yes | No

    Default Re: Measuring duty cycle of short duration pulses with long period

    Hi Bill,
    Your definition of dutycycle differs from mine but I think I understand what you want.
    The period (on-time + off-time) of the signal is 18-200ms and the on-time is 500-1000us. You want to measure the dutycycle, ie the ratio between on-time and period.

    If the period is 125ms and the on-time is 565us the dutycycle is 4.52%.
    If the period is 45ms and the on-time is 795us the dutycycle is 17.66%.

    Is this the number you're after?

    Let's see if we can make this easy....
    The longest time you want to measure is 200ms. Using a 16bit timer with a 4us "tick" you'll measure up to 262ms with 4us resolution without having to worry about overflows. Then the overflow can be used to signal invalid mesasurment (motor not running).

    Are we on the right track?

    /Henrik.

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,518


    Did you find this post helpful? Yes | No

    Default Re: Measuring duty cycle of short duration pulses with long period

    795us over 45ms is 1.76%, not 17.6% as I wrote earlier.

    Anyway, here's a piece of code that may do what you want. It uses TMR1 and CCP1 to measure the input signal, calculates the dutycycle and displays it with .1% resolution. It compiles for a 16F88 but I have not tested it.
    Code:
    ' Program expects 4MHz oscillator.
    ' CCP1 inputpin is either RB0 or RB3 depending on the CCPMX bit in CONFIG.
    
    CapRise CON %00000101		' Value to configure CCP1 for capturing every rising edge
    CapFall CON %00000100		' Value to configure CCP1 for capturing every falling edge
    
    CCP1IF 	VAR PIR1.2		' Alias to CCP1 Interrupt flag
    
    Period 	VAR WORD
    Width 	VAR WORD
    Duty 	VAR WORD
    Dummy	VAR WORD
    
    T1 	VAR WORD
    T2 	VAR WORD
    T3 	VAR WORD
    
    T1CON = %00100001		' TMR1 clock from FOsc/4, Prescaler 1:4
    
    Main:
        ' Capture the the time where the pulse starts
        CCP1CON = CapRise
        CCP1IF = 0
        WHILE !CCP1IF : WEND
        T1.HIGHBYTE = CCPR1H : T1.LOWBYTE = CCPR1L
    
        ' Capture the time where the pulse ends
        CCP1CON = CapFall
        CCP1IF = 0
        WHILE !CCP1IF : WEND
        T2.HIGHBYTE = CCPR1H : T2.LOWBYTE = CCPR1L
    
        ' Capture the time where the period ends (which is when the next pulse starts) 
        CCP1CON = CapRise
        CCP1IF = 0
        WHILE !CCP1IF : WEND
        T3.HIGHBYTE = CCPR1H : T3.LOWBYTE = CCPR1L
    
    
        Width = T2 - T1
        Period = T3 - T1
        Dummy = Width * 1000
        Duty = DIV32 Period
    
        ' Duty is now in units of .1% (111 = 11.1%)
    
        LCDOUT $FE, 1, "W:", DEC Width, " P:", DEC Period
        LCDOUT $FE, $C0, "Duty:", DEC Duty/10, ".", DEC Duty//10, "%"
    
    Goto Main
    /Henrik.

  6. #6
    Join Date
    Oct 2012
    Posts
    81


    Did you find this post helpful? Yes | No

    Default Re: Measuring duty cycle of short duration pulses with long period

    I’m not sure how much this will change things but shouldn’t maximum period expected be 20 ms not 200 ms?
    And if it is so, should the timer setup be changed or it will still work?

    Nick

  7. #7
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,518


    Did you find this post helpful? Yes | No

    Default Re: Measuring duty cycle of short duration pulses with long period

    Hmm, if maximum period is 20ms then the timer would need to be reconfigured but Bill said: variable frequency (5-55hz = 600-6600rpm). At 5Hz the period is 200ms, at 55Hz the period is 18ms. So the the timer must be able to measure at least 200ms. Or am I doing a stupid mistake somewhere?

    /Henrik.

  8. #8
    Join Date
    Oct 2012
    Posts
    81


    Did you find this post helpful? Yes | No

    Default Re: Measuring duty cycle of short duration pulses with long period

    No Henrik, as usual I'm wrong.
    Sorry for false alarm.

    Nick

  9. #9
    Join Date
    Jun 2005
    Location
    West Australia
    Posts
    116


    Did you find this post helpful? Yes | No

    Default Re: Measuring duty cycle of short duration pulses with long period

    Hi Henrik,

    Thanks for your help and code sample, I'll use this as a guide for other timing tasks if it doesn't work for this particular role.

    I understand the ratio calcs for Duty Cycle and have done this a few times before, but with gasoline injectors where their on time is proportional i.e. let's say max rpm limits maximum duty cycle to 20ms. In such circumstances DC is easy - 10ms = 50%, 20 = 100%, etc.

    But with modern diesel common-rail injectors (extremely high fuel pressure so inj open times are in microseconds) the ratio between on-times and period blows out so much to be unusable in normal math for DC. It doesn't need to be exact but does need to be reliable and repeatable as DC will form an axis in a lookup table to control vnt turbo characteristics and boost curve via a PWM solenoid valve. I will start a different thread soon and request suggestions on how to do 3D mapping.

    It's a catch-22 situation in that I don't know what a particular engine's max DC is unless fully loaded on a dyno and 'scope measurements are taken - expensive. In a gasoline engine this isn't needed due conventional math taking care of it. I can make an educated guess and set the diesel's max DC as 1000us (typical full load) then measure on-the-fly using this as the reference to derive some data as the engine is loaded - if it exceeds 100% then code could update the ref and store this along with the max pulse length... do you see another way?

    Kind regards,
    Bill

  10. #10
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,518


    Did you find this post helpful? Yes | No

    Default Re: Measuring duty cycle of short duration pulses with long period

    OK, so you're not really interested in the actual dutycycle of the signal.
    You're interested in how long the pulse is relative to its maximum length and the pulse maximum length is NOT equal to the period of the signal (which would be 100% duty cycle by the standard definition).

    This means that the timer doesn't need to be able to resolve the complete period of the signal, only the maximum width of the pulse - and this is good because it increases your resolution substantially. All you need to do then is to capture the TMR1 value on the rising edge and then capture again on the falling edge, that's your actual width. Calculate percentage relative your maximum width.

    You could certainly guestimate the initial value (1000us) and the apply some "adaptive learning" to the code.

    /Henrik.

    (This was my $0BB8 post, yay)
    Last edited by HenrikOlsson; - 10th February 2017 at 09:13.

  11. #11
    Join Date
    Jun 2005
    Location
    West Australia
    Posts
    116


    Did you find this post helpful? Yes | No

    Default Re: Measuring duty cycle of short duration pulses with long period

    Hi Henrik,

    Yes, I think conventional DC doesn't apply here. Thanks for the confirmation of what needs to be done.

    Congrats on the milestone in postings - makes my $32 look fairly miserable in comparison

    Cheers,
    Bill

  12. #12
    Join Date
    Jun 2005
    Location
    West Australia
    Posts
    116


    Did you find this post helpful? Yes | No

    Default Re: Measuring duty cycle of short duration pulses with long period

    Hi All,

    I've done some research and have found modern diesels have multiple fuel injection events such is the speed of the piezo injectors with extremes of fuel pressure to pass. Events typically number up to 5 but some documents suggest up to 8.

    So my goal has changed slightly whereby I now want to capture each of these events and sum their duration for maximum fuel injected and also record the longest pulse (if 5 events this is most likely the middle one). I can use tmr1 for capturing each pulse's duration but I want to limit recording of valid events to a 4ms window (triggered by first pulse edge) and am not doing too well manipulating tmr0 using Darrel's Instant Interrupts. I really need to embrace these and use more often...

    The full code (work in progress!) shows what I am trying to do but without success. As written Led2 pulses about 1hz and I only see a 4ms flash if the asm parts are commented out - but then pulse values are wild and erratic.

    How does one start and stop DT's Ints or is there a better way to control a 4ms window. All advice is greatly appreciated.

    Cheers,
    Bill

    Code:
    '****************************************************************************************************
    '*  Name    : Pulses Timer.pbp                                                                      *
    '*  Date    : 25-02-17                                                                              *
    '*  Device  : 16F648A (4k code space).                                                              *
    '*  Version : 1.0                                                                                   *
    '*  Notes 1 :  words with (PBP 3.0.6.4)  with thanks to Darrel Taylor for his ISR.                  *    
    '*          : 											                                            *
    '*          : Uses DT's Instant Interrupts with Tmr0 for a 4ms window and Tmr1 for pulse duration.  *
    '*          : 											                                            *
    '*          : The code records multiple injection events within a 4ms window and combines all for   *
    '*          : total fuel time, also takes longest pulse and self adjusts reference duration if it   *
    '*          : exceeds current set DutyCycle value.  A low value first read from EEPROM allows early *
    '*          : updates to the LCD.  Updated value can be saved to EEPROM by pushbutton control.      *
    '*          : 											                                            *
    '*          : A switch sets expected polarity of the incoming pulses - normally high pulsing low as *
    '*          : measured at injector [usual] or normally low pulsing high at ecu output [possible].   *
    '*          : 											                                            *
    '*          : 											                                            *
    '****************************************************************************************************
    '
    ' LCD     	PIC(F648A)          OTHER		
    '
    ' DB0-3   	No connection
    ' DB4     	PortA.0 (pin 17)    
    ' DB5     	PortA.1 (pin 18)    
    ' DB6     	PortA.2 (pin 1)     
    ' DB7     	PortA.3 (pin 2)     
    ' RS      	PortA.4 (pin 3)     10K pullup to 5v due Open Drain.
    '           MCLR    (pin 4)     10k pullup to 5v.
    ' RW      	Ground  (pin 5)
    ' Vdd     	5 volts (pin 14)			
    ' Vss     	Ground  (pin 5)				
    ' Vo      	                    20K LCD contrast potentiometer wiper (or ground).
    '       	PortB.0 (pin6)      Set button (10k pullup to 5v).		
    ' 		    PortB.1 (pin7)	    + button (10k pullup to 5v).
    '		    PortB.2 (pin 8)     - button (10k pullup to 5v).  Hardware serial port Rx.
    '   (CCP1)	PortB.3 (pin 9)     Input for Pulses/Duty Cycle via 1k.
    '		    PortB.4 (pin 10)    Polarity of pulse switch - Pulled up. 		
    '		    PortB.5 (pin 11)	
    '		    PortB.6 (pin 12)    
    ' 		    PortB.7 (pin 13)    Debug in via 22k. 
    '    Xtal   PortA.6 (pin 15)    Debug out via 1k.      
    ' E  Xtal   PortA.7 (pin 16)        
    
    '=========================================================================================================
    '        CONFIGURE DEVICE 
    '=========================================================================================================
    ' The config can set RB0 or RB3 for CCP1 capture use. Confirm by viewing the fuses code box via the programmer.
    #CONFIG
        __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_OFF & _MCLRE_ON & _LVP_OFF & _CP_OFF
    #ENDCONFIG
    
    wsave   VAR BYTE    $70     SYSTEM      ' Save location for W 
    
    ' -----[ Initialization ]------------------------------------------------------------------------------------------------ 
        CMCON = 7         	    ' Disable analog comparators.
        T1CON = 0               ' TIMER1: Clock Internal, Pre-scaler 1:1
        
    	Define 	OSC    4        ' Set Xtal Frequency
    
    ' Define LCD connections       Change these to match your LCD 
        DEFINE  LCD_DREG        PORTA	' LCD Data Port
        DEFINE  LCD_DBIT        0		' Starting Data Bit
        DEFINE  LCD_RSREG       PORTA	' Register Select Port
        DEFINE  LCD_RSBIT       4		' Register Select Bit
        DEFINE  LCD_EREG        PORTA	' Enable Port
        DEFINE  LCD_EBIT        7		' Enable Bit
        DEFINE  LCD_BITS		4		' Data Bus Size
        DEFINE  LCD_LINES		2		' Number of Lines on LCD
    
        DEFINE DEBUG_REG PORTA      ' Port_A outgoing serial communication.   
        DEFINE DEBUG_BIT 6
        DEFINE DEBUG_BAUD 9600
        DEFINE DEBUG_MODE 1         ' Debug mode: 0 = True, 1 = Inverted
    
    'Includes
    	Include "Modedefs.bas"      ' Mode definitions for Debug, Serin/out, Shiftin/out, Xin/out.
        INCLUDE "DT_INTS-14.bas"    ' Base Interrupt System
        INCLUDE "ReEnterPBP.bas"    ' Include if using PBP interrupts 
    
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR0_INT,  _ToggleLED2,   PBP,  yes
        endm
        INT_CREATE             ; Creates the interrupt processor
    ;    INT_ENABLE  TMR0_INT   ; enable Timer 0 interrupts.  [WJS] normally enabled here but not for this app. as it
    ENDASM                     ; is only enabled when required for the timing windows.
    
    ' OPTION_REG = %10010011    ; Prescale of 16 will give 4ms interrupt (8ms period).
     OPTION_REG = %10010010    ; Prescale of 8 will give 2ms interrupt (4ms period).
    
        Data "Pulses Timer",word 400 ' Next locn is 14.
        
    '=========================================================================================================
    '        PIN ASSIGNMENTS, SYSTEM CONSTANTS, TEMPORARY VARIABLES
    '=========================================================================================================
    ' Alias pins
    Set         var     PORTB.0     ' Set button.
    Plus        var     PORTB.1     ' + button.
    Minus       var     PortB.2     ' - button.
    SignalInput var     PORTB.3     ' Input pulses pin.
    Polar       var     PORTB.4     ' Polarity switch for output pin - normal high going low or normal low going high.
    LED2        var     PORTB.7     ' LED for Tmr0 testing.
    
    ' Variables       
        PulseHigh1      var word    ' Width of 1st +ve going pulse, idling low.
        PulseLow1       var word    ' Width of 1st -ve going pulse, idling high.
        PulseHigh2      var word    ' Width of 2nd +ve going pulse, idling low.
        PulseLow2       var word    ' Width of 2nd -ve going pulse, idling high.
        PulseHigh3      var word    ' etc...
        PulseLow3       var word    ' 
        PulseHigh4      var word    ' 
        PulseLow4       var word    ' 
        PulseHigh5      var word    ' 
        PulseLow5       var word    ' 
        SumPulseHigh    var word    ' Sum of Widths of +ve going pulses, idling low.
        SumPulseLow     var word    ' Sum of Widths of -ve going pulses, idling high.
        DC100           var word    ' Value of 100% Duty Cycle for math calcs despite frequency.
        Dummy           var Word    ' For Div32 math.
        DutyCycle       var word    ' Percentage of pulse ratio wrt DC100.
        MaxPulse        var word    ' Max pulse measured - should always be the Main injection pulse.
        x               var word    ' Loop counter.
        Events          var byte    ' Number of inj pulses per cycle.
        Sign            var byte    ' + or - sign for serial indication of polarity.
        Window          var bit     ' Event window - limits time when pulses are valid. 1 = open, 0 = closed.
    
    ' Alias Definition
        T1ON    var T1CON.0
    
    ' Software/Hardware initialisation         
        CLEAR
        TRISA = %00001111           ' PORTA I/O.
        TRISB = %10011111           ' RB3 as input for pulses, RB4 is polarity select switch.
        PortA.6 = 0                 ' Set low for serial debug idle state.
    
        read 12,word DC100          ' Read initial value of stored DutyCycle (start with 400).
        MaxPulse = 0                ' Reset count - can only get bigger from here.
        Events = 0                  ' Reset count.
        GOSUB ClearTimer
    
    First:      ' Operation when system first powered up. 
    ' Load custom characters to LCD CGRam memory.
        LCDOUT $FE,64                           ' Set CGRam mode.
        LCDOUT $FE,$40,15,9,9,9,9,9,9,25        ' Cust Char #0 +ve pulse symbol.
        LCDOUT $FE,$48,25,9,9,9,9,9,9,15        ' Cust Char #1 -ve pulse symbol.
        LCDOUT $FE,1,$FE,2                      ' Exit CGRam mode, Clear screen and home cursor.
        
        goto Start                              ' Jump subs.
    
    '=========================================================================================================
    ' Subroutines here in the first page...         
    '=========================================================================================================
    ClearTimer:
        TMR1L=0
        TMR1H=0
        RETURN
    
    AdjustDC100:        
        for x = 0 to 99        ' 100 cycles.
        LCDOUT $FE,2,"DC 100% = ",dec4 DC100,"us"
        LCDOUT $FE,$C0,"    Set + -     "
        if plus = 0 then       ' + pushed.
            DC100=DC100+10     ' increment in 10us lumps.
            pause 50
        else
            if Minus = 0 then  ' - pushed.
            DC100=DC100-10     ' decrement in 10us lumps.
            pause 50
            endif
        endif
        pause 100              ' .1*100 = 10 second loop.
            If Set = 0 then    ' Set is pushed.
            While Set = 0      ' If still pressed then wait -
            PAUSE 5            ' - until released.
            Wend
            write 12,DC100.lowbyte  ' Store new value in EEPROM.
            write 13,DC100.Highbyte ' Store new value in EEPROM.
            LCDOUT $FE,$C0," Stored okay... "
            pause 2000         ' Time to read it.
            return             ' Jump out once done.
            endif
        next
        return
    
    '=========================================================================================================
    ' Program area...
    '=========================================================================================================
    Start:
    ' Check if buttons pushed.
        If plus = 0 then            ' Plus button pushed.
            While plus = 0          ' If still pressed then wait -
            PAUSE 5                 ' - until released.
            Wend
            gosub AdjustDC100
        endif 
    
        If Minus = 0 then           ' Minus button pushed.
            While Minus = 0         ' If still pressed then wait -
            PAUSE 5                 ' - until released.
            Wend
            MaxPulse = 0            ' Reset Max.
        endif 
    
    ' Check Polarity switch state.
        if polar = 1 then           ' Switch open - this pin sits high due pullup, expects high pulse.
            sign = "+"              ' expecting high pulse.
            LCDOUT $FE,2,1          ' Cust Char #1 +ve pulse Line 1 posn 1.
            goto GetHighs           ' Jump to routine.
        endif                       
        
        if polar = 0 then           ' Switch closed - this pin sits low, expects low pulse.
            sign = "-"              ' expecting low pulse.
            LCDOUT $FE,2,0          ' Cust Char #0 -ve pulse Line 1 posn 1.
            goto GetLows            ' Jump to routine.
        endif
    
    GetHighs:   ' Measure high pulses
        WHILE SIGNALINPUT = 0       ' Waiting for rising edge.
        WEND
    
    ' Start timers - a rising edge has been detected to get here.
    @    INT_ENABLE  TMR0_INT       ; Enable Tmr0 interrupts for 4ms window.
     Window = 1                     ' Open the pulse count window.
     while Window = 1               ' 
     T1ON = 1                       ' Start Pulse Timer tmr1.
        WHILE SIGNALINPUT = 1       ' Wait for next falling edge.
        WEND
    
     T1ON = 0                       ' Stop timer.
        Events = 1                  ' 
        PULSEhigh1.HIGHBYTE=TMR1H   ' Store results. 
        PULSEhigh1.LOWBYTE=TMR1L    '
        if PULSEhigh1 > MaxPulse then
            MaxPulse = PULSEhigh1   ' Capture longest pulse.
        endif
        gosub Cleartimer            ' Reset Timer1 register (TMR1L, TMR1H).
    
    ' Capture additional high pulses
        WHILE SIGNALINPUT = 0       ' Waiting for rising edge.
        WEND
     T1ON=1                         ' Start Pulse Timer tmr1.
        WHILE SIGNALINPUT = 1       ' Wait for next falling edge.
        WEND
    
     T1ON = 0                       ' Stop timer.
        Events = 2                  ' 
        PULSEhigh2.HIGHBYTE=TMR1H   ' Store results. 
        PULSEhigh2.LOWBYTE=TMR1L    '
        if PULSEhigh2 > MaxPulse then
            MaxPulse = PULSEhigh2   ' Capture longest pulse.
        endif
        gosub Cleartimer            ' Reset Timer1 register (TMR1L, TMR1H).
    
        WHILE SIGNALINPUT = 0       ' Waiting for rising edge.
        WEND
     T1ON=1                         ' Start Pulse Timer tmr1.
        WHILE SIGNALINPUT = 1       ' Wait for next falling edge.
        WEND
    
     T1ON = 0                       ' Stop timer.
        Events = 3                  ' 
        PULSEhigh3.HIGHBYTE=TMR1H   ' Store results. 
        PULSEhigh3.LOWBYTE=TMR1L    '
        if PULSEhigh3 > MaxPulse then
            MaxPulse = PULSEhigh3   ' Capture longest pulse.
        endif
        gosub Cleartimer            ' Reset Timer1 register (TMR1L, TMR1H).
    
        WHILE SIGNALINPUT = 0       ' Waiting for rising edge.
        WEND
     T1ON=1                         ' Start Pulse Timer tmr1.
        WHILE SIGNALINPUT = 1       ' Wait for next falling edge.
        WEND
    
     T1ON = 0                       ' Stop timer.
        Events = 4                  ' 
        PULSEhigh4.HIGHBYTE=TMR1H   ' Store results. 
        PULSEhigh4.LOWBYTE=TMR1L    '
        if PULSEhigh4 > MaxPulse then
            MaxPulse = PULSEhigh4   ' Capture longest pulse.
        endif
        gosub Cleartimer            ' Reset Timer1 register (TMR1L, TMR1H).
    
        WHILE SIGNALINPUT = 0       ' Waiting for rising edge.
        WEND
     T1ON=1                         ' Start Pulse Timer tmr1.
        WHILE SIGNALINPUT = 1       ' Wait for next falling edge.
        WEND
    
     T1ON = 0                       ' Stop timer.
        Events = 5                  ' 
        PULSEhigh5.HIGHBYTE=TMR1H   ' Store results. 
        PULSEhigh5.LOWBYTE=TMR1L    '
        if PULSEhigh5 > MaxPulse then
            MaxPulse = PULSEhigh5   ' Capture longest pulse.
        endif
        gosub Cleartimer            ' Reset Timer1 register (TMR1L, TMR1H).
     wend   
    
        sumpulsehigh = pulsehigh1 + pulsehigh2 + pulsehigh3 + pulsehigh4 + pulsehigh5
        dummy = MaxPulse*100        ' Perform the multiply ready for Div32.
        DutyCycle = div32 DC100     ' Calculate wrt stored value. 
    
    ' ### NB debug affected by interrupts!
    'debug "Pol ",sign,", MaxPulse ",dec4 MaxPulse,"us, Events ",#Events,13 
        LCDOUT $FE,2,0," Inj ",dec4 maxpulse,"us Max"  ' Write LCD line 1.
        goto ShowMore               ' Jump GetLows.
    
    '===============================================================================================================
    GetLows:    ' Measure low pulses
     while Signalinput = 1          ' Waiting for falling edge.
     Wend
    ' Start timers - a falling edge has been detected to get here.
    @    INT_ENABLE  TMR0_INT       ; Enable Tmr0 interrupts for 5ms window.
        Window = 1                  ' Open the pulse count window.
     while Window = 1               ' ### is the first line needed?
     T1ON = 1                       ' Start timer1.
        WHILE SIGNALINPUT = 0       ' Wait for next rising edge.
        WEND
    
     T1ON = 0                       ' Stop Timer.
        Events = 1                  ' 
        PULSElow1.HIGHBYTE = TMR1H  ' Store result.
        PULSElow1.LOWBYTE = TMR1L   '    
        if PULSElow1 > MaxPulse then
            MaxPulse = PULSElow1    ' Capture longest pulse.
        endif         
        gosub Cleartimer            ' Reset Timer1 register (TMR1L, TMR1H).
    
    ' Capture additional low pulses
        while Signalinput = 1       ' Waiting for falling edge.
        WEND
     T1ON = 1                       ' Start timer1.
        WHILE SIGNALINPUT = 0       ' Wait for next rising edge.
        WEND
    
     T1ON = 0                       ' Stop Timer.
        Events = 2                  ' 
        PULSElow2.HIGHBYTE = TMR1H  ' Store result.
        PULSElow2.LOWBYTE = TMR1L   '    
        if PULSElow2 > MaxPulse then
            MaxPulse = PULSElow2    ' Capture longest pulse.
        endif         
        gosub Cleartimer            ' Reset Timer1 register (TMR1L, TMR1H).
    
        while Signalinput = 1       ' Waiting for falling edge.
        WEND
     T1ON = 1                       ' Start timer1.
        WHILE SIGNALINPUT = 0       ' Wait for next rising edge.
        WEND
    
     T1ON = 0                       ' Stop Timer.
        Events = 3                  ' 
        PULSElow3.HIGHBYTE = TMR1H  ' Store result.
        PULSElow3.LOWBYTE = TMR1L   '    
        if PULSElow3 > MaxPulse then
            MaxPulse = PULSElow3    ' Capture longest pulse.
        endif         
        gosub Cleartimer            ' Reset Timer1 register (TMR1L, TMR1H).
    
        while Signalinput = 1       ' Waiting for falling edge.
        WEND
     T1ON = 1                       ' Start timer1.
        WHILE SIGNALINPUT = 0       ' Wait for next rising edge.
        WEND
    
     T1ON = 0                       ' Stop Timer.
        Events = 4                  ' 
        PULSElow4.HIGHBYTE = TMR1H  ' Store result.
        PULSElow4.LOWBYTE = TMR1L   '    
        if PULSElow4 > MaxPulse then
            MaxPulse = PULSElow4    ' Capture longest pulse.
        endif         
        gosub Cleartimer            ' Reset Timer1 register (TMR1L, TMR1H).
    
        while Signalinput = 1       ' Waiting for falling edge.
        WEND
     T1ON = 1                       ' Start timer1.
        WHILE SIGNALINPUT = 0       ' Wait for next rising edge.
        WEND
    
     T1ON = 0                       ' Stop Timer.
        Events = 5                  ' 
        PULSElow5.HIGHBYTE = TMR1H  ' Store result.
        PULSElow5.LOWBYTE = TMR1L   '    
        if PULSElow5 > MaxPulse then
            MaxPulse = PULSElow5    ' Capture longest pulse.
        endif         
        gosub Cleartimer            ' Reset Timer1 register (TMR1L, TMR1H).
    '    Window = 0                  ' Close the pulse count window.  #### Testing - Int should do this.
     wend
        
        sumpulselow = pulselow1 + pulselow2 + pulselow3 + pulselow4 + pulselow5
        dummy = maxpulse*100        ' Perform the multiply ready for Div32.
        DutyCycle = div32 DC100     ' Calculate wrt stored value. 
    
    ' ### NB affected by interrupts!
    'debug "Pol ",sign,", MaxPulse ",dec4 MaxPulse,"us, ",#Events," Events, SumPulseLow = ",#sumpulselow,13
        LCDOUT $FE,2,0," Inj ",dec4 PULSElow3,"us Max"  ' Write LCD line 1.
            
    ShowMore:    
        LCDOUT $FE,$C0,"DC",DEC2 DutyCycle,"% ",dec4 DC100," ",dec5 MaxPulse    ' Write LCD line 2.
        pause 500                   ' Time to read.
                
        goto start
        
    '---[TMR0 - interrupt handler]-------------
    ToggleLED2:
        Window = 0                  ' Close the window for pulse counting.
        TOGGLE LED2                 ' LED2 flashes, timed by TMR0.
    @    INT_DISABLE  TMR0_INT      ; Disable Tmr0 interrupts ready for next window.    
    @ INT_RETURN                    ; Return to point where interrupt took place.
                      
    end

  13. #13
    Join Date
    May 2013
    Location
    australia
    Posts
    2,386


    Did you find this post helpful? Yes | No

    Default Re: Measuring duty cycle of short duration pulses with long period

    an alternative approach could be to use a chip with timer1 gate control.
    if the timer gate was connected to the injector signal and the timer read and reset at a metered rate
    the count would be directly proportional to the injector ontime [effectively a digital integrator].
    it should not be too difficult to find a suitable timer clock rate and integration period to suit.
    Warning I'm not a teacher

Similar Threads

  1. Count Pulses and duration
    By ruijc in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 13th February 2014, 23:04
  2. Measuring Period of a pulse
    By c_moore in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 17th February 2012, 06:15
  3. Measuring duty cycle when it can be 0 to 100.
    By Tobias in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 3rd December 2011, 19:24
  4. Pin max current - short duration?
    By kevj in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 2nd January 2008, 13:53
  5. Measuring Period & Hz
    By MaurI in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 29th July 2005, 05:03

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts