Expanding Timer1 counting range


Closed Thread
Results 1 to 15 of 15
  1. #1
    Join Date
    Dec 2007
    Location
    Malaysia
    Posts
    20

    Default Expanding Timer1 counting range

    I use Timer1 as a free running timer, using 4Mhz clock and 16F877A MCU. I do not know how to extend the timer range as it is from 0 to 65536 microsecond using 4Mhz clock.

    Can anyone teach me to extend the timer range from 0 to 5 seconds?

    Thanks in advance.
    Last edited by sycluap; - 13th January 2008 at 12:56.

  2. #2
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,611


    Did you find this post helpful? Yes | No

    Post

    Hi,

    Hardw.solution : Just use the external TMR1 clock with a 32,768 Hz Xtal ... easily gives 1 count per ms !!!

    SoftW.Solution : increment a variable for each overflow ( interrupts using or polling the overflow bit TMR1IF )

    Also See Darrel's posts about instant interrupts ... The Hardw solution is described here !!!

    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  3. #3
    Join Date
    Dec 2007
    Location
    Malaysia
    Posts
    20


    Did you find this post helpful? Yes | No

    Default

    I am using 4MHZ, 16F877a, Timer1, setting TMR1H = $00 and TMR1L = $00. Tried to activate the timer as free running timer. Previously used to capture the timer time from 0 - 65536 microseconds (full range). Now that I am trying to extend the timer range and to respond to 1ms interval, I change the TMR1H = $FC and TMR1L = $18, with the codes below to capture the timer1 overflow.

    Looping:
    While PIR1.0=0
    Wend
    PIR1.0=0
    TimerOverflow=TimerOverflow+1
    LCDOUT $FE,$C0,DEC5 TimerOverFlow
    If ButStop = 1 Then goto StopTimer
    Goto Looping

    But I am unable to get in 1ms interval. Can anyone guide me on this?

  4. #4
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,611


    Did you find this post helpful? Yes | No

    Default

    You just need to preload Timer 1 with a value "not so far" from 65536 - 1000 ... no more free running timer usable !!!

    it will overflow for 1000 counts = 1 ms ...

    "not so far" mean you have to add the time to reload the timer and do what you want to the "64536" value ...

    See Steve's ( Mr E !!! ) calculator here : http://www.mister-e.org/pages/utilitiespag.html


    I also forgot you could use the "compare" function of the CCP module ... and poll the CCPIF bit !

    Alain
    Last edited by Acetronics2; - 13th January 2008 at 15:26.
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  5. #5
    Join Date
    Dec 2007
    Location
    Malaysia
    Posts
    20


    Did you find this post helpful? Yes | No

    Default

    Yeah, I did make TMR1H = $FC, TMR1L=$18, which is obtained from 65536-1000. But the timer does not give me 1ms interval. I do not know what is wrong. Below is my program:

    'MAIN PROGRAM
    '------------
    ResetTimer:
    GoSub SetReg
    LCDOUT $FE, 1
    Timer1H = 0
    Timer1L = 0
    Result = 0
    TimerOverflow = 0

    Main:
    LCDOUT $FE, $80, "Test Mode 1"
    LCDOUT $FE, $C0, "Visual Response Test"
    If ButStart = 1 Then goto StartTimer
    Goto Main

    StartTimer:
    LCDOUT $Fe, 1
    LCDOUT $FE, $80, "Calculating..."
    T1CON.0=1

    Looping:
    While PIR1.0=0
    Wend
    PIR1.0=0
    TimerOverflow=TimerOverflow+1
    LCDOUT $FE,$C0,DEC5 TimerOverFlow
    If ButStop = 1 Then goto StopTimer
    Goto Looping

    StopTimer:
    T1CON.0 = 0
    LCDOUT $Fe, 1
    GoSub GetValue

    DisplayResult:
    Result = TimerOverflow
    LCDOUT $FE,$C0, dec5 Result
    If ButStart = 1 Then goto StartTimer
    If ButReset = 1 Then goto ResetTimer
    goto DisplayResult


    'SUBROUTINES
    '===========
    'Reset Timer1 Register to Start from 1ms interval
    '-------------------------------------------------------
    SetReg:
    TMR1H = $FC
    TMR1L = $18
    Return

    Is there anything wrong with the program that cause the Timer unable to display 1ms interval timing on LCD?
    Last edited by sycluap; - 13th January 2008 at 15:57.

  6. #6
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,611


    Did you find this post helpful? Yes | No

    Post

    Your LCD display is unable to show time for EACH ms ... the LCDOUT command needs much more thant 1 ms - OR you should use LED Display ...

    With that way of programming You might have enough time to refresh the display between two interrupts ...

    Here, to be accurate ... you just can display exact time ONLY once timer stopped !!!


    see How Darrel's "Elapsed timer Demo " works ... and you will be able to see "intermediate time"

    http://www.picbasic.co.uk/forum/show...=Elapsed+timer


    Alain

    PS: you can read the ms "on the fly" .... Wooowww !!! you got a fantastic pair of eyes !!!
    LOL ...
    Last edited by Acetronics2; - 13th January 2008 at 17:16.
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  7. #7
    Join Date
    Dec 2007
    Location
    Malaysia
    Posts
    20


    Did you find this post helpful? Yes | No

    Default

    The additional line of code after the clear overflow flag is to test the timer whether the timing is accurate or not. Let's say of ms can't be seen, but at least for the seconds can be seen accurately right? Previously the coding was to display the final value directly on the LCD after Stop button is pressed. Conclusion is, I wonder the 1ms interval can be achieved or not.

    From my codes structure, is achieving 1ms interval timing possible? Is there any modification need to be carried out besides displaying final timing value on LCD, in order to achieve 1ms interval timing?
    Last edited by sycluap; - 13th January 2008 at 17:34.

  8. #8
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Acetronics View Post
    Your LCD display is unable to show time for EACH ms ... the LCDOUT command needs much more thant 1 ms - OR you should use LED Display ...
    Actually, most of the LCDs I've got, usually the 16x2, are able to handle a commandus of around 100 and a dataus of 50 (the best one I've got will do commandus = 50 and dataus = 27, well below that datasheet values).
    So, assuming you don't have too much to display, theoretically, you could refresh one complete line on a 16x2 LCD inside of 1ms...assuming that is

    (and I knew this thread was coming)

  9. #9
    Join Date
    Dec 2007
    Location
    Malaysia
    Posts
    20


    Did you find this post helpful? Yes | No

    Default

    Is that mean the culprit for unable to get 1ms interval timer is the LCD display? What is I just make it display the final value upon stop button is pressed? Can this solve the problem?

  10. #10
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by sycluap View Post
    Is that mean the culprit for unable to get 1ms interval timer is the LCD display? What is I just make it display the final value upon stop button is pressed? Can this solve the problem?
    Are you completely incapable of doing any 'out of the box' thinking? Kick your brain into gear! Just because the LCD takes longer than 1ms to display (which is not necessarily true, but at default settings is true), doesn't mean the PIC can't keep counting until you stop it from counting and then displaying the result when it is done counting.
    What are you counting that supposedly requires microsecond accuracy anyways?

  11. #11
    Join Date
    Dec 2007
    Location
    Malaysia
    Posts
    20


    Did you find this post helpful? Yes | No

    Default

    Not that I can't think out of the box, but I've asked around and tried whatever is possible, to display counting in LCD, not to display in LCD, to display only the final value, etc, but i still can't manage to get the timer to display in 1ms timing interval. I know that the PIC can continue counting by itself, but, even I try to make it display only the final value, but it still can't display the accurate readings.

    Sorry for asking questions that might consider too easy for some others, but I am totally new in this. I need the timer to measure the human response time.

    MY CODE:

    'MAIN PROGRAM
    '------------
    ResetTimer:
    GoSub SetReg
    LCDOUT $FE, 1
    Timer1H = 0
    Timer1L = 0
    MicroThousandths = 0
    Thousandths = 0
    Hundredths =0
    Seconds = 0

    Main:
    LCDOUT $FE, $80, "Test Mode 1"
    'LCDOUT $FE, $C0, "Visual Response Test"
    If ButStart = 1 Then goto StartTimer
    Goto Main

    StartTimer:
    LCDOUT $Fe, 1
    LCDOUT $FE, $80, "Calculating..."
    T1CON.0=1

    Looping:
    While PIR1.0=0
    Wend
    PIR1.0=0
    Thousandths=Thousandths+1
    If Thousandths>9 Then
    Thousandths=0
    Hundredths=Hundredths+1

    If Hundredths>99 Then
    Hundredths=0
    Seconds=Seconds+1
    Endif
    Endif

    If ButStop = 1 Then goto StopTimer
    Goto Looping

    StopTimer:
    T1CON.0 = 0
    LCDOUT $Fe, 1
    GoSub GetValue

    DisplayResult:
    LCDOUT $FE, $80, "Time Elapsed"
    LCDOUT $FE,$C0, dec2 Seconds, ".", dec2 Hundredths, ":", dec Thousandths
    If ButStart = 1 Then goto StartTimer
    If ButReset = 1 Then goto ResetTimer
    goto DisplayResult


    'SUBROUTINES
    '===========
    'Get value from Timer1 Register
    '------------------------------
    GetValue:
    Timer1H=TMR1H
    Timer1L=TMR1L
    Return

    'Reset Timer1 Register to Start from 1ms interval
    '-----------------------------------------
    SetReg:
    TMR1H = $FC
    TMR1L = $18
    Return

    Now, what is wrong with my codes? Correct me please.
    Last edited by sycluap; - 14th January 2008 at 03:47.

  12. #12
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by sycluap View Post
    Not that I can't think out of the box......
    Big hints for you back in post's #5 and #7.

  13. #13
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    I think you're way over-doing this in the first place.
    So, what you want is a program to start counting when you hit one button, and stop counting when you hit a second button, and display the time interval between the 2 right?

    some generic code (you fill in the crap with real code)
    Code:
    'Set up all variables, registers, timers, etc... No interrupts
    
    'display start message
    
    'wait for start button to be hit, if it's not hit, don't jump back to the lcdout display command
    
    'takes time to display and might miss a button push in the meanwhile
    
    'if the button is hit, reset tmr1 to zero and start the timer
    
    'start a loop
    
    'display the current count (which will take longer than 1ms, but the next bunch will take care of that, again, the problem with displaying stuff during a tight count is that you will miss the exact time that a button is pushed and the count could possibly be off by 1 or 2 ms)
    
    'if the tmr1 value is above 1000, add 1 to the ms counter and subtract 1000 from tmr1 (3 from tmr1h and 232 from tmr1l, or subtract 4 from tmr1h and add 24 to a subcounter to cover the extra 24us.  when that subcounter exceeds 1000, add another one to the ms counter
    
    'check the stop button
    'if the stop button is not pushed, jump back to the loop
    'if the stop button is pushed, immediately save the tmr1 count, do the 'over 1000' math to keep the ms count and us count, and display the total
    No, not real code, an outline as a guide.

    Interrupts are nice, and DT interrupts and the Olympic timer are all you need, but apparently it's not enough to have almost 100% pre-written code made just for you.

    This code is based on the fact that you keep timer1 BELOW a certain value and keep track of it as it counts UP. That way if you miss a count or two, you can always recheck it (i.e. tmr1 is 3000, you've missed 3ms, no biggie, just subtract 1000 from it 3 times and you're back on track). I built an OBD2 reader that's based off this to drive my virtual odometer, integrates time and speed. In the process of reading the OBD2 message, I miss a count here and there. No problem, just let the counter increase in the background and cover it up later. The intervals are short enough that I get a nice accurate reading (within 1/10 mile over a 263 mile drive 2 weeks ago) and long enough that the timer won't overflow in between readings.
    Make any sense yet?

  14. #14
    Join Date
    Dec 2007
    Location
    Malaysia
    Posts
    20


    Did you find this post helpful? Yes | No

    Default

    Thanks for the guide. I have clearer idea now. Sorry for OVERDOING it. But at least Mr.Skimask and Mr.Acetronics is willing to help me out. Thanks.
    Last edited by sycluap; - 14th January 2008 at 05:32.

  15. #15
    Join Date
    Jan 2007
    Posts
    78


    Did you find this post helpful? Yes | No

    Default Re: Expanding Timer1 counting range

    Hello sycluap,
    In your code, where you have initiate time counting:

    Looping:
    While PIR1.0=0
    Wend


    It appears that you are allowing the timer1 to overflow and then checking to see if the button has been released. This leads me to assume that you don't care if the button is released during the time Timer1 takes to reach rollover.
    If this is the case, then is the use of Timer1 really necessary?
    If you don't need resolution under a uSec then you might consider using the PBP3 "pauseus" command to create the 1 uSec.
    1) Start button is pressed
    2) pauseus 1 (delay 1uSec)
    3) count0 = count0 + 1
    4) if count0 = 65535 then count1 = count1 + 1; count0 = 0
    5) check button ( if still pressed loop again)

    In this case, you can capture ( minimum 1 uSec - maximum 4294 seconds).
    For the math, just use count1 value as a multiplier of 65535
    So, then if count1 = 40 you have (65535*40) = 2.6214 seconds accumulated in count1
    and then you just add count0 value to that to get the total.


    for loop1 = 1 to count1
    for loop2 = 1 to 5
    micro_sec = micro_sec + 13107
    while micro_sec > 999
    milli_sec = milli_sec + 1
    micro_sec = micro_sec -1000
    wend
    while milli_sec > 999
    sec = sec + 1
    milli_sec = milli_sec - 1000
    wend
    next
    next
    Lcdout $fe, 1, #sec,":",#milli_sec,":",#micro_sec



Similar Threads

  1. Software PWM using Timer1
    By muqasim in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 18th December 2009, 12:49
  2. Help with TIMER1 + SLEEP
    By Yodoad in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 22nd May 2009, 16:07
  3. Time Period of Timer1
    By arnol34 in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 4th May 2007, 01:31
  4. continious counting process (capture)
    By asynch in forum General
    Replies: 1
    Last Post: - 17th February 2006, 08:42
  5. Timer1 and Interupt wierdness
    By mind in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 23rd August 2005, 02:24

Members who have read this thread : 2

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts