PDA

View Full Version : Measuring duty cycle of short duration pulses with long period



wjsmarine
- 6th February 2017, 01:32
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

HenrikOlsson
- 6th February 2017, 06:06
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.

wjsmarine
- 8th February 2017, 01:29
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

HenrikOlsson
- 8th February 2017, 07:48
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.

HenrikOlsson
- 8th February 2017, 19:48
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.

' 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.

NickMu
- 9th February 2017, 14:55
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

HenrikOlsson
- 9th February 2017, 17:02
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.

NickMu
- 9th February 2017, 17:54
No Henrik, as usual I'm wrong.
Sorry for false alarm.

Nick

wjsmarine
- 10th February 2017, 03:24
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

HenrikOlsson
- 10th February 2017, 07:56
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)

wjsmarine
- 11th February 2017, 08:33
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

wjsmarine
- 25th February 2017, 09:37
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



'************************************************* ************************************************** *
'* 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

richard
- 25th February 2017, 10:08
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.