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.

Software Trim Idea

Status
Not open for further replies.

Suraj143

Active Member
My clocks time base is done with TMR0.

Can somebody explain me how to do a software trim for the TMR0.

Because my clocks timing is varying.

No need codes just tell me the idea

Thanks
 
If you're presetting TMR0 it will be very difficult to keep it accurate, free running mode is best. Roman Black has an article on this.
Official Home Page of Roman Black
PS TMR1 has a wonderful connection to the CCP1 special interrupt (mode 14) which can form an excellent timebase for a clock.
 
If you're presetting TMR0 it will be very difficult to keep it accurate, free running mode is best. Roman Black has an article on this.
Official Home Page of Roman Black
PS TMR1 has a wonderful connection to the CCP1 special interrupt (mode 14) which can form an excellent timebase for a clock.

Yes I'm resetting TMR0.I have every 10ms T0IF interrupts & I count 100 to generate 1 second.

On every T0IF interrupts I reload TMR0.
 
The problem with reloading TMR0 is it resets the prescaler and other such stuff. Allowing it to freerun is the better way to do it. It'll set TMR0IF on overflow and use Romans zero error clock algorithm for getting a 1 second timebase.
 
Usually you just don't reload a timer with a calculated value. You add the current Timer value + your calculated value + amount of cycle it need to reload your timer.

HTH

TMR0=TMR0 + ReloadValue + SomeCallItFudgeFactor

From the datasheet said:
If the TMR0 register
is written, the increment is inhibited for the following
two instruction cycles. The user can work around this
by writing an adjusted value to the TMR0 register.
 
Last edited:
If you set the prescaler to 32 then the timer will overflow every 8192 cycles - close to your current 10,000. Use Roman Blacks code to subtract 32 from the middle byte and add the 1,000,000 when the top bytes become zero. This will give you a very accurate clock.

Mike.
 
If you set the prescaler to 32 then the timer will overflow every 8192 cycles - close to your current 10,000. Use Roman Blacks code to subtract 32 from the middle byte and add the 1,000,000 when the top bytes become zero. This will give you a very accurate clock.

Mike.

Hi thats a good way I'll try to like that.

Thanks
 
I just realised that adding 32 will not work with Roman Blacks code. It needs to be modified to,
Code:
		movlw	.32		;subtract 32*256 from accumulator
		subwf	AccHi,F
		skpnc
		goto	DoneTimer
		decfsz	AccUp,F
		goto	DoneTimer

;only gets here if 1 second has passed

		movlw	low(.1000000)	;add 1 million to the accumulator
		addwf	AccLo,f
		movlw	high(.1000000)
		skpnc
		addlw	1
		addwf	AccHi,f
		skpnc
		incf	AccUp,F
		movlw	upper(.1000000)
		addwf	AccUp,F
DoneTimer	bcf	INTCON,TMR0IF
The three variables AccLo, AccHi and AccUp can be initialised to 1.

Mike.
 
What are you using TMR2 for? You might be able to use it for both your current purpose and for the RTC 'heartbeat'.

There's a brief description of a software trimmer function here (for timer 2).

Regards, Mike
 
Last edited:
Hi Mike (Pommie) thanks for your new code thats the one I like to put.

Hi Mike, K8LH

I need a 2.5Khz separate frequency to drive a speaker.So I using PWM module.Thats why I cannot use TMR2.
 
I need a 2.5Khz separate frequency to drive a speaker.So I using PWM module.Thats why I cannot use TMR2.

If you set timer2s postscaler to 10 you will get an interrupt at 250Hz which you could use for the clock timebase. This will not effect your PWM output at all. To turn off the 2.5kHz signal set the pulse width to zero.

Mike.
 
If you set timer2s postscaler to 10 you will get an interrupt at 250Hz which you could use for the clock timebase. This will not effect your PWM output at all. To turn off the 2.5kHz signal set the pulse width to zero.

Mike.

Hi Mike thats a clever method.It didn't come to my mind.I can't think like you all think.Because I'm very new to this subject.

So that means I can do both works (time base + speaker output frequency) from a single TMR2.Wow thats very nice.

Thanks for the help I'm going to try that as well.
 
At the moment I'm studying roman blacks original code.I have got stuck with that.Sorry about that.

First it loads accumulator to 100000+256=100256uS.
Every 256uS it generates interrupt.& every 256uS interrupts he subtract 256 from accumulator.

When continue subtracting theres a point coming you cannot subtract anymore.That is 100096uS.So balance is 160uS remaining (100256uS-100096uS =160uS) .

I'm not sure what he is doing for this 160uS :(
 
Roman Blacks code simply subtracts 256 from a 24 bit counter by decrementing the middle byte. Whenever the value goes below 256 (top two bytes are zero), he adds 1,000,000 to the 24 bit counter. This means that, on average, the seconds will be be incremented every 1,000,000 cycles. The actual seconds will vary slightly (by up to 255uS) but overtime the errors cancel out and so it is very accurate.

The code I posted above does the same thing except I subtract 8192 by subtracting 32 from the middle byte. This is simply because I didn't like the idea of an interrupt every 256 cycles.

Mike.
 
Roman Blacks code simply subtracts 256 from a 24 bit counter by decrementing the middle byte. Whenever the value goes below 256 (top two bytes are zero), he adds 1,000,000 to the 24 bit counter.

Totally understood.

The code I posted above does the same thing except I subtract 8192 by subtracting 32 from the middle byte. This is simply because I didn't like the idea of an interrupt every 256 cycles.

I also like your method.I'm going to use it.

This means that, on average, the seconds will be be incremented every 1,000,000 cycles. The actual seconds will vary slightly (by up to 255uS) but overtime the errors cancel out and so it is very accurate.

This is the place I got stucked :(

That means on every second the time will be vary.I mean I'm getting like this

100096uS
100096uS
99840uS
100096uS
100096uS

For the first five seconds average is = 100044.8uS
 
If you run it through a spreadsheet you get,
Code:
Start		Remainder	Time		Plus 1 Million	Total Time
1000000		64		0.999936	1000064		0.999936
1000064		128		0.999936	1000128		1.999872
1000128		192		0.999936	1000192		2.999808
1000192		0		1.000192	1000000		4
1000000		64		0.999936	1000064		4.999936
1000064		128		0.999936	1000128		5.999872
1000128		192		0.999936	1000192		6.999808
1000192		0		1.000192	1000000		8
1000000		64		0.999936	1000064		8.999936
1000064		128		0.999936	1000128		9.999872
1000128		192		0.999936	1000192		10.999808
1000192		0		1.000192	1000000		12
1000000		64		0.999936	1000064		12.999936
1000064		128		0.999936	1000128		13.999872
1000128		192		0.999936	1000192		14.999808
1000192		0		1.000192	1000000		16
1000000		64		0.999936	1000064		16.999936
1000064		128		0.999936	1000128		17.999872
1000128		192		0.999936	1000192		18.999808
1000192		0		1.000192	1000000		20
Notice how every 4 seconds the total time is exact.

<edit>I just noticed you're only adding 100,000 in your calculations.</edit>

Mike.
 
Last edited:
Hi Mike thanks for spending your time on this.Actually it is really helpful.I'm analizing your results.

One more question.
At start how did you get 64 remainder?From what value did you divide?
Roman Black initialize his accumulator with 100256uS on power up.
 
hi Suraj,
A related point to the clock 'accuracy', what range of ambient temperatures is the 16F88 working over.
Either the internal osc or the external osc if applicable.:)
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top