Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Pulse width timing: 16F non enhanced PIC challenge

Status
Not open for further replies.

Mosaic

Well-Known Member
I wanted to get a bit of feedback on this approach, thx for reading.

Constraints

1) 16F886 @ 8 Mhz
2) CCP/ECCP pins not available
3) T0CK available
4) TMR1 (16 bit) running at 2Mhz Fosc.
5) External Pulse period around 2000 µS.
6) Pulse width from 5 µS to 300 µS
7) External Pulse period NOT synced to Fosc.
8) Accuracy desired : ±1µS
9) Interrupt processing overhead: 30µS

Possible Solution
Preset TMR0 (setup as counter) to 255, rising edge triggered as the external pulse input.
Pulse #1 T0IF (rising edge) interrupt servicing:
a) the TMR1L & TMR1H bytes are buffered as 'Time1' word.
b) T0SE set to falling edge and TMR0 reset to 255, T0IF cleared just before RETFIE.

Pulse#2 (falling edge) T0IF servicing:
a) If this 'Time2' - Time1 is < 400µS then Pulse Width = Time2-Time1.
b)Otherwise sample NEXT rising edge and calc. for Pulse Width.Can set a 'flag' to note this condition.
Within current T0IF servicing, reset T0SE to rising edge, Tmr0 to 255, clrf T0IF and RETFIE
Pulse#3 (rising edge) T0IF servicing
a)based on pulse#2 'flag' set, Pulse width = Time2-{(Time3+Time1)/2}
b) if 'flag' clear then Pulse width was obtained in Pulse#2 and the loop repeats as the Pulse#3 setup ≡ Pulse#1 setup


EDIT:
Conclusion:
For those interested, the reliable solution required transferring TMR1 duties to TMR2 and utilising the T1 Gate feature coupled with a falling edge T0CK interrupt to obtain automated updates of the most recent pulse width. Both PWM channels remain available as no capture event was required.
 
Last edited:
Ok, I tested the approach and it works quite well. It's a bit of a relief as I had about 6000 lines of asm invested in the 16F886 and I didn't want to have to change the chip.
The project suffered feature creep and the PIC is maxed out on I/O as well as internal features. I think only the comparators aren't used, as I needed the pins for I/O.

If I had to I would prob. have gone to a 16F1936 as it's pin compatible with more internal features & timers, hardware context saving and a 4x clock.
 
Another approach to pulse width timing is via the timer 1 gating pin (T1G). This holds the timer until a positive going pulse is present on the T1G pin, and the timer runs for as long as T1G is held high. Poll the pin until it goes low, then read the timer value and convert.
 
Thanks Jon.
Won't work here though as the Tmr1 runs other timing sensitive interrupts to maintain a system clock and LCD display and so forth. It is the main timer and can't be stopped.
I also lean towards a interrupt based timing activity as opposed to polling.
 
There's no way in the world you can measure 5us pulse width through the interrupts with 30us processing time. The signal will go low during your processing, and you'll never know whether it's been on for 5us or 25us.

You may be able to satisfy 1us accuracy requirement, but not easily, and only if you don't have any other interrupts. Otherwise, if rising edge comes when you process the other interrupt, your measurement is screwed.

Gated timer is the only way to achive your requirements in the absense of CCP.
 
The pulse width in question is sourced from the square wave generated by a TL494 PWM signal.
The timebase period is ≈2000µS fixed, pulse width is variable.
The solution used can and does measure down to 5 µS. Even with other interrupts running.
If you read it carefully you'll see how that works.
 
At 8 mhz clock don't it take longer then ten cycles to run need code. Just wondering
 
I see. So, the period is not "around 2000us", but fixed with 1us accuracy. This changes things.

Other interrupts simply have an effect of increased latency. The other interrupt is doing something, then the falling edge happens, then the other interrupt continues to do whatever it does, then it finishes, and only after this you get your "falling edge" interrupt and lock your Time2, which can be quite a bit after the falling edge. In your method you assume fixed latency.
 
Not quite.
The method corrects for 'missed' falling edges based on the limit of about 300µS for the peak pulse width (DTC limited). Anything over that means a missed edge or more.
 
Why can't you use the CCP? Are you using the pin for something else??? What I do in these situations is put a little pic12f1840 in the circuit somewhere and do the timing with that... It has a precision 32Mhz internal crystal and enhanced CCP modules... You can just output you results serially!!

Whoops sorry!!! You are using timer1... Shame as there are two CCP modules on that chip

How much work is needed to move your tmer1 stuff to timer2??
 
Ok,let's look at freeing timer 1:
It's setup for 0.977 µS interrupts right now which makes a 1024 count = 1.000mS. I can make do with a 2.000mS interrupt.

Tmr2 is running at 8µS per count or 2.048mS per roll over. It also handles the PWM clock.
Ideally, i'd want to make that rollover/interrupt happen at 2.000mS. So each time the Tmr2IF hits, Tmr2 is incremented by 6 so it actually counts 250 before the next rollover = 2.000mS.
That allows proper time keeping for sec/minutes/hours/days.

Now, what happens to the 10 bit PWM duty cycles with this alteration to the smooth TMR2 count? I don't know.
 
Not quite.
The method corrects for 'missed' falling edges based on the limit of about 300µS for the peak pulse width (DTC limited). Anything over that means a missed edge or more.

It is not about missing edges, but about latency. Look at this time line with 100us pulse width. 0us mark is the rising edge.

-5 us. Some other unrelated interrupt starts
0us. Rising edge
25us. The other interrupt ends
27us. Your interrupt starts
35us. You mark Time1
57us. Your interrupt stops
100us. Falling edge
102us. Your interrupt starts
110us. You mark Time2

Time2 - Time1 =110 - 35 = 75us instead of 100us correct reading.

Opposite scenario.

0us. Rising edge
2us. Your interrupt starts
10us. You mark Time1
30us. Your interrupt stops
95us. Some other unrelated interrupt starts
100us. Falling edge
125us. The other interrupt ends.
127us. Your interrupt starts
135us. You mark Time2

Time2 - Time1 = 135 - 10 = 125us instead of 100us correct reading.

Makes sense?
 
It's setup for 0.977 µS interrupts right now which makes a 1024 count = 1.000mS.
??? HOW

8Mhz yields a TCy of .5uS so .5uS * 1024 = 512uS and 1uS = 1024uS....

Have I missed something...
 
@ Ian Rogers, you can configure the Tmr1 interrupt to happen at different intervals based on presetting it's starting value so when it rolls over at 0 the interrupt happens. then that interrupt tick is used to form the fundamental timebase of a clock. eg 1 second.
The 0.977 should be in mS not µS! Ain't slept in 24 hours.
It's setup for 0.977 mS interrupts right now which makes a 1024 count = 1.000S.
NorthGuy I have encountered the problem you describe and am proceeding to 'free' TMR1 to use the T1G approach!
 
Last edited:
Ok, I got the T1G working , plus I tied it to the T0CK interrupt(falling edge) to obtain the T1G pulse width sample without polling.
TMR2 now runs the system Clock (sec/min/hour) and the LCD 16x2 update buffer refresh.
 
The 0.977 should be in mS not µS! Ain't slept in 24 hours.
Its okay... It happens to us all. I actually assumed as much...

Your minimum pulse width??? Is that 5uS or 5mS?...

I have also ( a couple of times ) used the timers for two different devices.... You just need to find a common ground... Unfortunately in your case its 1uS.... So I can't help there either..
 
5µS - 255uS , is the range I am using. Proteus shows T1 gate working.

I have discovered a bug in ISIS PIC configs though.

ADCON1,VCFG1 enables the ext. Vref+ in ISIS rather than ADCON1,VCFG0 as per the PIC datasheet.
 
Status
Not open for further replies.

Latest threads

Back
Top