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

Truncated match.
PICList Thread
'4MHz OSC / 1 Sec Interrupt'
2000\01\09@185611 by JB

flavicon
face
On a 16f84, TMR0 prescale = 256, 4MHz crystal, I have the interrupt routine
shown below. This once-per-second interrupt occurs every 1.25 seconds or
somewhere close to that. It's got to be something obvious, but I'm missing
it - what is causing the extra 1/4 second?


Interrupt:
       <save state code>
       incf            intc,f
       movf            intc,W
       sublw           D'17'           ;17 * 230 * 256 = 1000960uS
       bnz             IntBail
       clrf            intc

       incf            intc2,f ;every 4 seconds, compensate for long interval
       movf            intc2,W
       sublw           D'3'
       bnz             IntPerSecond
       movlw           D'15'           ;subtract the extra 3840uS (960uS * 4)
       addwf           TMR0,f
       clrf            intc2

IntPerSecond:
       call            IncTime

IntBail:

       movlw           D'26'           ;preload TMR0 for 230 counts per round
       addwf           TMR0,f  ;amounting to 58,880uS per interrupt
                                                       ;and 1,000,960uS every 17 interrupts.
       bcf             INTCON,T0IF
       <restore state code>
       retfie

2000\01\09@200159 by Byron A Jeff

face picon face
{Quote hidden}

         ^^^^^^^^^^^^^^^^^^^^^^

{Quote hidden}

Right here. Changing TMR0 resets the prescale, adding to your delay.

I got tired of fighting this. So I never reset the timer if I can help it.
If you have to adjust it, only do it at the absolute end of the interval.

This is what you should do:

- Change the prescale to 64. That with the normal /4 gives you exactly
15625 ticks per second.
- Use a 2 byte countdown timer. Use the decfsz instead of incf so that you
know immediately when the timer has counted down. Also it doesn't require
the use of the W register. Something like:

Interrupt:
       decfsz          ticklo,F
       return
       decfsz          tickhi,F
       return

; Now you reach this area exactly once per second. Be sure to reset tickhi
; and ticklo back to 61 and 9 respectively. That's 15625 ticks.

Hope this helps,

BAJ

2000\01\09@221310 by quozl

flavicon
face
On Sun, Jan 09, 2000 at 07:59:42PM -0500, Byron A Jeff wrote:
> - Change the prescale to 64. That with the normal /4 gives you exactly
> 15625 ticks per second.
> - Use a 2 byte countdown timer. Use the decfsz instead of incf so that you
> know immediately when the timer has counted down. Also it doesn't require
> the use of the W register.

Aha, so you don't have to save registers first!

{Quote hidden}

Woohoo, that's soo simple.  Why didn't I think of that?

Now, what would you choose as a prescale and countdown preload for a
10MHz crystal?  And what if you wanted hundredths of hours instead?
i.e. 36 second intervals.  I will think on this, but I welcome
confirmation.  ;-)

Should those RETURNs be RETFIEs?

--
James Cameron   spam_OUTquozlTakeThisOuTspamus.netrek.org   http://quozl.us.netrek.org/

2000\01\09@225719 by JB

flavicon
face
At 02:11 PM 1/10/00 +1100, you wrote:
>On Sun, Jan 09, 2000 at 07:59:42PM -0500, Byron A Jeff wrote:
>> - Change the prescale to 64. That with the normal /4 gives you exactly
>> 15625 ticks per second.

I get 61.035 (64uS * 256 = 16385uS/Int)

{Quote hidden}

Unless I missed something the author was trying to get across, this
actually works out to 256 seconds, not 1 second. The countdown depicted
amounts to a delay of 15625 interrupts. Each interrupt is 64uS (prescale)
times 256 (TMR0) which equals 16384uS. Multiply this times the delay of
15625 interrupts gives a total delay of exactly 256 seconds.

It is however MUCH better of an idea than resetting the TMR0 register, so I
made some changes which ended up like so:

Interrupt:
       <save status>
       decfsz  tickhi,f                ;counting down from 61
       goto            IntBail         ;16385uS * 61 = 999424uS/"second"
                                                               ;1 "second" has elapsed now
       movlw           D'61'                   ;reset every "second"
       movwf           tickhi

       decfsz  tickadj,f       ;counting down from 57
       goto            IntPerSecond

IntAdjust:
       movlw           D'63'           ;add 32768uS every 57 "seconds"
       movwf           tickhi  ;results in 64uS lost / 57 "seconds"
       movlw           D'57'           ;or 35 seconds/year
       movwf           tickadj

IntPerSecond:
       call            IncTime
       bsf             IntFlags,SecFlag;indicate that a second has elapsed

IntBail:
       <restore & exit>

The accuracy could probably be refined further, but this is good enough for
now, especially considering the crystal may have wider variations than the
routine itself. I have tried this in-circuit, and the results are on-target
based on casual comparision against my PC clock.

Many thanks for the help!

JB

2000\01\10@002246 by Byron A Jeff

face picon face
>
> On Sun, Jan 09, 2000 at 07:59:42PM -0500, Byron A Jeff wrote:
> > - Change the prescale to 64. That with the normal /4 gives you exactly
> > 15625 ticks per second.
> > - Use a 2 byte countdown timer. Use the decfsz instead of incf so that you
> > know immediately when the timer has counted down. Also it doesn't require
> > the use of the W register.
>
> Aha, so you don't have to save registers first!

Nope. Not until you actually use W. And the default interrupt won't use W,
just decrement the counter.

{Quote hidden}

I didn't either. This is a PIC/uC trick from antiquity: If the count is known
always count down because every CPU has a Z flag.

>
> Now, what would you choose as a prescale and countdown preload for a
> 10MHz crystal?

If the timing is a critical part of the equation, it's better to choose a
crystal frequency that's easily divided by a power of 2. For example if you can
get a 9.99936 Mhz crystal for example it can be divided evenly by 1024
which means you can use the natural /4 and the prescale to /256 giving exactly
9765 ticks per second, easily held in 2 bytes. Whereas exactly 10 Mhz can
only be evenly divided by 128 (/4 + prescale of /32) and having to track
78125 ticks per second. That's the reason that seemingly strange frequencies
such as 18.432 Mhz, 11.0592 Mhz, and 14.9456 Mhz exists, because they are
highly dividable by 2, and also can be evenly divided into serial comm
frequencies.

Even better if you have the pins is to attach a second crystal specifically
for the timing to your circuit. 32.768 Khz watch crystals are specifically
designed for this task. Once scaled it only gives 128 ticks per second. And
since resetting only takes one bit of one byte, you can delay up to 256
seconds without ever involving the W register.

>  And what if you wanted hundredths of hours instead?
> i.e. 36 second intervals.

Add a third byte with the number of seconds. You'll still have to reset the
tick count every second but the key is not to mess with the timer, just let
it free run. If you have to put a value into TMR0, then you're going to get
into trouble.

>  I will think on this, but I welcome
> confirmation.  ;-)
>
> Should those RETURNs be RETFIEs?

Yes.

Glad it helped.

BAJ

2000\01\10@003736 by Byron A Jeff

face picon face
{Quote hidden}

You're right. I forgot about the timer itself! Oops. This presents a problem
due to divisibility. Let's see. First turn off the prescaler. If the timer
free runs it'll generate 3906.25 ticks per second. So then you could add
exactly one extra count every 4 seconds and be right on the mark. But I think
it's the same effect as the code above.

Now the best thing is to change the crystal to 4.096 Mhz. Then it becomes
divisible by 32768 meaning that you could set the prescale to 32 and get
exactly 125 ticks per second.

Sorry about the timer.

BAJ

2000\01\10@004607 by Byron A Jeff

face picon face
> >
> > Now, what would you choose as a prescale and countdown preload for a
> > 10MHz crystal?
>
> If the timing is a critical part of the equation, it's better to choose a
> crystal frequency that's easily divided by a power of 2. For example if you can
> get a 9.99936 Mhz crystal for example it can be divided evenly by 1024
> which means you can use the natural /4 and the prescale to /256 giving exactly
> 9765 ticks per second, easily held in 2 bytes. Whereas exactly 10 Mhz can
> only be evenly divided by 128 (/4 + prescale of /32) and having to track
> 78125 ticks per second. That's the reason that seemingly strange frequencies
> such as 18.432 Mhz, 11.0592 Mhz, and 14.9456 Mhz exists, because they are
> highly dividable by 2, and also can be evenly divided into serial comm
> frequencies.

I need to amend this because I forgot about the actual TMR0 register itself.
With the PIC /4, the prescaler /256, and the TMR0 /256, a free running
TMR0 will roll over every 262144 ticks. The closest multiple of that
to 10 Mhz is 9.961472 Mhz. With that frequency you'll get 1 second every
38 ticks.

BAJ

2000\01\10@010518 by quozl

flavicon
face
On Mon, Jan 10, 2000 at 12:21:12AM -0500, Byron A Jeff wrote:
> > Now, what would you choose as a prescale and countdown preload for a
> > 10MHz crystal?
>
> If the timing is a critical part of the equation, it's better to choose a
> crystal frequency that's easily divided by a power of 2 [...]

I agree, however I only have 10MHz, 4MHz and 32768Hz crystals handy and
I'm in the Australian Outback.  Postal service is "fun".

You said 10MHz divided by 128, which gives 78.125kHz.  Neat, I agree.
I also see that 64 works as well, at 156.250kHz.  At 78125 I'll clearly
be using a 24-bit counter.  Should be easy.

> Even better if you have the pins is to attach a second crystal specifically
> for the timing to your circuit. 32.768 Khz watch crystals are specifically
> designed for this task.

Given one or two PIC I/O pins, say, on a 16F84, how would you drive this
sort of crystal?  I don't want another chip.

--
James Cameron   .....quozlKILLspamspam@spam@us.netrek.org   http://quozl.us.netrek.org/

2000\01\10@012001 by quozl

flavicon
face
On Mon, Jan 10, 2000 at 12:44:59AM -0500, Byron A Jeff wrote:
> I need to amend this because I forgot about the actual TMR0 register itself.
> With the PIC /4, the prescaler /256, and the TMR0 /256, a free running
> TMR0 will roll over every 262144 ticks. The closest multiple of that
> to 10 Mhz is 9.961472 Mhz. With that frequency you'll get 1 second every
> 38 ticks.

Okay, I take back some of my previous reply then.

But what if you set the prescaler to /128, and on every TMR0 interrupt
simply subtracted 256 from the counter?  Wouldn't that be the same as
78,125 counts?  You'd have to _add_ the 78,125 into your counter rather
than reload it, but that would be minor.  You would still get 1Hz, just
that some of the 1Hz would be shorter and some longer.

--
James Cameron   quozlspamKILLspamus.netrek.org   http://quozl.us.netrek.org/

2000\01\10@094455 by Michael Rigby-Jones

flavicon
face
part 0 4068 bytes
<P><FONT SIZE=2 FACE="Arial">James Cameron&nbsp;&nbsp;<U> </U></FONT><U><FONT COLOR="#0000FF" SIZE=2 FACE="Arial"><A HREF=".....quozlKILLspamspam.....us.netrek.org">EraseMEquozlspam_OUTspamTakeThisOuTus.netrek.org</A></FONT></U><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;</FONT><U> <FONT COLOR="#0000FF" SIZE=2 FACE="Arial"><A HREF="http://quozl.us.netrek.org/" TARGET="_blank">http://quozl.us.netrek.org/</A></FONT></U><FONT COLOR="#0000FF" SIZE=2 FACE="Arial"> replied:</FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">Okay, I take back some of my previous reply then.</FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">But what if you set the prescaler to /128, and on every TMR0 interrupt</FONT>
<BR><FONT SIZE=2 FACE="Arial">simply subtracted 256 from the counter?&nbsp; Wouldn't that be the same as</FONT>
<BR><FONT SIZE=2 FACE="Arial">78,125 counts?&nbsp; You'd have to _add_ the 78,125 into your counter rather</FONT>
<BR><FONT SIZE=2 FACE="Arial">than reload it, but that would be minor.&nbsp; You would still get 1Hz, just</FONT>
<BR><FONT SIZE=2 FACE="Arial">that some of the 1Hz would be shorter and some longer.</FONT>
</P>
</UL>
<P><FONT COLOR="#0000FF" SIZE=2 FACE="Arial">How about the following (sorry in C, but self explanatory I hope).&nbsp; The timer would be configured to run without the pre scaler in this case, but the prescaler could be used if the count decrement value and counter preload values are changed accordingly.</FONT></P>

<P><FONT COLOR="#0000FF" SIZE=2 FACE="Arial">int counter;</FONT>
</P>

<P><FONT COLOR="#0000FF" SIZE=2 FACE="Arial">void interupt timer()</FONT>
<BR><FONT COLOR="#0000FF" SIZE=2 FACE="Arial">{</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT COLOR="#0000FF" SIZE=2 FACE="Arial">counter = counter - 4;</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT COLOR="#0000FF" SIZE=2 FACE="Arial">if (counter == 0)</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT COLOR="#0000FF" SIZE=2 FACE="Arial">{</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT COLOR="#0000FF" SIZE=2 FACE="Arial">counter = 15625;</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT COLOR="#0000FF" SIZE=2 FACE="Arial">/* do stuff here once per second */</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT COLOR="#0000FF" SIZE=2 FACE="Arial">}</FONT>
<BR><FONT COLOR="#0000FF" SIZE=2 FACE="Arial">}</FONT>
</P>
<BR>

<P><FONT COLOR="#0000FF" SIZE=2 FACE="Arial">If this post is in HTML then please accept my apologies,&nbsp; I've tried my hardest to fix it.&nbsp; Outlook 97 is truly horrible.</FONT></P>

<P><FONT COLOR="#0000FF" SIZE=2 FACE="Arial">Cheers</FONT>
</P>

<P><FONT COLOR="#0000FF" SIZE=2 FACE="Arial">Mike Rigby-Jones</FONT>
</P>

</BODY>
</HTML>
</x-html>

2000\01\10@161738 by Mark Willis

flavicon
face
James Cameron wrote:
> On Mon, Jan 10, 2000 at 12:21:12AM -0500, Byron A Jeff wrote:
> > > Now, what would you choose as a prescale and countdown preload for a
> > > 10MHz crystal?
> >
> > If the timing is a critical part of the equation, it's better to choose a
> > crystal frequency that's easily divided by a power of 2 [...]
>
> I agree, however I only have 10MHz, 4MHz and 32768Hz crystals handy and
> I'm in the Australian Outback.  Postal service is "fun".

Still, I imagine things mailed to you do get there?  Crystals can be
small-packed, they're reasonably tough <G>  If you want "care packages",
I can mail 'em...

{Quote hidden}

Bit-Banging 32.768 kHz, anyone?  I imagine it can be done, unsure how
well it'd work <G>  I'd try a Colpitts Osc. - Try Horowitz/Hill, Page
302, 3 C's, 2 R's,. and a 2N5484 FET.  (Anyone guess what I got for
Christmas?  <G>)

> --
> James Cameron   quozlspamspam_OUTus.netrek.org   http://quozl.us.netrek.org/

 Mark

--
I re-ship for small US & overseas businesses, world-wide.
(For private individuals at cost; ask.)

2000\01\10@171752 by quozl

flavicon
face
On Mon, Jan 10, 2000 at 02:43:15PM -0000, Michael Rigby-Jones wrote:
> void interrupt timer() {
>         counter = counter - 4;
>         if (counter == 0) {
>                 counter = 15625; /* do stuff here once per second */
>         }
> }

Mike, counter would never be zero if it were not initialised to a
multiple of four.

The solution I have tested overnight works as follows;

- prescaler set to 1:256,
- TMR0 interrupt enabled,
- maintain a 24-bit 0.1us counter,
- add 26214.4us to the counter each interrupt,
- subtract 1,000,000us (1s) from the counter,
- if underflow, ignore the subtract and return from interrupt,
- if no underflow, retain the new value, and do the once-a-second task.

Having done this, I'm a bit annoyed that the accuracy wasn't very high.
Using a low profile 10MHz crystal, two 27pF capacitors, on veroboard,
gave me a loss of about 9 seconds per hour.  0.2% error.

What changes do I make to use a 32768Hz clock crystal?

--
James Cameron   @spam@quozlKILLspamspamus.netrek.org   http://quozl.us.netrek.org/

2000\01\10@200710 by Jan Erik Bertram

picon face
----- Original Message -----
From: "James Cameron" <KILLspamquozlKILLspamspamUS.NETREK.ORG>    Sent: Monday, January 10,
2000 11:16 PM
Subject: Re: 4MHz OSC / 1 Sec Interrupt


{Quote hidden}

I played a bit with this.
I calculated 137329,1016 Interrupt per hour.
You loss 9 seconds, that means you loss 65,5365s per Interrupt.
I suppose, it isn't a casualness.
Try to run it a while in mpsim with the stopwatch, or send a code snippet to
the list.

> What changes do I make to use a 32768Hz clock crystal?
Clock Cycle Time is 32768/4Hz=1/8192s
if prescaler is set to 1:32, every 32*256Cycles=8192Cycles an interrupt
occurs.

- prescaler set to 1:32,
- TMR0 interrupt enabled,
- each interrupt is a one-second-interrupt, therefore do the once-a-second
task.


Ciao
   Jan Erik Bertram

2000\01\10@201357 by Dave VanHorn

flavicon
face
> > Having done this, I'm a bit annoyed that the accuracy wasn't very high.
> > Using a low profile 10MHz crystal, two 27pF capacitors, on veroboard,
> > gave me a loss of about 9 seconds per hour.  0.2% error.

Eventually, you'll want to check that your 10.000 MHz is really that, and
not something else.

2000\01\10@203436 by Robert.Rolf

picon face
On Mon, 10 Jan 2000, Dave VanHorn wrote:
> > > Having done this, I'm a bit annoyed that the accuracy wasn't very high.
> > > Using a low profile 10MHz crystal, two 27pF capacitors, on veroboard,
> > > gave me a loss of about 9 seconds per hour.  0.2% error.
>
> Eventually, you'll want to check that your 10.000 MHz is really that, and
> not something else.

No crystal is THAT badly off freq, even with totally wrong loading.
Even the worst case 500ppm is .0005% .
That you have a nice binary (65536) count error suggest a boundary
condition on your compares or reloads of bytes.

See my tag line <G>.

Robert
RemoveME--Robert.RolfTakeThisOuTspamUAlberta.ca
"If 'debugging' is the process of removing errors, then 'programming' must
be the process of putting them in".

2000\01\10@210155 by Jinx

face picon face
Is there a local (New Zealand) or a Global way of adjusting this clock
say once a month ? I'm thinking of some sort of beacon or satellite.
Does GPS have a time component in it that the PIC can read and
compensate for any crystal deviations, but without going to the
expense of full GPS receiver ? I'm looking to get better performance
from a battery-powered device which doesn't have constant access
to mains frequency.

Jinx

> > IntAdjust:
> >         movlw           D'63'           ;add 32768uS every 57 "seconds"
> >         movwf           tickhi           ;results in 64uS lost / 57
"seconds"
> >         movlw           D'57'           ;or 35 seconds/year
> >         movwf           tickadj
> >
> > The accuracy could probably be refined further, but this is good enough
> > for now, especially considering the crystal may have wider variations
than
> > the routine itself. I have tried this in-circuit, and the results are
on-target
> > based on casual comparision against my PC clock.
>

2000\01\10@212251 by Brent Brown

picon face
> Is there a local (New Zealand) or a Global way of adjusting this clock
> say once a month ? I'm thinking of some sort of beacon or satellite.
> Does GPS have a time component in it that the PIC can read and
> compensate for any crystal deviations, but without going to the
> expense of full GPS receiver ? I'm looking to get better performance
> from a battery-powered device which doesn't have constant access
> to mains frequency.
>
> Jinx

GPS modules do give you an accurate clock signal, and some
people a GPS fixed to a building for this purpose only. A GPS
module without the GPS part would be great!

Farnell sell a wall clock that synchs with a radio time code, but
last time I asked this product didn't work in NZ.

Brent Brown
Electronic Design Solutions
16 English Street
Hamilton, New Zealand
Ph/fax: +64 7 849 0069
Mobile: 025 334 069
eMail:  spamBeGonebrent.brownspamBeGonespamclear.net.nz

2000\01\10@221714 by Dave VanHorn

flavicon
face
> > Eventually, you'll want to check that your 10.000 MHz is really that,
and
> > not something else.
>
> No crystal is THAT badly off freq, even with totally wrong loading.
> Even the worst case 500ppm is .0005% .
> That you have a nice binary (65536) count error suggest a boundary
> condition on your compares or reloads of bytes.


See the word "Eventually" as in: Eventually, once the glaring software
problems are ironed out.

2000\01\10@224238 by quozl

flavicon
face
"What changes do I make to use a 32768Hz clock crystal?"

I'll rephrase that ... I mean on the circuitry side.  Do I need a
series resistor or different capacitor values?

Page 39 of the PIC16F8X data sheet, table 8-2, suggests LP mode, and
68-100pF capacitors.  But it also says "For Vdd > 4.5V, C1 = C2 = 30pF
is recommended."  So since I'm using Vdd of 5.0V do I just leave it as
it is (27pF) and change to LP mode on configuration word?

--
James Cameron   TakeThisOuTquozlEraseMEspamspam_OUTus.netrek.org   http://quozl.us.netrek.org/

2000\01\10@230759 by quozl

flavicon
face
quozl.us.netrek.org/draft-16f84-10mhz-1hz-interrupt.asm

I've taken the working code, cut out the irrelevancies, and placed it
on a web server for review.  However, it appears my result of 9 seconds
lost in an hour may have been bogus.  The method I used to do this is
suspect, and over the last 18 hours it has only lost 30 seconds.

(I display 0.01 hour units, so the error can be up to 36 seconds either
way.  Sorry about that.)

--
James Cameron   RemoveMEquozlspamTakeThisOuTus.netrek.org   http://quozl.us.netrek.org/

2000\01\11@040128 by Michael Rigby-Jones

flavicon
face
> On Mon, Jan 10, 2000 at 02:43:15PM -0000, Michael Rigby-Jones wrote:
> > void interrupt timer() {
> >         counter = counter - 4;
> >         if (counter == 0) {
> >                 counter = 15625; /* do stuff here once per second */
> >         }
> > }
>
> Mike, counter would never be zero if it were not initialised to a
> multiple of four.
>
True....I didn't actually show the initialisation fo the variable...I kinda
implied it really :o)

main()
{
       counter = 15625;
}

And 'counter' can be a signed int since it's max value is less than 32768,
so to make it more bomb proof you could change the compare to:

if(counter <= 0) { etc...etc...

The ASM of the main part of the ISR would look something like this (slightly
edited output of HiTech C) :

       movlw   -4                      ; counter = counter - 4
       addwf   counter_lo
       skpc
       decf    counter_hi

       movf    counter_hi,w ; is counter < 0?
       xorlw   128
       movwf   temp
       movlw   128
       subwf   temp,w
       movlw   1
       skpnz
       subwf   counter_lo,w ; is counter = 0?
       skpnc
       goto    IsrExit

       movlw   0x09            ; reload counter with 15625 (0x3D09)
       movwf   counter_lo
       movlw   0x3D
       movwf   counter_hi
       ; do 1 second stuff here
IsrExit


18 instructions program space and 1 byte of RAM, 15us min, 17 us max not
including user code for the 1 second function and not including context
saving and restoring.

Cheers

Mike

2000\01\11@092504 by Jim Hartmann

flavicon
face
I think the problem is not enough precision in your counter--
You are throwing away 0.4us per interrupt by rounding 26214.4 to 26214 (I
assume).  At an interrupt rate of 102.4uS, this causes an error of
-0.4/102.4 =   -0.4%  multiplied by 3600 sec/hour is -14.06 seconds per
hour.  So your measurement is pretty close to what would be expected.

To get more precision you need to scale your phase accumulator so instead
of 0.4% error you get an error more like 0.0040% per period.

-Jim





James Cameron <quozlEraseMEspam.....US.NETREK.ORG>EraseMEspam.....MITVMA.MIT.EDU> on 01/10/2000 04:16:35
PM

Please respond to EraseMEquozlspamus.netrek.org

Sent by:  pic microcontroller discussion list <RemoveMEPICLISTEraseMEspamEraseMEMITVMA.MIT.EDU>


To:   RemoveMEPICLISTspam_OUTspamKILLspamMITVMA.MIT.EDU
cc:
Subject:  Re: 4MHz OSC / 1 Sec Interrupt


- prescaler set to 1:256,
- TMR0 interrupt enabled,
- maintain a 24-bit 0.1us counter,
- add 26214.4us to the counter each interrupt,
- subtract 1,000,000us (1s) from the counter,
- if underflow, ignore the subtract and return from interrupt,
- if no underflow, retain the new value, and do the once-a-second task.

Having done this, I'm a bit annoyed that the accuracy wasn't very high.
Using a low profile 10MHz crystal, two 27pF capacitors, on veroboard,
gave me a loss of about 9 seconds per hour.  0.2% error.

What changes do I make to use a 32768Hz clock crystal?

--
James Cameron   RemoveMEquozlTakeThisOuTspamspamus.netrek.org   http://quozl.us.netrek.org/

2000\01\11@103144 by Jim Hartmann

flavicon
face
Sorry, my numbers are messed up, I didn't read carefully enough.  I see now
that the interrupt rate is 38.14697265625 Hz.  I'll try again.

There are 26214.4uS per interrupt (like you said).  You add 26214, so 0.4us
of every 26214.4us is lost.  That's only -15 ppm, plenty good enough.

However, to simplify here's what I'd do--

Scale the phase accumulator so that 1 second is a power of two instead of
1000000 in the accumulator.  For the most precision with 24 bits let 2^23
(8388608) counts be one second.  Now you will need to add
2^23/(10E6/4/256/256) = 219902<.326> at each interrupt.  When bit 23 is
set, clear it and increment your one second counter.   This is much simpler
and faster in software, and 8X more accurate too.

-Jim





Jim Hartmann <EraseMEJim_HartmannspamspamspamBeGoneSILENTKNIGHT.COM>spamspamspamBeGoneMITVMA.MIT.EDU> on 01/11/2000
08:21:01 AM

Please respond to pic microcontroller discussion list
     <RemoveMEPICLISTKILLspamspamMITVMA.MIT.EDU>

Sent by:  pic microcontroller discussion list <PICLISTSTOPspamspamspam_OUTMITVMA.MIT.EDU>


To:   spamBeGonePICLISTSTOPspamspamEraseMEMITVMA.MIT.EDU
cc:
Subject:  Re: 4MHz OSC / 1 Sec Interrupt


I think the problem is not enough precision in your counter--
You are throwing away 0.4us per interrupt by rounding 26214.4 to 26214 (I
assume).  At an interrupt rate of 102.4uS, this causes an error of
-0.4/102.4 =   -0.4%  multiplied by 3600 sec/hour is -14.06 seconds per
hour.  So your measurement is pretty close to what would be expected.

To get more precision you need to scale your phase accumulator so instead
of 0.4% error you get an error more like 0.0040% per period.

-Jim





James Cameron <KILLspamquozlspamBeGonespamUS.NETREK.ORG>spamBeGonespamMITVMA.MIT.EDU> on 01/10/2000 04:16:35
PM

Please respond to EraseMEquozlspamEraseMEus.netrek.org

Sent by:  pic microcontroller discussion list <@spam@PICLIST@spam@spamspam_OUTMITVMA.MIT.EDU>


To:   spamBeGonePICLISTspamKILLspamMITVMA.MIT.EDU
cc:
Subject:  Re: 4MHz OSC / 1 Sec Interrupt


- prescaler set to 1:256,
- TMR0 interrupt enabled,
- maintain a 24-bit 0.1us counter,
- add 26214.4us to the counter each interrupt,
- subtract 1,000,000us (1s) from the counter,
- if underflow, ignore the subtract and return from interrupt,
- if no underflow, retain the new value, and do the once-a-second task.

Having done this, I'm a bit annoyed that the accuracy wasn't very high.
Using a low profile 10MHz crystal, two 27pF capacitors, on veroboard,
gave me a loss of about 9 seconds per hour.  0.2% error.

What changes do I make to use a 32768Hz clock crystal?

--
James Cameron   .....quozlspam_OUTspamus.netrek.org   http://quozl.us.netrek.org/

2000\01\11@113011 by Michael Rigby-Jones

flavicon
face
part 0 8040 bytes
<P><FONT COLOR="#0000FF" SIZE=2 FACE="Arial">Jim,</FONT>
<BR><FONT COLOR="#0000FF" SIZE=2 FACE="Arial">James already has scaled his accumulator so it counts in 0.1 us increments.</FONT>
</P>
<UL>
<P><FONT SIZE=1 FACE="Arial">{Original Message removed}

2000\01\11@114919 by Ken Webster

flavicon
face
Dunno if you want to get this fancy ...

I have a subroutine that reads TMR1, subtracts the value at the last reading
to obtain a delta, multiplies the delta by a 32-bit fixed-point calibration
factor, and adds the calibrated time-delta into a set of time registers
(subseconds, seconds, minutes, hours, etc.).  It is optomized for a 32768 Hz
crystal on TMR1 but can be used with other frequencies by changing the
calibration factor.  It should be easy to adapt to use TMR0 instead of TMR1
(but you may need to call it more often or use a prescaler to avoid
overflows).

One least-significant bit in the calibration factor represents 1 part in
16,777,216 (with a 32768 Hz crystal) which corresponds to about 1.8 seconds
per year or 5 milliseconds per day.  (a lot less than the error one would
expect from the crystal's temperature coefficient unless it is in a
temperature-controlled environment)

The source code for the application is here:
http://ken.webster.org/clock/cdclock.txt
The Subroutine: UPDATE_TIME

A description of the application is here:
http://ken.webster.org/clock

Cheers,
Ken

<-- chop -->
{Quote hidden}

2000\01\24@042238 by Bob Jenner
flavicon
face
At 04:55  9/01/00 -0700, you wrote:
>On a 16f84, TMR0 prescale = 256, 4MHz crystal, I have the interrupt routine
>shown below. This once-per-second interrupt occurs every 1.25 seconds or
>somewhere close to that. It's got to be something obvious, but I'm missing
>it - what is causing the extra 1/4 second?
Sorry to come in late on this but I have been away. This works for me
although I'm sure someone can dot more elegantly.

;Program "Timer"
;General purpose program for counting seconds.
;Assumes a 4Mhz Osc (ceramic resonator in my case). If the resonator wobbles
;that's not too bad in the long term. If drift causes a problem
; get a crystal!

;Assuming the Osc is accurate at 4 Mhz, the following applies.
;Driving TMRO from Osc/4 (1Mhz) and not using the prescaler, an interrupt
;occurs every 256 us. The 16 bit counter (tickhi,ticklo) is loaded with
;D 3906 which gives a count every 256 x 3906 = 999936 us. 4us short
;of a second amounts to 2.1 seconds/non leap year...good enough for me.

;The constants coarse and fine can be altered to account for variations in
;Osc freq. In this example, the value used is
;16x256+40=4136 hence my Osc is 4136X256x4= 4.235264 Mhz



; Assembly code for PIC16F84 microcontroller
; CPU configuration
;       (It's a 16F84, ceramic oscillator,
;       watchdog timer off, power-up timer on)

       processor 16f84
       include   <p16f84.inc>
       __config  _XT_OSC & _WDT_OFF & _PWRTE_ON

; Declare variables
ticklo          equ     H'10'   ;lo byte of tick counter
tickhi          equ     H'11'   ;hi byte of tick counter
tmpstatus       equ     H'12'   ;push and pop status reg here during interrupts
tmpW            equ     H'13'   ;same for W register
secs            equ     H'14'   ;increments every second
       constant        coarse = D'16'  ;adjust for variations
       constant        fine =  D'40'   ;in Osc freq
; Program
       org     0         ; start at address 0
       goto    start
       nop
       nop
       nop
       goto    isr             ;interrupt service routine
start:
       bsf     STATUS,RP0      ;select bank1
       movlw   B'11011000'     ;assign timer0 to system clock/4
       movwf   OPTION_REG      ;and prescaler to the WDT
       bcf     STATUS,RP0      ;select bank 0
       movlw   B'10100000'     ;set global int enable and TMRO int.
       movwf   INTCON
       movlw   coarse          ;coarse adustment
       movwf   tickhi          ;initialise the 16 bit counter
       movlw   fine            ;fine adjustment
       movwf   ticklo
       clrf    PORTA
       clrf    PORTB
       ;set port directions for test rig
       bsf     STATUS, RP0     ;select bank 1
       movlw   B'11111'
       movwf   TRISA           ;all portA as inputs
       clrf    TRISB           ;all port B  bits as output
       bcf     STATUS, RP0     ;select bank 0
mloop:
       movf    secs,W          ;do whatever
       movwf   PORTB           ;you want here.
       goto    mloop



isr:    ;
       ;Push status and W registers
       movwf   tmpW
       swapf   STATUS,W
       movwf   tmpstatus
       ;service interrupt here

       decfsz  ticklo,1
       goto    endisr
       decfsz  tickhi,1
       goto    endisr
       ;1 sec is up! increment the seconds counter
       ;and reload the tick counter
       ;We arrive here every 999936 usecs so we lose
       ;2 secs per year...big deal
       incf    secs,1
       movlw   coarse
       movwf   tickhi          ;initialise the 16 bit counter
       movlw   fine            ;
       movwf   ticklo


endisr: ;Pop status and W registers
       swapf   tmpstatus,W
       movwf   STATUS
       movf    tmpW,W
       bcf     INTCON,2        ;clear interrupt flag
       retfie                  ;piss off

       end
Bob Jenner
Trading as RAJE Consulting
3 Cahill Cr Nakara NT 0810
Tel 08 89 455 796
Fax 08 89 275147
http://www.coolspot.com.au

2000\01\24@083106 by Ken Webster

flavicon
face
Bob Jenner wrote:
>;Assuming the Osc is accurate at 4 Mhz, the following applies.
>;Driving TMRO from Osc/4 (1Mhz) and not using the prescaler, an interrupt
>;occurs every 256 us. The 16 bit counter (tickhi,ticklo) is loaded with
>;D 3906 which gives a count every 256 x 3906 = 999936 us. 4us short
>;of a second amounts to 2.1 seconds/non leap year...good enough for me.


Isn't that 64us short of a second?
Wouldn't the clock gain 5.5296 seconds per day?
(about 33.6 minutes per year)


Why not count subseconds ... add 0.000256 to a subseconds register every
interrupt.  Let the subseconds register carry into the seconds register.
Using a 32-bit subseconds register you would simply add the number
0x0010c6f8 each interrupt cycle.  The register will overflow once per second
(averaged over the long term .. each overflow will be constrained to the
256us interval nearest to the actual second).

Because of the rounding errors due to limiting the resolution to 32 bits,
the clock would still loose some time but it would only be about 30ms per
day which is about 11 seconds per year.  Making your subseconds register
larger could reduce this error but there would be little point in doing this
unless you have a very accurate and stable oscillator and can control the
temperature of your crystal.

For an example of applying this technique (using a low-frequency crystal and
a software calibration constant), see:

http://ken.webster.org/clock/cdclock.txt

Note that this example is more complex than you would need because it uses a
software calibration constant (i.e. the number corresponding to 0x0010c6f8
is not hard-coded) and it moves counts out of the hardware timer register at
unpredictable times (controlled by a software loop rather than an interrupt)
and thus needs to multiply the counts by a calibration factor rather than
simply adding a pre-calculated number to a subseconds register.  It does
work quite nicely though and you are welcome to borrow the code if you like.

Cheers,

Ken

2000\01\25@214921 by Bob Jenner

flavicon
face
At 06:29  24/01/00 -0700, you wrote:
>Bob Jenner wrote:
>>;Assuming the Osc is accurate at 4 Mhz, the following applies.
>>;Driving TMRO from Osc/4 (1Mhz) and not using the prescaler, an interrupt
>>;occurs every 256 us. The 16 bit counter (tickhi,ticklo) is loaded with
>>;D 3906 which gives a count every 256 x 3906 = 999936 us. 4us short
>>;of a second amounts to 2.1 seconds/non leap year...good enough for me.
>
>
>Isn't that 64us short of a second?
>Wouldn't the clock gain 5.5296 seconds per day?
>(about 33.6 minutes per year)
>
Ouch! What an idiot (me that is). Thanks Ken.
Bob Jenner
Trading as RAJE Consulting
3 Cahill Cr Nakara NT 0810
Tel 08 89 455 796
Fax 08 89 275147
http://www.coolspot.com.au

2000\01\25@230800 by Ken Webster

flavicon
face
Bob Jenner wrote:
>At 06:29  24/01/00 -0700, you wrote:
>>Bob Jenner wrote:
>>>;Assuming the Osc is accurate at 4 Mhz, the following applies.
>>>;Driving TMRO from Osc/4 (1Mhz) and not using the prescaler, an interrupt
>>>;occurs every 256 us. The 16 bit counter (tickhi,ticklo) is loaded with
>>>;D 3906 which gives a count every 256 x 3906 = 999936 us. 4us short
>>>;of a second amounts to 2.1 seconds/non leap year...good enough for me.
>>
>>
>>Isn't that 64us short of a second?
>>Wouldn't the clock gain 5.5296 seconds per day?
>>(about 33.6 minutes per year)
>>
>Ouch! What an idiot (me that is). Thanks Ken.


Aww, heck ... I do that kinda stuff all the time (drop digits, etc.).  Then
I stare at it for hours trying to figure out why its not doing what I think
its supposed to do.  A fresh set of eyes always helps.  Chalk another one up
for the PICList!

Cheers,

Ken

2000\01\26@185246 by Greg Ahpee

flavicon
face
Bob,

There is a problem in your code below which I feel you should be made aware of  in
case you (or others) copy it for future projects. As the decfsz instruction
decrements the register before testing the result  for zero, your loop will
actually terminate when the value in tickhi/ticklo is H'0101 and not H'0000 as you
expect. To further complicate the matter a starting value of say H'0401 will
actually result in a shorter delay than H'0400

Although you will be able to get the delay you need by fiddling with the starting
value it is not easy to calculate what it should be.

There are numerous ways around the problem but the simplest is to calcuate the
starting value as H'10000 - cycles and use incfsz instructions in place of the
decfsz's.

On another issue, I have been using 3.2768MHz xtals in applications where a 1 sec
clock is needed. If these are divided by 4*256*32 you get 100Hz exactly. They are
available in Oz from Jaycar at $1 each!

Greg Ahpee
Melbourne

Bob Jenner wrote:

{Quote hidden}

2000\01\27@185106 by Bob Jenner

flavicon
face
At 10:38  27/01/00 +1100, you wrote:
>Bob,
>
>There is a problem in your code below which I feel you should be made aware
of  in
>case you (or others) copy it for future projects. As the decfsz instruction
>decrements the register before testing the result  for zero, your loop will
>actually terminate when the value in tickhi/ticklo is H'0101 and not H'0000
as you
>expect. To further complicate the matter a starting value of say H'0401 will
>actually result in a shorter delay than H'0400
>
>Although you will be able to get the delay you need by fiddling with the
starting
>value it is not easy to calculate what it should be.
>
>There are numerous ways around the problem but the simplest is to calcuate the
>starting value as H'10000 - cycles and use incfsz instructions in place of the
>decfsz's.
>
>On another issue, I have been using 3.2768MHz xtals in applications where a
1 sec
>clock is needed. If these are divided by 4*256*32 you get 100Hz exactly.
They are
>available in Oz from Jaycar at $1 each!
>
>Greg Ahpee
>Melbourne
Thanks Greg I will look into it. Xtal's at $1...whew + $9 freight to Darwin :-(
{Quote hidden}

interrupts
{Quote hidden}

Bob Jenner
Trading as RAJE Consulting
3 Cahill Cr Nakara NT 0810
Tel 08 89 455 796
Fax 08 89 275147
http://www.coolspot.com.au

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