[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 771
  • Last Modified:

Accuracy of Timer Control

I am trying to get an accurate timer control, however, I realised that the Timer control of VB 6 does not seemed to be too accurate.  Is there a more accurate timer or are there ways to make the Timer control more accurate?

Tks in advance

Ivanc
0
ivanc
Asked:
ivanc
  • 12
  • 11
  • 7
  • +3
1 Solution
 
VbmasterCommented:
You can check what the Timer function returns, this returns the number of seconds elapsed since midnight. One way of doing it would be to use a Timer control with a more narrow interval than you actually need and check the Timer function to see if the timer code is to be run, otherwhise just use Exit Sub to exit the timer.
0
 
ivancAuthor Commented:
vbmaster

I have actually set the timer interval to 1, that means to say that every 1ms it would run timer function.  HOwever, I realise that by putting an integer and increment when the integer reaches 1000, the time elasped is more than 1 sec.  Is there a way to ensure that the time elasped is exactly as stated.

Tks in advance

Ivanc
0
 
ivancAuthor Commented:
vbmaster

I have actually set the timer interval to 1, that means to say that every 1ms it would run timer function.  HOwever, I realise that by putting an integer and increment when the integer reaches 1000, the time elasped is more than 1 sec.  Is there a way to ensure that the time elasped is exactly as stated.

Tks in advance

Ivanc
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
mark2150Commented:
Setting the timer interval to 1 doesn't work.

You have to understand that the only reliable time tick on the PC is the 18.2Hz main time-of-day (TOD) clock. This will give you an interval no finer than 55ms or so. There is simply no possibility of measuring time on a "vanilla" PC with resolution tighter than this.

Even though the control is denominated in units of ms, it's actually a farce as what it *counts* will be multiples of 55ms. So you can get 55ms, 110ms 165ms, 220ms etc. and even then the timing jitter will be +- one 55ms tick.

Now some controls can tap the timer on the sound card or you can add timer hardware, but the baseline PC simply CANNOT measure time with better than 55ms resolution. Any *software* control that says it can on a *baseline* PC is *LYING*.

You can't rely on software timing loops in a heavily interrupt driven environment.

The only way that the PC can "measure" times less than 55ms is to measure multiple occurances of the event, take the total elapsed time and then divide down to get an average. There is simply no way that a PC can directly measure time intervals shorter than one 18.2Hz tick.

This question has come up many times and no-one has *EVER* been able to prove me wrong on this.

M
0
 
caraf_gCommented:
Hello ivanc. You cannot use the VB timer for accurate timings.... But there are ways around it.

As long as the required interval is not too short, you can achieve acceptably accurate timing intervals with a timer set at a short interval (< 1/5 of the required interval) and clever use of the Now function.

Simply keep the start time, and compare it to Now in each iteration of the timer (using DateDiff), and execute code when appropriate.

Hope this helps.
0
 
caraf_gCommented:
PS - mark2150 is right, and my solution uses Now which basically gives you the PC's time according to its main Time of Day clock.
0
 
johnny6Commented:
The following information comes directly from "Visual Basic 5 Interactive Course" by John Harrington et al:

"The Timer control is limited in that the maximum interval allowed is 65,536 milliseconds.
Even though the timer Interval property is measured in milliseconds, the system only generates 18 clock ticks per second, so the actual precision of a timer interval is no more than 1/18th of a second, which is a little over 55.5 milliseconds.
If your application is performing intensive computing like querying a database, accessing a network, or performing file input or output, your application may not get the Timer events as often as the Interval property specifies.  Also, the interval is not guaranteed to fire the event exactly on time.  If you need precision timing, use the GetSystemTime API function.
Using a small timer interval can slow system performance because the Timer events are continuously triggered. Do not use a small interval unless you really need one."
0
 
ivancAuthor Commented:
Guys

I am really grateful for your analysis and I truly have a better understanding of this timer issue.

I would like to ask if any of you can give me some guidelines of getting a timer function that acts like a timer function.

Johnny6 you pointed the usage of getsystemtime api can you elaborate

Tks in advance

Ivanc
0
 
johnny6Commented:
Ivanc:
The following program makes use of the GetSystemTime API call:


Option Explicit
Private Const LOCALE_SYSTEM_DEFAULT& = &H800
Private Const LOCALE_USER_DEFAULT& = &H400


'**********************************
'**  Type Definitions:

#If Win32 Then
Private Type SYSTEMTIME
        wYear As Integer
        wMonth As Integer
        wDayOfWeek As Integer
        wDay As Integer
        wHour As Integer
        wMinute As Integer
        wSecond As Integer
        wMilliseconds As Integer
End Type

Private Type TIME_ZONE_INFORMATION
        Bias As Long
        StandardName As String * 64
        StandardDate As SYSTEMTIME
        StandardBias As Long
        DaylightName As String * 64
        DaylightDate As SYSTEMTIME
        DaylightBias As Long
End Type

#End If 'WIN32 Types

'**********************************
'**  Function Declarations:

#If Win32 Then
Private Declare Function GetLocaleInfo& Lib "kernel32" Alias "GetLocaleInfoA" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String, ByVal cchData As Long)
Private Declare Sub GetSystemTime Lib "kernel32" (lpSystemTime As SYSTEMTIME)
Private Declare Sub GetSystemTimeAdjustment Lib "kernel32" (lpTimeAdjustment As Long, lpTimeIncrement As Long, lpTimeAdjustmentDisabled As Long)
Private Declare Sub GetLocalTime Lib "kernel32" (lpSystemTime As SYSTEMTIME)
Private Declare Function GetTimeZoneInformation& Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION)
Private Declare Function GetTimeFormat& Lib "kernel32" Alias "GetTimeFormatA" _
        (ByVal Locale As Long, ByVal dwFlags As Long, lpTime As SYSTEMTIME, _
        ByVal lpFormat As Long, ByVal lpTimeStr As String, ByVal cchTime As Long)


#End If 'WIN32

Private Sub Form_Load()
    Dim myTZ As TIME_ZONE_INFORMATION
    Dim myAdj&, myIncr&, myDisabled&
    Dim s$, dl&
    GetSystemTimeAdjustment myAdj&, myIncr&, myDisabled&
    If myDisabled& Then
        txtAdjust = "Disabled."
    Else
        txtAdjust = myAdj& & " ns Every " & myIncr& & " ns."
    End If
    dl& = GetTimeZoneInformation(myTZ)
    txtTZBias = CInt(myTZ.Bias / 30) / 2 & " hours"
    s$ = myTZ.StandardName
    txtTZName = StrConv(s$, vbFromUnicode)
    s$ = myTZ.DaylightName
    txtTZSName = StrConv(s$, vbFromUnicode)
End Sub


'
' Obtain the system and local time and display them
'
Private Sub Timer1_Timer()
    Dim myTime As SYSTEMTIME, s$, dl&
    GetLocalTime myTime
    s$ = String$(255, Chr$(0))
    dl& = GetTimeFormat&(LOCALE_SYSTEM_DEFAULT, 0, myTime, 0, s$, 254)
    txtLocTime = s$
    GetSystemTime myTime
    s$ = String$(255, Chr$(0))
    dl& = GetTimeFormat&(LOCALE_SYSTEM_DEFAULT, 0, myTime, 0, s$, 254)
    txtSysTime = s$
   
End Sub


Private Sub txtNum_Change()

End Sub


0
 
rmichelsCommented:
There are high performance timer functions that give you much better resolution that the system time.

The frequency value is how many time a single tic occurs in one second.  The counter value is how many tics occurred.  Using the frequency value you can determine how much time elapsed.

In the following example, calling StartTime seeds the value, then Calling End Time, you can see the ending value.  The difference between the two times would be the number of tics.

Not sure if this helps you or not, but this allow be to time some small values, but there is no "event" generated as in a timer.

Option Explicit


Type LARGE_INTEGER
    lowpart As Long
    highpart As Long
End Type

Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long
Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long

Public a As LARGE_INTEGER
Public b As LARGE_INTEGER
Private s_start As String
Private s_end As String
Private s_freq As String

Public Function sFrequency() As String

    Call QueryPerformanceFrequency(a)
    sFrequency = Hex$(a.highpart) & Hex(a.lowpart)

End Function

Public Function sCounter() As String

    Call QueryPerformanceCounter(a)
   
    sCounter = Hex$(a.highpart) & Hex(a.lowpart)
End Function

Public Sub StartTime()
    s_freq = sFrequency
    s_start = sCounter
End Sub

Public Function EndTime() As String
    s_end = sCounter
   
    EndTime = "Freq:" & s_freq & " Start:" & s_start & " End:" & s_end
   
End Function
0
 
mark2150Commented:
The "high precision timers" are a *farce*. If you actually try to use them you'll find that they don't work reliably. There is no *HARDWARE* driving them so any claim on their accuracy is smoke and mirrors.

This Q has come up several times. No-one has ever shown me a "precision timer" that has held up to scrutiny. You can use the timer on the sound card, but not 100% of systems will HAVE sound capability. So my underlying point is still 100% correct - a PC simply CANNOT measure time tighter than 18.2Hz without additional hardware.

The "precision timers" that run in software provide their time intervals by blocking interrupts and running a software loop. This will give you an accurate *delay*, but *NOT* a steady timebase as when they turn interrupts back on (as they must do) the OS may not let them retrigger for longer than their period! Thus you can get accurate 1ms time ticks - every 18.2Hz.

I *DEFY* anyone to strobe the Printer port (or com port or any other measurable output) at a 1ms rate without adding hardware. Let me feed the output into a freq counter or storage scope and we'll *see* the "accuracy" of the PC.

M

0
 
ivancAuthor Commented:
Guys

I can see this is a very testing questions and Mark2150 has made a challenge.  I have actually decided to live with the fact that the CPU can only keep time at a resolution of 55ms as it tested out to be pretty accurate upon increasing the interval of the Timer control to 50. However, I think that I would leave the question for a while to see if anybody is keen to the challenge of Mark2150.

The next questions is Johnny6 adn rmichels have provided 2 very complicated answers which in my limited time would not be able to test it to prove Mark2150 challenge.  However, I was wondering who should have the points.

SO you guys decide!

Tks once again
0
 
caraf_gCommented:
I vote for mark2150
0
 
mark2150Commented:
Thanx!

M
0
 
ivancAuthor Commented:
Mark
I forgotten to add that I think your analysis is sound too. But... I am also keen to see someone coming with a better idea.

Ivanc
0
 
mark2150Commented:
Getting accurate times is easy. Simply plug in a timer card from Keithly/Metrabyte and let it rip. There's no provision for realtime measurement in the baseline PC architecture and with the *huge* task switch overhead of Windows, you'll never see time critical systems developed on that platform.

I've done quite a bit of embedded firmware over the years and windows is simply too top-heavy and unpredictable for realtime applications. Can you imagine say, a shuttle launch, and 3 seconds into the flight they get a GPF! The process control crowd will never be able to use windows unless they can get it into ROM...

M
0
 
ivancAuthor Commented:
Johnny6 and Rmichels

I have spent some time trying you guys program and am not sure how it runs

Johnny6, I am unable to see the milliseconds and is there a way to find the difference in time

Rmichels
I can't seemed to get the time as I can't convert the string into time or decimal.  Is there a way to find the difference

Tks in advance

Ivanc
0
 
mark2150Commented:
You may not be able to find a difference because as far as the time of day clock is concerned both events may happen inside one 18.2Hz tick and therefore are reported at the *same* time. Like I said, PC's can't measure time tighter than 18.2Hz.

Just as an aside, do you know *why* it's 18.2Hz? Well it's related to the fact that the original PC ran at 4.77MHz and the reason that *THAT* speed was chosen is because at the time the least expensive clock crystal was the 3.58MHz color subcarrier used by color TV's of the day. They used a 4th overtone crystal that ran at 14.32Mhz and divided it by three in the clock generator for a net 4.77+MHz. Now the largest divisor on the time of day prescaler was 3FFFFh and when you divide 4.77Mhz by 262,143 (3FFFFh) you get 18.209Hz!

Ain't *that* a piece of PC trivia!

M
0
 
ivancAuthor Commented:
Mark

It is not I am not convince by your analysis, however, my lecturer insists that he can do it using VC and I am suppose to match it. Thus I am stuck with this and cracking my head against the wall.
You mentioned about using the sound card timer, is it possible to help me in this cos I am really stuck.

Tks in advance and really grateful for your PC Trivia cos I am shock by the truth of it

Ivanc

0
 
mark2150Commented:
Convinced or not my data is accurate. I have the "IBM PC Technical Reference Manual" at my elbow and have been writing realtime .ASM for PC's for *YEARS* and there is NO ACCURATE TIMEBASE in a "vanilla" PC.

Ask your lecturer what *hardware* he's using for timer tick and watch him choke and be unable answer. If he's using *any* OS level calls for timing then his time routine is a *farce* as the underlying OS does NOT have an accurate timebase.

M
0
 
ivancAuthor Commented:
mark

Really grateful for your knowledge.  I would like to know what book or IBM manual you have and can I locate it.  It would really help to make my lecturer choke if I can get hold of something like this.

Tks in advance

Ivanc
0
 
caraf_gCommented:
Mark, I've been following this discussion with interest.

Just out of curiosity. When I look at the bottom right hand side of my screen, there's a clock in the start bar.

I know this is not very accurate, but it's acceptable. At the moment it says 8.59. AFAIK it *is* 8.59, and I can't remember the last time I had to adjust the clock.

Am I right in assuming that this clock runs off the PC's hardware? So this is the most accurate you can get off your pc?

And what about functions such as VB's Now function, does that get the information from the same source?

Cheers

Pino
0
 
mark2150Commented:
All PC's have a RTC (Real Time Clock) chip in them as part of the BIOS configuration IC. The same battery that keeps the BIOS settings runs the clock. If you look closely on the MB near the keyboard connector you'll usually (but not always) see a small silver cylnder that is the clock oscillator crystal. (Sometimes they're integrated into the Clock/Bios IC) Anyway your PC clock has the same basic timing accuraccy (when off) as a cheap digital watch - about a minute a month +-. When the PC is running the clock timebase is usually derived from the processor clock and divided down. Since the CPU clock is at a much higher frequency any error in it is reduced by the division factor and the clock timebase should be much less.

Internally in the BIOS the clock is assumed to be 18.2Hz instead of 18.2088+ so it does tend to drift somewhat over a long run. Depending on the quality of the BIOS programmer in adjusting the count rate the .0088Hz may or may not be accounted for.

The BIOS, during startup, reads the current time from the clock IC and then from that point forward count's 18.2Hz interrupts to determine time of day (as reported by NOW and on the taskbar).

So the most accurate timer in the system is the number of 18.2Hz ticks since midnight. Anything "faster" than that can't be measured - period. (without additional hardware)

M
0
 
caraf_gCommented:
Excellent. Thanks for that further explanation.
0
 
johnny6Commented:
ivanc:
     I think I found an example of what your instructor *might* be using.  Here is the website:

http://www.mvps.org/vb/

If you click on the link "What's Hot" and click on the file named ccrpTmr6.zip you will see the following comments:

ccrpTmr.zip

I wrote this little ditty one afternoon after, for the 101st time, I became frustrated that I needed to add a form to my project just to support a timer. After passing it along to my friends at the Common Controls Replacement Project, they convinced me to release it as part of their (totally free) toolset.

The ccrpTimers library is an axDLL that currently exposes Timer, Countdown, and Stopwatch objects. You can sink fired events, using either the classic WithEvents method or via (non-blocking) implemented interfaces, into any form or class module. All objects use the multimedia timer, thus enabling true 1 millisecond resolution and intervals. Swing on over to the CCRP site for all the latest details.

John
0
 
mark2150Commented:
Johhny6,

And what magical source is used for the 1Ms timing?

You expose these *software* objects and they get their timebase from *what*?

Yes, they have values denominated in 1Ms increments. Doesn't mean that they can accurately *time* 1ms events.

Just what *hardware* device provides the timing reference for these objects? Hmmm?

M
0
 
johnny6Commented:
Mark:
     I appreciate the information you are sharing with us. I agree with you.  That is why I said that I thought that Ivanc's *instructor* might be using something along these lines.
     My question for you is could you give me the author, title, publisher, copyright date, and ISBN number of the book where you got your information from?  Thanks.

John
0
 
ivancAuthor Commented:
Mark

I believe I am requesting the same info as Johnny too.

Tks

Ivanc
0
 
mark2150Commented:
I have the original "IBM PC Technical Reference". It does *NOT* have an ISBN as it was published by IBM and I got it when I went thru their 3rd party maintainer class. It has complete schematics and .ASM listings of the BIOS as well as detailed engineering information on all aspects of the IBM PC. It is *the* definative reference on the design of the original IBM 5050 AKA the "PC".

M


0
 
johnny6Commented:
Mark2150:
       Do you have any idea where I can get my hands on a copy of it?

John
0
 
mark2150Commented:
Ummm, no. My copy is old enough to vote and if the house were on fire I'd jump out the window with it and my skivvies. If I was really pressed I'd leave the skivvies!

This book was *THE* reference for designing "PC Compatible" devices and the entire PC industry was based on it's publication by IBM. I'm sure it's way out of print and anyone that has a copy wouldn't part with theirs at gunpoint. By definition any hardware that doesn't follow *that* spec is NOT "PC compatible.

I could scan a couple of pages from it if you had a specific item in mind. The original design used an intel 8253 triple counter timer for timing. One channel was used for DMA refresh, one channel was used to time the "beep" (don't look at *me*, I didn't design it!) and the remaining channel was hooked up as the 18.2Hz TOD clock interrupt. There are no other timers available in the baseline architecture and without a ticker wired to an IRQ there is no way for a PC to *ACCURATELY* measure time.

M
0
 
johnny6Commented:
Mark2150:
       Is it possible for you to email me a copy of all of the specifications concerning anything to do with the timing and all areas that we discussed in this question? If this sounds like a lot of copying, then at least the information concerning the accuracy of the timer. I really appreciate this Mark. Thanks. My email is sobiranski@email.msn.com

John
0
 
caraf_gCommented:
;-) Better even, scan 'em in and publish them as a URL
0
 
ivancAuthor Commented:
mark

Could you email me too.

My email is woonlim@pacific.net.sg

Ivanc
0
 
mark2150Commented:
Ok, I've scanned and sent the pages. Basically here's what the book from IBM has to say on the topic in Section 1-4 System Unit:

"The three programmable timer/coutners are used by the system as follows: Channel 0 is used as a general-purpose timer providing a constant time base for implementing a time-of-day clock; Channel 1 is used to time and request refresh cycles from the DMA channel; and Channel 2 is used to support the tone generation for the audio speaker."

Schematically the timer is shown as an Intel 8253-5 on page D-9 Logic Diagrams. The PCLK signal (2.38Mhz) is fed to a /2 prescaler consisting of 1/2 of '175 U26 and the resulting 1.19Mhz signal is fed into the three clock inputs of the 8253, CLK0, CLK1, and CLK2 on pins 9, 15, and 18.

The 8253-5 is an I/O mapped device at addresses 0040-0043H

The outputs from the timer are OUT0, OUT1 and OUT2. OUT0 is on pin 10 and is labelled "TIMER INTERRUPT" and heads to IRQ0. OUT1 from pin 13 is divided by 2 by 1/2 of '74 flipflop U67 and is labelled "REFRESH REQ DMA" and heads out as DRQ0. OUT2 comes out on pin 17 and wanders around into the speaker and cassette interfaces (remember this is the old 5150 V1.0 PC!) Of the three outputs, only OUT0 feeds into the CPU as an interrupt and therefore is the only possible source for timing.

OUT0 feeds into the 8259 (U2) interrupt controller on pin 18, IRQ0. It is prioritized and fed out on the INT output pin, #17. This is wired directly to the CPU's INTR pin, pin #18.

The 8259A is an I/O mapped device at addresses 0020 and 0021.

While the capabilities and clock rates of the PC have grown over the years the baseline architecture hasn't fundamentally been modified at this level. The 8253 and 8259's have been integrated into the core logic of the MB and are no longer separate IC's, but their interconnections and assigned functions haven't (can't!) change. This is so that the systems exhibit "PC Compatibility" at the binary level. Any system that is billed as being "PC Compatible" MUST behave this way at the lowest levels.

The BIOS listing on pages A-82 and A-83 are the handlers for the time-of-day and 8253 interrupt service routines. The comment block at the front of the 8253 routine on page A-83 reads:

"This routine handles the timer interrupt from channel 0 of the 8253 timer. Input frequency is 1.19318 MHZ and the divisor is 65536, resulting in approx. 18.2 interrupts every second.

"The interrupt handler maintains a count of interrupts since power on time, which may be used to establish time of day.

"The interrupt handler also decrements the motor control count of the diskette, and when it expires, will turn off the diskette motor, and reset the motor running flags.

"The interrupt handler will also invoke a user routine through interrupt 1CH at every time tick. The user must code a routine and place the correct address in the vector table.

So this is the *ONLY* source of time tick to the standard PC. It runs at 18.2Hz and *NOTHING* is going to be able to measure tighter than this without additional hardware. I don't care what API call is used, or what control properties are exposed, or who wrote what function, there is simply NO UNDERLYING HARDWARE to provide an accurate timing reference in the baseline PC.

M
0
 
johnny6Commented:
Thanks for the schematics and the explanation Mark. I am sure they will come in handy one day.

John
0
 
ivancAuthor Commented:
Guys

I think Mark has provided all of us alot of information and thus I would award the points to him.

Tks for all the comments

Ivanc
0
 
ivancAuthor Commented:
Tks for all the great info and the scans

Ivanc
0
 
caraf_gCommented:
Mark, I've used your explanation in a newsgroup where a similar question was asked. I hope you don't mind.
0

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

  • 12
  • 11
  • 7
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now