Log in

View Full Version : SOLVED - How to calculate Timer preload



Demon
- 23rd August 2024, 01:21
From Art's Timer thread here:

https://www.picbasic.co.uk/forum/showthread.php/20013-Elapsed-Timer-findings?p=131978#post131978


Hi Guys,

...For the 20MHz example where the constant is 03B7h, it's the reverse of this:

FFFFh - 03B7h = C348h (49992 decimal),
49992 + 8 = 50000 (it must take eight instruction cycles to reload the timer)
50000 / 10000 = 5
5 x 4 = 20MHz

...Cheers, Art.

If I reverse these steps for a 16F1936 at 32MHz, I get this:

32 / 4 = 8
8 x 10000 = 80000
80000 - 8 = 79992

And that's where I block; 79992 is > 65535

What am I doing wrong?

I assume this is where the Prescaler comes into play, but I don't know how.


EDIT: So far, I have this for T1CON:


T1CON = %01010100 ; Prescaler=1:1, TMR3ON.
' bit 7-6 TMR1CS<1:0>: Timer1 Clock Source Select bits
' 01 =Timer1 clock source is system clock (FOSC)
' bit 5-4 T1CKPS<1:0>: Timer1 Input Clock Prescale Select bits
' 01 = 1:2 Prescale value
' bit 3 T1OSCEN: LP Oscillator Enable Control bit
' 0 = Dedicated Timer1 oscillator circuit disabled
' bit 2 T1SYNC: Timer1 External Clock Input Synchronization Control bit
' 1 = Do not synchronize external clock input
' Unimplemented: Read as ‘0’
' bit 0 TMR1ON: Timer1 On bit
' 1 = Enables Timer1


I'm still looking how to use Prescaler in Art's formula.

(moved my post out of Art's thread)

Demon
- 23rd August 2024, 02:04
SOLVED

16F1936 at 32MHz:

1) Elapsed_INT.bas, used Preload from 16 MHz,


If OSC == 32
TimerConst = 063C7h
EndIF

2) Set TMR1CS to Fosc/4

3) Set T1CKPS to 1:2 Prescaler

It runs at same speed as timer on my cell phone.

Compete code:


@ ERRORLEVEL -301 ; turn off ADC clock ignored message
@ ERRORLEVEL -306 ; turn off crossing page boundary message

#CONFIG
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _VCAPEN_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
#ENDCONFIG

DEFINE OSC 32

SPLLEN CON %1 ' PLL enable
IRCF CON %1110 ' to enable 8 MHz
SCS CON %00 ' system clock determined by FOSC
OSCCON = (SPLLEN << 7) | (IRCF << 3) | SCS

INCLUDE "DT_INTS-14.bas"
INCLUDE "ReEnterPBP.bas"
Include "Elapsed_INT.bas"

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _ClockCount, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = %00010101 ; Prescaler=1:1, TMR3ON.
' bit 7-6 TMR1CS<1:0>: Timer1 Clock Source Select bits
' 00 =Timer1 clock source is instruction clock (FOSC/4)
' bit 5-4 T1CKPS<1:0>: Timer1 Input Clock Prescale Select bits
' 01 = 1:2 Prescale value
' bit 3 T1OSCEN: LP Oscillator Enable Control bit
' 0 = Dedicated Timer1 oscillator circuit disabled
' bit 2 T1SYNC: Timer1 External Clock Input Synchronization Control bit
' 1 = Do not synchronize external clock input
' Unimplemented: Read as ‘0’
' bit 0 TMR1ON: Timer1 On bit
' 1 = Enables Timer1

DEFINE LCD_DREG PORTB ' Set LCD data port
DEFINE LCD_DBIT 0 ' Set starting data bit
DEFINE LCD_RSREG PORTC ' Set LCD register select port
DEFINE LCD_RSBIT 5 ' Set LCD register select bit
DEFINE LCD_EREG PORTC ' Set LCD enable port
DEFINE LCD_EBIT 4 ' Set LCD enable bit
DEFINE LCD_BITS 4 ' Set LCD bus size
DEFINE LCD_LINES 4 ' Set number of lines on LCD
DEFINE LCD_COMMANDUS 1000 ' Set command delay time in microseconds
DEFINE LCD_DATAUS 50 ' Set data delay time in microseconds

define CCP4_REG PORTC ' PWM Pulse out to LCD contrast
DEFINE CCP4_BIT 1 ' 2N2907 PNP with 1K on base
define CCP5_REG PORTC ' PWM Pulse out to LCD backlight
DEFINE CCP5_BIT 2 ' 2N2222A NPN with 1K on base

ANSELA = %00000000
ANSELB = %00000000

TRISA = %00000111
TRISB = %00110000
TRISC = %10000000
TRISE = %00000000

HPWM 2,100,1953
HPWM 1,180,1953

@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
Gosub ResetTime ' Reset Time to 0d-00:00:00.00

Pause 500 ' Let PIC and LCD stabilize

LCDOUT $FE, 1 : Pauseus 1

GOSUB StartTimer ' Start the Elapsed Timer

Mainloop:

IF SecondsChanged = 1 THEN
SecondsChanged = 0
LCDOUT $FE,2, DEC Days,"d-",DEC2 Hours,":",DEC2 Minutes,":",DEC2 Seconds
ENDIF

goto mainloop
end

Demon
- 23rd August 2024, 02:17
Art's formula with Prescaler:

65535 - (((( MHz / Prescaler ) / 4 ) x 10000 ) - 8 )

Ioannis
- 23rd August 2024, 06:21
What are the 10000 and 8 stand for in the equation?

Ioannis

Demon
- 23rd August 2024, 11:40
I couldn't tell you. See Art's thread above.

tumbleweed
- 23rd August 2024, 14:30
What are the 10000 and 8 stand for in the equation?

The 10000 comes from the fact that the intr code is assuming a 100Hz interrupt (MHz -> 100Hz = 10000),
and the 8 is an attempt to compensate for the number of instruction cycles it takes to reload the timer.

Demon -
How long of a time period are you looking to measure?
If you can live with 65536 counts (the 16-bit timer count) then you can just drop all the interrupt code, let the timer free-run, and just subtract two unsigned timer values... something like this:


start_time = readtimer()
'code you wish to time is here
elapsed_time = readtimer() - start_time

tumbleweed
- 23rd August 2024, 14:59
If you let the timer free-run, then at 32MHz using FOSC/4 as the timer clock and 1:1 prescaler you can count up to 8192us (8ms) with 125ns/count.
Setting the prescaler to 1:8 extends this to 8x8192 = 65536us (roughly 65ms), but your resolution drops to 8x125ns = 1us

Demon
- 23rd August 2024, 17:33
Tumbleweed, that's the thing. I'm still at the research phase; trying to determine what Henrik calls velocity sensing.


Next challenge: Velocity sensing, ie a way to detect that the user wants the value to change by a lot and not have to turn the knob 600 turns. Getting that just right seems to be tricky, even the big boys don't always... (I've never tried).



I can flick the rotary encoder at 3.5msec from low-low to high-high, but still need to determine that cut-off speed.

https://www.picbasic.co.uk/forum/showthread.php/26768-My-rotary-encoder-adventures?p=156000#post156000


And then it hit me as I'm typing this post. I can use the logic probe in real-time to find that sweet spot, instead of writing code to display that on LCD (or xmit via HSEROUT). And that's where things get crazy cause all that extra code and I/O would definitely throw off my readings.

Can't see the forest for the trees... :rolleyes: