Timing Problem in C

Hi everyone!

Having some problems with a DOS program which should send a string out to the COM-Port [b]exactly[/b] every 250 milliseconds. I tried it this way:

[code]
clock_t start_time, end_time;
unsigned int waitfor=250;
start_time = clock();
for (;;)
{
compute(); // This takes between 5 and 170 milliseconds
end_time = clock();
while((end_time - start_time) < waitfor)
{
end_time = clock();
}
comsend(); // This sends out the string
}
[/code]

But for some reason it doesn't work out. It seems like DOS increases the clock every 55 milliseconds with a value of 55, and NOT every millisecond with a value of 1. If I set the variable 'waitfor' to a value between 221 and 275 I always get the string send out every 275 milliseconds. If I set the value between 166 and 220 the string is send out every 220 milliseconds.. and so on. Can anybody help?

Zeek

Comments

  • [b][red]This message was edited by stober at 2004-2-12 8:25:4[/red][/b][hr]
    [blue]no operating system can achieve your goal of [b]exactly[/b] 250 milliseconds -- they just ain't that accurate. MS-DOS 6.X or earlier can come reasonably close, but is still at the mercy of the clock's cycle times. And even if it could do that, sending a string out the serial port is a very very slow process. Depending on the length of the string and the port's baud rate, the transmit time could exceed the wait time in your program. [/blue]

    : Hi everyone!
    :
    : Having some problems with a DOS program which should send a string out to the COM-Port [b]exactly[/b] every 250 milliseconds. I tried it this way:
    :
    : [code]
    : clock_t start_time, end_time;
    : unsigned int waitfor=250;
    : start_time = clock();
    : for (;;)
    : {
    : compute(); // This takes between 5 and 170 milliseconds
    : end_time = clock();
    : while((end_time - start_time) < waitfor)
    : {
    : end_time = clock();
    : }
    : comsend(); // This sends out the string
    : }
    : [/code]
    :
    : But for some reason it doesn't work out. It seems like DOS increases the clock every 55 milliseconds with a value of 55, and NOT every millisecond with a value of 1. If I set the variable 'waitfor' to a value between 221 and 275 I always get the string send out every 275 milliseconds. If I set the value between 166 and 220 the string is send out every 220 milliseconds.. and so on. Can anybody help?
    :
    : Zeek
    :



  • Hi Stober!

    I want to get it as close as possible. An accurancy of 55 milliseconds can't be the maximum you can achive... can it? Sending out the string to the COM Port takes pretty exactly 30 milliseconds.

    Does anyone know another solution?

    Zeek


    : [b][red]This message was edited by stober at 2004-2-12 8:25:4[/red][/b][hr]
    : [blue]no operating system can achieve your goal of [b]exactly[/b] 250 milliseconds -- they just ain't that accurate. MS-DOS 6.X or earlier can come reasonably close, but is still at the mercy of the clock's cycle times. And even if it could do that, sending a string out the serial port is a very very slow process. Depending on the length of the string and the port's baud rate, the transmit time could exceed the wait time in your program. [/blue]
    :
    : : Hi everyone!
    : :
    : : Having some problems with a DOS program which should send a string out to the COM-Port [b]exactly[/b] every 250 milliseconds. I tried it this way:
    : :
    : : [code]
    : : clock_t start_time, end_time;
    : : unsigned int waitfor=250;
    : : start_time = clock();
    : : for (;;)
    : : {
    : : compute(); // This takes between 5 and 170 milliseconds
    : : end_time = clock();
    : : while((end_time - start_time) < waitfor)
    : : {
    : : end_time = clock();
    : : }
    : : comsend(); // This sends out the string
    : : }
    : : [/code]
    : :
    : : But for some reason it doesn't work out. It seems like DOS increases the clock every 55 milliseconds with a value of 55, and NOT every millisecond with a value of 1. If I set the variable 'waitfor' to a value between 221 and 275 I always get the string send out every 275 milliseconds. If I set the value between 166 and 220 the string is send out every 220 milliseconds.. and so on. Can anybody help?
    : :
    : : Zeek
    : :
    :
    :
    :
    :

  • [b][red]This message was edited by tom_sw at 2004-2-12 13:38:55[/red][/b][hr]
    Actually there is a limit to how fine that value can go. It is the same underlying mechanism as used in the OnTimer functions in MFC. Its been awhile, but I beleive the limit on DOS/W31/W95/W98 was in fact 55ms. Win NT could go down to 20ms I believe (and I would assume that applies to 2K and XP also). There are similar limitations on a Unix system. Our team had considered playing games with the process priority to get better resolution, but the 20ms limit was satisfactory for what we needed at that time, so we just went with the NT system.

    I know the actual limits used to be documented in the MSDN library, but it was a rather obscure entry.

    EDIT: Try here for a start:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/windows_time.asp


    : Hi Stober!
    :
    : I want to get it as close as possible. An accurancy of 55 milliseconds can't be the maximum you can achive... can it? Sending out the string to the COM Port takes pretty exactly 30 milliseconds.
    :
    : Does anyone know another solution?
    :
    : Zeek
    :
    :



  • : Hi everyone!
    :
    : Having some problems with a DOS program which should send a string out to the COM-Port [b]exactly[/b] every 250 milliseconds. I tried it this way:
    :
    : [code]
    : clock_t start_time, end_time;
    : unsigned int waitfor=250;
    : start_time = clock();
    : for (;;)
    : {
    : compute(); // This takes between 5 and 170 milliseconds
    : end_time = clock();
    : while((end_time - start_time) < waitfor)
    : {
    : end_time = clock();
    : }
    : comsend(); // This sends out the string
    : }
    : [/code]
    :
    : But for some reason it doesn't work out. It seems like DOS increases the clock every 55 milliseconds with a value of 55, and NOT every millisecond with a value of 1. If I set the variable 'waitfor' to a value between 221 and 275 I always get the string send out every 275 milliseconds. If I set the value between 166 and 220 the string is send out every 220 milliseconds.. and so on. Can anybody help?
    :
    : Zeek
    :

    Hmm have you tried using the PIT to sync? I don't know for sure but I would think that might do it. I believe DOS uses it, but it can be modified to suit your needs.

  • [b][red]This message was edited by Lundin at 2004-2-13 0:7:21[/red][/b][hr]
    I would say that Windows' accuracy is around +- 5ms depending on how many programs that are running. This seem to be a bug.

    A common problem is to forget what happens when you get a variable overflow. This is a way to check that:

    time = end_time - start_time;
    if(end_time < start_time)
    time *= -1;

    Another way to solve the problem would be to use sleep/delay functions. Those will force a context switch if there are other processes running, so that you won't get the switch in an undesired place.


    : [b][red]This message was edited by stober at 2004-2-12 8:25:4[/red][/b][hr]
    : [blue]no operating system can achieve your goal of [b]exactly[/b] 250 milliseconds -- they just ain't that accurate. MS-DOS 6.X or earlier can come reasonably close, but is still at the mercy of the clock's cycle times. And even if it could do that, sending a string out the serial port is a very very slow process. Depending on the length of the string and the port's baud rate, the transmit time could exceed the wait time in your program. [/blue]
    :
    : : Hi everyone!
    : :
    : : Having some problems with a DOS program which should send a string out to the COM-Port [b]exactly[/b] every 250 milliseconds. I tried it this way:
    : :
    : : [code]
    : : clock_t start_time, end_time;
    : : unsigned int waitfor=250;
    : : start_time = clock();
    : : for (;;)
    : : {
    : : compute(); // This takes between 5 and 170 milliseconds
    : : end_time = clock();
    : : while((end_time - start_time) < waitfor)
    : : {
    : : end_time = clock();
    : : }
    : : comsend(); // This sends out the string
    : : }
    : : [/code]
    : :
    : : But for some reason it doesn't work out. It seems like DOS increases the clock every 55 milliseconds with a value of 55, and NOT every millisecond with a value of 1. If I set the variable 'waitfor' to a value between 221 and 275 I always get the string send out every 275 milliseconds. If I set the value between 166 and 220 the string is send out every 220 milliseconds.. and so on. Can anybody help?
    : :
    : : Zeek
    : :
    :
    :
    :
    :



  • [b][red]This message was edited by zeek2003 at 2004-2-13 4:45:33[/red][/b][hr]
    It really seems like the internal DOS-Timer has a resolution of exactly 55ms. If I needed the string to be sent out every 220ms, everything would be fine, as 220ms is a multiple of 55ms. I checked that with an oscilloscope which shows that this works very accurately.

    Now I've had the idea to wait for these 220ms and add a delay of another 30ms after the loop, as delay is specified in documentation as follows:

    Synopsis:
    #include
    void delay( unsigned milliseconds );

    Description:
    The delay function suspends execution by the specified number of milliseconds.

    Unfortunately this doesn't work either, 'cause the delay is always *55. So a delay of 30, delays the system for about 30*55=1650 milliseconds. :(

    Any other ideas?

    Zeek


    : Hi everyone!
    :
    : Having some problems with a DOS program which should send a string out to the COM-Port [b]exactly[/b] every 250 milliseconds. I tried it this way:
    :
    : [code]
    : clock_t start_time, end_time;
    : unsigned int waitfor=250;
    : start_time = clock();
    : for (;;)
    : {
    : compute(); // This takes between 5 and 170 milliseconds
    : end_time = clock();
    : while((end_time - start_time) < waitfor)
    : {
    : end_time = clock();
    : }
    : comsend(); // This sends out the string
    : }
    : [/code]
    :
    : But for some reason it doesn't work out. It seems like DOS increases the clock every 55 milliseconds with a value of 55, and NOT every millisecond with a value of 1. If I set the variable 'waitfor' to a value between 221 and 275 I always get the string send out every 275 milliseconds. If I set the value between 166 and 220 the string is send out every 220 milliseconds.. and so on. Can anybody help?
    :
    : Zeek
    :



  • : [b][red]This message was edited by zeek2003 at 2004-2-13 4:45:33[/red][/b][hr]
    : It really seems like the internal DOS-Timer has a resolution of exactly 55ms. If I needed the string to be sent out every 220ms, everything would be fine, as 220ms is a multiple of 55ms. I checked that with an oscilloscope which shows that this works very accurately.
    :
    : Now I've had the idea to wait for these 220ms and add a delay of another 30ms after the loop, as delay is specified in documentation as follows:
    :
    : Synopsis:
    : #include
    : void delay( unsigned milliseconds );
    :
    : Description:
    : The delay function suspends execution by the specified number of milliseconds.
    :
    : Unfortunately this doesn't work either, 'cause the delay is always *55. So a delay of 30, delays the system for about 30*55=1650 milliseconds. :(
    :
    : Any other ideas?
    :
    : Zeek
    :
    :
    In Michael Abrash's book [italic]Graphics Programming Black Book[/italic] he talks about being able to time code with a resolution of around 10us. He's using Assembly programming and stopping the timer to take readings. He's doing this to time how long sections of code take to run. His entire book is available on the web in .pdf version. Capter three is the one which references the timer chip. If his information is still valid for the more current versions of the timer system, perhaps you can find a way to make use of his routines. Chapter three can be downloaded at http://planetmirror.com/pub/gpbb/gpbb3.pdf and is about 2.6MB.

    I know this isn't C, but maybe you can find some code that you can insert into your C program.

    Take Care,
    Ed Hall

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories