How to use a "Timer"

How to include the Timer to the program.

P.S how many 1/x bits per Sec.

Thx alot “Hamosad” team. :yikes:

one loop of the controller is 26.2 millis - approx 38 loops per second. just add a variable to count till 38 and then reset it to zero

good luck/behatzla’ha

A word of caution–I learned the hard way that this is not always true.

The loop executes at a minimum of 26.6ms, but it most certainly can take much longer than 26.6ms!
The BLROD doesn’t trigger until the code takes a whopping 1/4 to 1/2 second per loop! :ahh:

EDIT:
If you want an example of this behavior, try the 2005 default camera code.
The code slows dramatically as soon as the camera is hooked up, and as far as I can tell, takes more on the order of 1/4-second per loop.

Do not depend on loop timings! They are highly variable!

Use timer interrupts. Kevin has code on his website.

I’m a little unclear of what the actual question is. Are you asking how to use the PIC’s internal timers? How to use the timers would vary based on your application. The PIC’s timer modules can be configured as either timers or counters based on a few different internal sources (at varying speeds) as well as external sources.

If you are interested in using the timer modules I would suggest you start by reading the data sheet on the PIC micro timer modules and then reviewing Kevin’s interrupt/timer code from 2005 (he hasn’t posted 2006 code yet).

Once you’ve reviewed the above items you should have a better idea of what you are looking for, or where you may need some assistance.

We did read the PDF files and we dont know the specific code to operate the Timer.

( AKA. we dont know how to use the code thats in the “H” files ) .

Thx again : ) :ahh: :slight_smile: :ahh:

Hmm…i wouldn’t recommend using the “approx 38 loops per second” method.

If you’re looking for greater precision i recommend using the interrupt-driven timers. Our team is currently using Timer1 of the five PIC timers. Perhaps i’m not the best person to explain you exactly how they work but let me see if i can help…

First off, we created a function known as Init_timers(); (inside a .c file of our choice), which is called from inside User_Initialization() under user_routines.c.

Inside *Init_timers *we wrote the following code (to initialize and configure Timer1):

void Init_timers(void)
{

*T1CONbits.T1CKPS0 = 1; // 1:8 Prescale (clock=1.25MHz/each tick=800ns)
T1CONbits.T1CKPS1 = 1;
*
TMR1H = 0x85; // sets Timer1’s most significant byte
TMRIL = 0xED; // sets Timer1’s least significant byte

T1CONbits.TMR1CS = 0; // Uses Internal clock

*T1CONbits.T1OSCEN = 0; // Internal oscillator off

T1CONbits.RD16 = 1; // Timer1 operations done in 16-bit accesses*

*IPR1bits.TMR1IP = 0; // Sets interrupt as low priority
*
*PIR1bits.TMR1IF = 0; // Overflow flag
*
*PIE1bits.TMR1IE = 1; // Timer1 interrupt OK
*
*INTCONbits.GIEL = 1; // Low priority interrupts OK *

T1CONbits.TMR1ON = 1; // Timer1 set as on

}

Next you’ll need to add a few things inside *InterruptHandlerLow() inside user_routines_fast. *This is a system function; I.E. when an interrupt is set, this function is immediately called by IFI’s interrupt handler. You do not need to call it from anywhere in your code, however, you will need to include the following lines of code inside it. You’ll notice this function already has several “IF” loops so all you have to do is add one more…

void InterruptHandlerLow ()
{

if…]

else if (PIR1bits.TMR1IF && PIE1bits.TMR1IE) // checks to see if overflow has occured
{
PIR1bits.TMR1IF = 0; // resets Timer1 overflow
TMR1L = 0xED;
TMR1H = 0x85;
timer1_count++; // Timer1 counter incremented every 25ms
}

…]

} // end of InterruptHandlerLow() function

Since I’m assuming you’ll be working with timers inside your Autonomous code (as are we), all you’d have to do next is use "IF"s to compare the timer1_count variable. As was explained, the timer increments every 25ms, so if for example you wanted to have your robot execute a specific part of your code for 1s (=1000 ms), simple!: check if timer1_count is equivalent to 40…! For 2 seconds, 80, for 10 seconds, 400, etc etc etc…

This may not perhaps be the most accurate method but from our experiences it suited our specific needs…

Hope this helps…
any questions whatsoever, pm me…
*

oops…rather small yet important detail…don’t forget to include the “timers.h” header file inside any .c files that work with Timers… :wink:

Thx all !!! (for the help :slight_smile: )

:ahh: 21’ is comming soon :ahh: :wink:

thanks a ton. this is very useful. I think.

Do you think you could provide more details on interrupt driven timers? Does it use up one of the six interrupts your robot has? Oh, and the 25 ms timing loop, why is it 25 ms? It seems to me that the calculation is:

2 bytes*8 bits/byte = 16 bits

largest possible 2-byte integer = 2^16 - 1 = 65535

And 800 ns*65535 =52.428 ms

You seem to get half of that…

I’m not doubting the correctness of 25 ms, I just wonder as to why it is 25 ms…

TMR1H = 0x85; // sets Timer1’s most significant byte
TMRIL = 0xED; // sets Timer1’s least significant byte

Rather small detail…on my posts above i made a typo mistake … TMRIL should be TMR1L…so don’t panic if you’re getting any “symbol undefined” errors!! Sorry about that…:yikes:

Now a few comments on the 25 ms loop…:

OK up to that point that’s correct… according to the Timers White Paper found here:(http://www.ifirobotics.com/docs/timers_white_paper_2004-jan-14.pdf) the following formula should give you what you want:

# of ticks = (time elapsed) * 10^7s / (prescale factor)

As you said above, with a 16 bit timer, counting to 65535, we can measure 6.5535 ms (considering the fact that the internal clock is 10MHz). What happens is that this duration is far too small to use for real applications, so then we used a prescale factor. In this case, we’re using one of 8. This means that the timer will only increment once every eight ticks, therefore it will overflow after 52.428 ms. So that is where and how you got this value.

OK up to that point i think we can agree on. Now, we use the formula above to find the # of ticks we need to get a nice even interval of 25 ms (= 0.025 s):

# of ticks = (time elapsed) * 10^7s / (prescale factor)
# of ticks = (0.025) * 10^7s /(8)

Using the last equation we find that we need 31250 ticks to do this. Since it is easier to look at an overflow condition in the timer, we will preload the timer with a value that will cause this overflow after 31250 ticks. To get this value we subtract 31250 from the 16-bit timer’s maximum value (65535) and get 34285.

Therefore we get **65535 **(timer’s max value of ticks) - **31250 **(number of ticks we need) = **34285 **(preload value).

This is the value we will preload our timer with. In the code written above you will see 34285 represented in hexadecimal as 0x85ED. Which pretty much explains why the following lines are written the way they are:

TMR1H = 0x85; // sets Timer1’s most significant byte
TMR1L = 0xED; // sets Timer1’s least significant byte

So, if for example you wanted to work a different time interval (50 ms, let’s suppose) use the formula to find out the number of ticks you will need, subtract that value from 65535 and convert the result of that into hexadecimal. That will get you your preload value.

Hope this helps…

Oh alright. I somehow overlooked the preload values.

So, how do I set a sclaing factor? In your code there seems to be a line that sets it to one yet it’s 8…

There is one problem with this

the timer link you have is for the 8520 controller the new controller is the 8720 and I can’t get the code that was given in this thread to work has any one else???
also does any one have the code/“white papers” for the 8720 timers???
or is it the same and we just messed with it too much???

Check out the OpenTimer#() functions in this PDF:

It’s very useful.

The new PIC is 8722 not 8720 and the processor runs at 40 MHz but the prescaler examples are assuming the procesor is running at 10 MHz.

This is the actual Pic18F8722 data sheet:http://www.kevin.org/frc/PIC18F8722_ds.pdf

Check out the OpenTimer#() functions in this PDF:
http://www.kevin.org/frc/C18_libraries.pdf

It’s very useful.

That is just he C18 complier library to help with timers and stuff but not the actual Pic data sheet.

How do I use another timer? The way I’m having things work right now, I’m already using Timer 1 to do something. Now I want another timer to do something else? How can I do that? And if there are two timers firing interrupts at the same time, is that going to mess things up? I heard that the five timers in the FRC are all different, so how do I use another timer?

It wasn’t meant to be a link to the datasheet, and yes it is in fact a 10MHz clock. I’m using those to generate a 4ms overflow timer, and I’ve verified its speed by having a printf every 250 overflows (one second) and timing it with my watch, as well as a few other people who concur, its definitely 10MHz.


void Initialize_Clock(void)
{
/* Use Timer3 (16-bits) to control our clock */
/* timer set to 4 ms */

  OpenTimer3(TIMER_INT_ON &
             T3_16BIT_RW &
             T3_SOURCE_INT &
             T3_PS_1_8
             );

  // Maximum for 16-bit 65535 - 5000 (4ms) = 60535
  WriteTimer3(CLOCKOFFSET);  /* Preload timer to overflow after 4ms */
}

Make sure to include timers.h

Sorry I ment the clock speed is 40 MHz but the timer incriments one every 4 of them. Same with the processor instructions cycle. It is 1/4 the speed of the clock.

The example has a 10MHz clock but but the acutal ticks on the timer are only 2.5 MHz so per second(assuming 1 to 1 prescale). So on the robot controller you have to multiply that number by 4 to get the real number of ticks per second( If you are going by the example in Kevin Watson’s interrupt code or the data sheets).

Huh?

I’ve never heard of it running a 40MHz clock and none the tests I’ve run support that, they do however support a 10MHz clock.

For example, the code example I posted previously is a 4ms clock.
I preloaded the timer with 60535 so it would overflow 5000 ticks later (65535).
4ms / 5000 = 800 ns per tick
1 second / 800 ns = 1,250,000 ticks = 1.25 MHz
1.25MHz * 8 (1 to 8 prescale) = 10MHz

If I missed something, can you point out where I can find it? I’m genuinely confused and I don’t understand where you got your numbers from.

Hopefully helping,
Matt