Searching \ for 'Interrupt woes...' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: techref.massmind.org/techref/microchip/ints.htm?key=interrupt
Search entire site for: 'Interrupt woes...'.

Truncated match.
PICList Thread
'Interrupt woes...'
2000\02\07@053920 by oyvind

flavicon
face
Ok, guys.

I'm having some trouble, and I can't get it figured out.

I'm building a device that's sampling the RPM of an engine.
The incoming signal is therefore in the range of max 350 Hz, and it
is connected to RB0.

I need to accurately count the time *between* pulses, to get a number
that is inversely proportional to the RPM.

The TMR0 and the external interrupt is used. (16F84)

I've programmed the TMR0 to run with a prescaler of 1:2, so the TMR0
frequency should be 1.25 MHz.

I want to have a 16 bit counter, so in the interrupt routine I
increment a register for each TMR0 interrupt. This is the high byte
of my counter.

When the external interrupt occurs, I read both the TMR0 and this
register. Together they are transferred to another 16 bit variable
that is used by the rest of the code. Then the TMR0 and the high byte
register is cleared, and I exit the ISR.

What troubles me is that I get a lot of jitter on my count value.
A lot more than I would expect. The latency of the TMR0 interrupt
should not bother me, since in the part of the ISR that handles this
I just increment the high byte and then exits. The TMR0 itself is not
tampered with.

The latency that I get when the external interrupt occurs will cause
a little bit of jitter, since I'm reading the TMR0, but it shouldn't
be more than a couple of bits, especially since the TMR0 is running
at half the instruction cycle.

Any good hints?

I don't have the code here, but I can post that later if necessary.


_______________________________________________
¯yvind Kaurstad, spam_OUToyvindTakeThisOuTspamsafetel.no

Safetel AS
P.B. 405, N-4067 Stavanger, Norway
Tel: +47 51 81 78 80 (Switchboard)
    +47 51 81 78 82 (Office)
    +47 51 81 78 93 (Fax)

2000\02\07@060920 by Michael Rigby-Jones

flavicon
face
       Xyvind Kaurstad [.....oyvindKILLspamspam@spam@SAFETEL.NO] wrote:
> Ok, guys.
>
> I'm having some trouble, and I can't get it figured out.
>
> I'm building a device that's sampling the RPM of an engine.
> The incoming signal is therefore in the range of max 350 Hz, and it
> is connected to RB0.
>
> I need to accurately count the time *between* pulses, to get a number
> that is inversely proportional to the RPM.
>
> The TMR0 and the external interrupt is used. (16F84)
>
> I've programmed the TMR0 to run with a prescaler of 1:2, so the TMR0
> frequency should be 1.25 MHz.
>
So that would be a 10MHz crystal then?

{Quote hidden}

Ok, I did almost exactly this about 6 months back.  It was for a digital
tachometer which also used software PWM to drive a conventional meter
movement and had all sorts of bells and whistles such as max RPM memory.
All on a 16F84 with lots of room to spare.

I didn't bother with the external interupt to detect the ignition pulses, I
just used polling as the frequency was so slow.  I did use TMR0 with another
8 bit register though.  Jitter was a problem.  The reason is that you are
measuring the period between sparks with a very high precision, and engines
just do not run at constant speed.  In fact even during one revolution the
crank doesn't turn at a constant velocity.  The fewer cylinders the engine
has, the worse this effect is.

Unfortunately you need 16 bits because of the dynamic range of the counter.
Unless you use a large counter, it will either overflow at low RPM or run
out of resolution at higher RPM.  What I did was to convert to RPM, and feed
the results into a simple (digital) low pass filter.  I could get a reading
steady to within a few RPM on a 4 cylinder engine this way. You could lose
either one or two significant figures depending on your requirements.  A
least significant digit which constantly changes is very irritating, I'd
rather not see it :o)

Cheers

Mike

2000\02\07@063451 by oyvind

flavicon
face
> > I need to accurately count the time *between* pulses, to get a
> > number that is inversely proportional to the RPM.
> >
> > The TMR0 and the external interrupt is used. (16F84)
> >
> > I've programmed the TMR0 to run with a prescaler of 1:2, so the TMR0
> > frequency should be 1.25 MHz.
> >
> So that would be a 10MHz crystal then?

Yup. Forgot to tell.

{Quote hidden}

I'm not running into trouble with space either.

> I didn't bother with the external interupt to detect the ignition
> pulses, I just used polling as the frequency was so slow.  I did use
> TMR0 with another 8 bit register though.  Jitter was a problem.  The
> reason is that you are measuring the period between sparks with a very
> high precision, and engines just do not run at constant speed.  In
> fact even during one revolution the crank doesn't turn at a constant
> velocity.  The fewer cylinders the engine has, the worse this effect
> is.

Yes, that can be a problem, but I see my jitter also when I have a
function generator at a constant frequency connected to the circuit.

> Unfortunately you need 16 bits because of the dynamic range of the
> counter. Unless you use a large counter, it will either overflow at
> low RPM or run out of resolution at higher RPM.  What I did was to
> convert to RPM, and feed the results into a simple (digital) low pass
> filter.  I could get a reading steady to within a few RPM on a 4
> cylinder engine this way. You could lose either one or two significant
> figures depending on your requirements.  A least significant digit
> which constantly changes is very irritating, I'd rather not see it :o)

I also have an IIR low-pass filter that works ok.

The thing I'm building is a shift-light device, but not a
conventional one. It's supposed to be predictive, so that it will
give a forewarning that is time dependant, ie it gives you a warning
at a preset time before max RPM is reached. Conventional shift-lights
is based on RPM, and will warn based on current RPM-reading.

This involves a bit of math, but I got that part figured out. The
problem is that my counter jitters too much, and I can't figure out
why.

I could use polling as you did, but I'm not sure why that should be
better.


_______________________________________________
¯yvind Kaurstad, oyvindspamKILLspamsafetel.no

Safetel AS
P.B. 405, N-4067 Stavanger, Norway
Tel: +47 51 81 78 80 (Switchboard)
    +47 51 81 78 82 (Office)
    +47 51 81 78 93 (Fax)

2000\02\07@074554 by Michael Rigby-Jones

flavicon
face
> Yes, that can be a problem, but I see my jitter also when I have a
> function generator at a constant frequency connected to the circuit.
>
And this is with a nice clean square wave into the INT input?  I was going
to suggest that noise may be a problem.

{Quote hidden}

So you work out the slope of the current (delta RPM)/Time and then
extrapolate the RPM in x seconds?  That's pretty cunning.

> I could use polling as you did, but I'm not sure why that should be
> better.
>
I'm wondering if you have a potential problem with interrupt priorities.
Posting your ISR code would be helpfull.
What level of jitter are you seeing?  Is it always the same or does it vary
with the input frequency (RPM)?

Cheers

Mike

2000\02\07@082408 by oyvind
flavicon
face
> > Yes, that can be a problem, but I see my jitter also when I have a
> > function generator at a constant frequency connected to the circuit.
> >
> And this is with a nice clean square wave into the INT input?  I was
> going to suggest that noise may be a problem.

It can't be.
I even have two different signal genaerators. One of them has sweep
capability so that I can test an "acceleration".

{Quote hidden}

That is correct. When you got it figured out the math is pretty
straightforward. If the sampling interval was constant it would have
been easy, but my sampling interval is increasing with RPM which adds
a bit to the complexity of the task.

> > I could use polling as you did, but I'm not sure why that should be
> > better.
> >
> I'm wondering if you have a potential problem with interrupt
> priorities. Posting your ISR code would be helpfull. What level of
> jitter are you seeing?  Is it always the same or does it vary with the
> input frequency (RPM)?

If I don't find my problem tonight I will post the ISR tomorrow. I'm
at work now and don't have the ISR handy.

The jitter is somewhere in the range of 5-6 bits, and that should
actually make the task of finding the error easier. It's really a lot
of jitter, so there must be some huge mistake somewhere.

Working off mind the ISR looks like this:

org 0x04

...
context save from Microchip databook.
...

btfss INTCON,T0IF              ;Timer interrupt?
goto nex_chk_1

incf TIMER,1                   ;Yes, increasing high byte
bcf INTCON,T0IF                ;Clearing timer interrupt

nex_chk_1

btfss INTCON,INTF              ;RPM-interrupt?
goto end_handler

movf TMR0,0
movwf TIMER_STR                ;Saving TMR0 in low byte
clrf TMR0

movf TIMER,0
movwf TIMER_STR+1              ;Saving TIMER in high byte
clrf TIMER

bsf STAT,0                             ;Sets a status bit to indicate that a new
                                               ;count value is ready

bcf INTCON,INTF                ;Clearing external (RPM) interrupt

end_handler

...
context restore from Microchip databook.
...

retfie


What could go wrong here?
The main code is running in an loop polling the STAT,0 bit.
When it gets set the math is performed and the STAT,0 is cleared
again, and it goes back in the polling loop.

The TIMER_STR:2 variable is the count value used in the math.

If both interrupts occur simultaneously both will be serviced in turn
without leaving the ISR, since I'm checking the INTCON,INTF flag
after serviceing the timer interrupt.

If the timer interrupt occurs after the "btfss INTCON,T0IF"
instruction above I will get some extra jitter since it is not
rechecked until the ISR has ended. I tried correcting for this by
checking this bit within last part of the ISR, and if it was set I
would increase the TIMER register manually before storing it in
TIMER_STR+1. I also cleared the interrupt so that it would not cause
a retrig.

I still fail to see what's wrong here. Some jitter is bound to
happen, but not very much, I would think.


-¯yvind


_______________________________________________
¯yvind Kaurstad, .....oyvindKILLspamspam.....safetel.no

Safetel AS
P.B. 405, N-4067 Stavanger, Norway
Tel: +47 51 81 78 80 (Switchboard)
    +47 51 81 78 82 (Office)
    +47 51 81 78 93 (Fax)

2000\02\07@122747 by Dag Bakken

flavicon
face
¯K> What could go wrong here?
¯K> The main code is running in an loop polling the STAT,0 bit.
¯K> When it gets set the math is performed and the STAT,0 is cleared
¯K> again, and it goes back in the polling loop.

¯K> The TIMER_STR:2 variable is the count value used in the math.

You might want to try double-buffering of the 16bit timer.  If your math
takes a lot of time, and you're working on the same registers all the time,
you may get a new interrupt overwriting you previous values with new ones
while still not finished calculation with the previous ones.
This could work:

ISR routine:
   ...
   RETFIE

Polling loop
   pollwaitpollwait
   optionally-do-math
   keeponwaiting

Math
   GIE=off
   Copy TIMER_STR:2
   STAT,0=0               ; Do this early so you still register
                          ; interrupts while calc'ing.
   GIE=on
   Perform math on TIMER_STR:2 copies

The GIE should be switched off so your TIMER_STR:2 is not updated by the
ISR while you copy it.

rgds,
Dag S
Any programming language is at its best before it is implemented and used.

2000\02\07@154145 by John De Villiers

flavicon
face
Im trying to do the same thing with some added difficulties. Im trying to
determine the rpm on a motor bike, which normally rev's much higher than a
car.

Added complexity : some motor bikes fire the spark twice for every 4-stroke
cycle, or once per rev ( on the combustion stroke AND on the exhaust
troke  - well my 6 cyclinder does anyway ).

I Also came up with the idea of not trying to display the rpm in realtime
but rather at about 4hz. updating the display faster than that is pointless.
And then use a rule of averages for calc the rpm for that period. Makes
things a litte less jittery. I also only display down to 100 rpm. On a bike
that can rev at 14,000 rpm , not seeing the 10's and 1's isnt all that
important.

I have a working analogue version that uses a PLL and a decade counter that
drives a 3 1/2 digit 7seg led.  That had a display freq of 2hz, so the pll
multiplied the rpm pulse to reflect x amount of pulses per .5 second =
actual rpm. counting and displaying it was easy then.

> > I'm building a device that's sampling the RPM of an engine.
> > The incoming signal is therefore in the range of max 350 Hz, and it
> > is connected to RB0.
>

2000\02\08@013127 by Nikolai Golovchenko

flavicon
face
Hello Xyvind,

I've had exactly the same problem when worked with digital thermometer
TMP03.  It had about 30 Hz output and pulse width and period should have
been measured both.
Your problem lies in TMR0 overflow when it is not detected. See, what
happens on INT interrupt, if your code goes to nex_chk_1 and TMR0
overflows at this moment, before you read TMR0... You will get error
of about 256. After filtering it reduces to 5-6 bits, I guess.

This code may help:

    BANK0               ;set bank here

    btfss INTCON,T0IF              ;Timer interrupt?
    goto nex_chk_1

    incf TIMER,f                   ;Yes, increasing high byte
    bcf INTCON,T0IF                ;Clearing timer interrupt

nex_chk_1
    btfss INTCON, INTF
     goto end_handler
    movf TMR0, w        ;read TMR0 register
    btfsc INTCON, T0IF  ;check for overflow
     movlw  255         ;correct low byte
                        ;(reduces error to a couple of lsb's)
    clrf TMR0           ;clear TMR0 immediately
    movwf TIMER_STR     ;store low byte

    movf TIMER, w
    movwf TIMER_STR+1   ;Saving TIMER in high byte
    clrf TIMER

    bsf STAT,0          ;Sets a status bit to indicate that a new
                        ;count value is ready

end_handler
    bcf INTCON, T0IF
    bcf INTCON, INTIF

Bye,
Nikolai

On Monday, February 07, 2000 Xyvind Kaurstad wrote:
{Quote hidden}

2000\02\08@015324 by oyvind

flavicon
face
> Im trying to do the same thing with some added difficulties. Im trying
> to determine the rpm on a motor bike, which normally rev's much higher
> than a car.

12-15000 RPMs, right?

> Added complexity : some motor bikes fire the spark twice for every
> 4-stroke cycle, or once per rev ( on the combustion stroke AND on the
> exhaust troke  - well my 6 cyclinder does anyway ).

But the exhaust spark has no function.
I assume you have a setup with three coils, and each coil sparks two
cylinders? Or is it six coils and that two and two share the same
control signal?

> I Also came up with the idea of not trying to display the rpm in
> realtime but rather at about 4hz. updating the display faster than
> that is pointless. And then use a rule of averages for calc the rpm
> for that period. Makes things a litte less jittery. I also only
> display down to 100 rpm. On a bike that can rev at 14,000 rpm , not
> seeing the 10's and 1's isnt all that important.

But if you run an IIR-filter with sensible coefficients you may
display real time (at each pulse) without too much trouble.

Take a look at:

http://www.iversoft.com/piclist/9705/0320.shtml

This is similar to what I am running.

> I have a working analogue version that uses a PLL and a decade counter
> that drives a 3 1/2 digit 7seg led.  That had a display freq of 2hz,
> so the pll multiplied the rpm pulse to reflect x amount of pulses per
> .5 second = actual rpm. counting and displaying it was easy then.

Why change a winning team?

Regards
-¯yvind


_______________________________________________
¯yvind Kaurstad, oyvindspamspam_OUTsafetel.no

Safetel AS
P.B. 405, N-4067 Stavanger, Norway
Tel: +47 51 81 78 80 (Switchboard)
    +47 51 81 78 82 (Office)
    +47 51 81 78 93 (Fax)

2000\02\08@063624 by rubenj

flavicon
face
{Quote hidden}

One thing that could go wrong is if your RPM interrupt comes just
before TMR0 has rolled over, just after You check INTCON,TOIF. This
would mean that when You read TMR0 it is a low value but the high
byte has not got incremented giving You a fault of 256 counts.

The way I have handled this is to set a flag bit when TIMER has been
incremented due to a TMR0 interrupt in the ISR and in the main loop
clear this flag bit whenever bit 7 of TMR0 is 1. In the RPM
interrupt, when You sample TMR0 and TIMER, check if TMR0 is, say less
than 0x40, and Your flag bit is clear - if so You know that TIMER is
off by one and can increment it before You use it. This only works if
your main loop can check bit 7 of TMR0 with a rate of at least once
per 128th count of TMR0.

Another way is to allways read TMR0 at the very first point in Your
ISR and save it in a temp register. Then read this temp register
instead of TMR0 in Your RPM interrupt handler. (At least I think this
would work, it is possible though that an increment of TIMER could be
missed even here.)


==============================
Ruben Jvnsson
AB Liros Elektronik
Box 9124, 200 39 Malmv, Sweden
TEL INT +46 40142078
FAX INT +46 40947388
@spam@rubenKILLspamspampp.sbbs.se
==============================

More... (looser matching)
- Last day of these posts
- In 2000 , 2001 only
- Today
- New search...