PDA

View Full Version : Timer Accuracy



GEEZER
- 30th March 2005, 04:47
I'm new a this. I need a background timer for a project to give me an exact second. I have it down to a max error of .3% it seems to drift between .3% and .1%. Is this as good as it gets?

I am using a 16F877A at 20 mHZ. Can I make any adjustments that will give me absolute precision?

Here's my code.

DEFINE LCD_DREG PORTC
DEFINE LCD_DBIT 4
DEFINE LCD_RSREG PORTC 'DEFINES
DEFINE LCD_RSBIT 1
DEFINE LCD_EREG PORTC
DEFINE LCD_EBIT 0
DEFINE LCD_BITS 4
DEFINE LCD_LINES 4
DEFINE LCD_COMMANDUS 3000
DEFINE LCD_DATAUS 1000
DEFINE OSC 20

'VARIABLES
REFRESHED VAR BIT
X VAR WORD
Y VAR WORD
Z VAR WORD
ZZ VAR WORD
X = 0
Y = 0
Z= 0
ZZ=0

ON INTERRUPT GOTO PULSE_COUNT 'WHERE TO GO ON INTERRUPT

GOTO INITIALIZE 'SKIP INTERUPT CODE TO SET UP TIMER

''' INTERRUPT CODE '''

DISABLE
PULSE_COUNT:
T1CON.0 = 0 ' TURNS TIMER OFF
T1CON.0 = 1
REFRESHED = 1 'SET FLAG TO SAY COUNT READ


X = X + 1
IF X = 133 THEN
Y = Y + 1
X = 0
ENDIF



INTCON.2 = 0 'CLEARS INTERRUPT FLAG
RESUME
ENABLE ' RELOAD SYSTEM VARIABLES

''' END OF INTERRUPT CODE '''


''' INITIALIZE ALL REGS '''

INITIALIZE:
OPTION_REG.0 = 0 'SET PRESCALER TO 1:1
OPTION_REG.1 = 0
OPTION_REG.2 = 0
OPTION_REG.5 = 0 'TMR0 CLOCK FROM MAIN OSC
OPTION_REG.3 = 0 'PRESCALER ASSIGNED TO TMR0
INTCON.2 = 0 'CLEARS INTERRUPT FLAG
T1CON = %00000110
T1CON.0 = 1 'TURNS TIMER ON
TMR0 = 7 'LOAD THE TIMER IN MEMORY
INTCON.5 = 1 'ENABLE TMR0 INTERRUPTS
REFRESHED = 0 'HOLD FIRST READ TILL MAIN INT OCCURS
INTCON.7 = 1 'START TIMER RUNNING

''' CALCULATIONS AND READ OUT '''
HIGH PORTC.1
PAUSE 1000
LCDOUT $FE, 1

LOOP:
IF Y = 59 THEN
Z = Z + 1
Y = 0
ENDIF



iF REFRESHED = 1 THEN
LCDOUT $FE, 1
LCDOUT $FE, 2
LCDOUT
LCDOUT $FE, $C0
LCDOUT " SEC ", DEC Y
LCDOUT $FE, $90
LCDOUT " MIN ", DEC Z
LCDOUT $FE, $D0
LCDOUT
REFRESHED = 0 'PREVENT RE-READ TILL NEXT
ENDIF 'INTERRUPT
PAUSE 50
GOTO LOOP
END

Your help is appreciated.

The Geezer

mister_e
- 30th March 2005, 05:08
IMHO, the most accurate solution is to get TIMER overflow interrupt counting the internal clock ticks. adjust the prescaller and pre-load the timer registers TMR1L and TMR1H. once you get interrupt re-load TMR1L, TMR1H.

a other way to do it simple too... can you acces to the ac-line source and divide the frequency by using internal counter to get a accurate 1 second?? I mean counting the ac-line pulses (let's say 60hz) and once you get 60 or a counter overflow interrupt do your stuff.

maybe confusing but that's food for brain cells...

GEEZER
- 30th March 2005, 05:19
Thanks Steve,

The 60 HZ is out as this will be used on AC and Battery power. I'll do a search for TMR1H and TIMR1L. It's all new to me with only a couple of months experience.

The Geezer

Melanie
- 30th March 2005, 10:14
I hate to tear other peoples code apart, but I think it's shot.

In one spot you're playing with TMR0...

TMR0 = 7

and then you're messing with TMR1...

T1CON.0 = 1 'TURNS TIMER ON

So which Timer are you using? And then what interrupt time interval are you keeping track of?

Also those Pause commands... what are you going to do when an interrupt occurs in the middle of one? Remember, you don't get an interrupt until the current PICBasic command completes.

As an example (including interrupt usage), have a look at this...

http://www.picbasic.co.uk/forum/showthread.php?t=632

GEEZER
- 30th March 2005, 13:48
Thanks Melanie, you just shot my whole timer plan. I didn't think about the pauses.

I have been writing computer routines in basic anc C for more than 20 years, 50 years of amatuer and professional electronics experience, and about 2 months of experimenting with this PIC.

This timer was to be used in a pic program that includes a 4 button - 4 line lcd interface, the analog converters and a number of digital pots, to precisely control and monitor the work of four power transistors. This program will probably strain the 8k program limit of the 16F877A.

I guess starting small is just not me.

The systems are all working except for the timer and the digital pots which arrived yesterday.

My mind just can't seem to run at 20 mHZ.

I guess I am going to have to add an outboard RTC and find a way to access it.

Is there any other way?

I surely appreciate the suggestions I have been given on this forum by you and others.

Thanks again,

The Geezer

Melanie
- 30th March 2005, 17:58
It would help if you gave us an idea of what are you are using your "exact second" for, and why it has to be so accurate.

GEEZER
- 30th March 2005, 20:07
Actually, Melanie, hundreths or thousandths would be even better. I am monitoring the current flow through transistors and keeping track of the mAH as it counts up on the LCD. When the current stops the count stops. I will be monitoring the current through 4 transistors simultaneously. With a time reference that each sub program can access, the math in the sub program can make the calculations and display them on the four lines of the LCD. When the current flow stops, the readings will remain on the LCD until the user decides otherwise.

I can do this with seconds, but the math will work even better with hundredths or thousandths, without floating point.

Melanie
- 31st March 2005, 01:58
You're obsessed! Look, you're charging/discharging batteries for Gawds sake, not measuring the velocity of a speeding bullet!

Who cares if it's exactly an hour, or an hour and 15 seconds...

Do your ADC's, do your calculations (assuming a 100mS time interval), insert a Pause 100 and simply Loop. Just forget the time for the ADC's to operate and your math time. Just do a Pause 100.

The first time you run your program insert a message to appear on your LCD after 36000 loops... (an hours worth of 100mS loops). You run a stop-watch and compare your watch against the PIC. You'll probably find it'll be an hour and a few minutes. Calculate the overspill time and reduce the Pause 100 statement accordingly. Hey presto - you're done.

Now, if it ends up a few seconds out per hour, the batteries aren't going to care, after all they're a big chemical pile and you can't predict how chemicals will react from charge to charge, let alone down to fractions of a second. You're going to charge a 2200mAH Battery for example... it'll behave differently when factory fresh to when it's a year old. Best guess is close enough. So if you're charging a Battery for an hour, so what if you charge for one hour, one minute and seventeen seconds? It's not going to hurt.

GEEZER
- 31st March 2005, 05:26
Very perceptive Mel, I'm impressed! I'll give it a try. 15 sec. an hour is less than 1%, I could live with that. One minute and fifteen seconds would not let an obsessed geezer sleep at night.

I am an old broadcast engineer, +/- 20 cycles per million in the days of vacuum tubes and crystal ovens. I'm too old to change very much now.

I didn't expect the pause command would be that accurate, but i'll try anything once.

This is a great forum, lots of idea exchange, and helpful people. It's a fast track for those just getting started, especially the chronologically handicapped.

Thanks for your help.

The obsessed Geezer