Results 1 to 10 of 10

Thread: [RESOLVED] Help with timing procedures

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Jan 2012
    Location
    UK
    Posts
    20

    Resolved [RESOLVED] Help with timing procedures

    Hi everyone,

    I’m having trouble yet again, this time to do with timing. I have created a bunch of Public Sub procedures that draw different graphics, but I want them to be executed in a specific order and for different amounts of time. More precisely, after a certain key is pressed N times, I need the following sequence to be executed:
    Public Sub A () for 1000ms
    Public Sub B () for 1500ms
    Public Sub C () for 50ms
    Public Sub D () for 50ms
    Public Sub E () for 100ms
    Public Sub F () for 900ms
    Public Sub G () until a keyboard input

    And this sequence needs to cycle multiple times. Something along those lines. Is this even possible?
    Is it possible to use some sort of Select Case code that would dictate the interval of the timer? Or do I use a different timer for each sub? Actually, do I call the procedures within a timer's Sub? As you can tell I'm quite clueless. I generally find working with timers very frustrating and I’m not quite certain I even understand how they work.
    Not sure if coding the event sequence by using different sub procedures was a good idea now Maybe I need to find an alternative way…
    Any suggestion will be much appreciated. Thank you!

  2. #2

    Thread Starter
    Junior Member
    Join Date
    Jan 2012
    Location
    UK
    Posts
    20

    Re: Help with timing procedures

    Ok, so I did something which in my head should be working just fine, but in reality it behaves quite oddly...
    I set the timer's interval to 1 millisecond and then created a variable to count each time it fires. After that I used select case in order to make it execute specific subs at certain time... It does do it, but not withing the timing I expect. Here's the code for the timer:

    Private Counter as Double
    Counter = 0

    Private Sub Tmr1_Timer()
    Counter = Counter + 1
    Select Case Counter
    'Display Modal for 2 seconds
    Case 1 To 2000
    Call Modal
    'Change colour for 100ms
    Case 2001 To 2101
    Call ColourChange(vbRed, vbBlue, vbYellow, vbCyan, vbMagenta, vbGreen)
    'Display Cue for 50ms
    Case 2102 To 2152
    Call Cue(x3, y3)
    'Hide Cue for 50ms
    Case 2153 To 2203
    Call CueOff(x3, y3)
    'Display Probe after
    Case Else
    Call Probe(vbBlue, vbCyan, vbGreen, vbRed, vbMagenta, vbYellow, x4, y4)
    Tmr1.Enabled = False
    Counter = 0
    End Select
    End Sub

    I though setting a case from 1 to 2000 would suggest the procedure would be executed for 2 seconds, instead it lasts about 30 seconds! After that everything proceeds in order, but for way longer than it should. For example the procedure supposed to last 50ms lasts for about a second and a half
    Any idea what I'm doing wrong?
    Thank you!

  3. #3
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,929

    Re: Help with timing procedures

    You are assuming two things that are not necessarily true.

    The first assumption is that a Timer with an interval of 1 will fire 1000 times a second, and it usually wont. Timers are a very low priority thing, so the interval only counts as the minimum... while you will usually be relatively close to it, sometimes it can be dramatically longer (even a few seconds longer, depending on what the computer is doing at the time).

    The other assumption is that the Timer will fire at the frequency related to the interval, but it usually wont: because it will run the code inside the event, then start the next interval (so if your code takes 50ms, the second time it runs will be 50+1ms after the first).


    If you need to know the time since the start, then you should be calculating/storing that independently of the timer ticks. An easy way to do that (which has problems if you run the code during midnight) is to read the value of the Timer function, which specifies the number of milliseconds since midnight, eg:
    Code:
    Private TimerStart as Single
    ...
    Tmr1.Enabled = True
    TimerStart = Timer
    ...
    Private Sub Tmr1_Timer()
    Select Case (Timer - TimerStart)

  4. #4

    Thread Starter
    Junior Member
    Join Date
    Jan 2012
    Location
    UK
    Posts
    20

    Re: Help with timing procedures

    Wow, that would have never occured to me... Thank you!
    I did try it, but couldn't get it to work properly either. Anyway, I've found a way around it! Very clumsy coding (making the timer read a string where each letter corresponds to executing a specific sub for a specified interval), but it works and that's all I care about .
    Thanks again for the info, I've certainly learnt something new!

  5. #5

    Thread Starter
    Junior Member
    Join Date
    Jan 2012
    Location
    UK
    Posts
    20

    Re: [RESOLVED] Help with timing procedures

    Erm, hello again .

    I have another problem, but didn't want to start a new thread as it's still related to timing.
    I coded a couple of loops within a timer, but although everything seems to be working fine in terms of order of progression (in step mode), the intervals of the timer seem to be ignored... so what I get at run time is the very end result. What I expect though is for it to cycle through the code with the specified timing, in reality none of that is visible. Step mode suggests that it is indeed registering and changing the interval of the timer as I want it to, but it doesn't seem to be actually executing it. And it all worked fine before I introduced the loops. Here are bits of the code:

    This one is supposed to change the values of the variables for each cycle:

    Private Sub Tmr1_Timer()
    Do While Block1 < 4
    Select Case Block1
    Case 1
    strTrial = "0156789 !"
    'Set variable values
    Call Timer
    Case 2
    strTrial = "0256789 !"
    'Change variable values
    Call Timer
    Case 3
    'Change variable values
    Call Timer
    End Select
    Block1 = Block1 + 1
    Loop
    End Sub

    This is the Timer procedure which is called. It executes certain commands for specified periods of time, using the variable values determined from the previous loop:

    Public Sub Timer()
    Static bytCounter As Byte
    If bytCounter = 0 Then
    bytCounter = 1
    End If
    Do
    strStage = Mid(strTrial, bytCounter, 1)
    Select Case strStage
    Case "0"
    Do stuff...
    .........
    Tmr1.Interval = 1000
    Case "1"
    ..........
    Tmr1.Interval = 1500
    Case "2"
    ..........
    Tmr1.Interval = 1500
    Case "3"
    .........
    Tmr1.Interval = 1500
    Case "4"
    ......
    Tmr1.Interval = 1500
    Case "5"
    ........
    Tmr1.Interval = 50
    Case "6"
    ........
    Tmr1.Interval = 50
    Case "7"
    .......
    Tmr1.Interval = 100
    Case "8"
    ........
    Tmr1.Interval = 900
    Case "9"
    .......
    Tmr1.Interval = 1
    Case " "
    .......
    Tmr1.Interval = 2000
    Case "!"
    ....
    Tmr1.Interval = 1
    End Select
    If bytCounter >= Len(strTrial) Then
    bytCounter = 0
    Tmr1.Enabled = False

    End If
    bytCounter = bytCounter + 1
    Loop Until bytCounter >= Len(strTrial)

    End Sub

    Any ideas why the timer is not working (properly)??

  6. #6
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,929

    Re: [RESOLVED] Help with timing procedures

    When you post code please put it inside code tags so it is displayed in a more readable way - either using the Code/VBCode buttons in the post editor screen (or at the top of the Quick Reply box), or by putting them in manually, like this: [code] code here [/code]


    Given the code you have shown, there seems to be no way you could tell what it is doing, as there is no kind of output whatsoever.

  7. #7

    Thread Starter
    Junior Member
    Join Date
    Jan 2012
    Location
    UK
    Posts
    20

    Re: [RESOLVED] Help with timing procedures

    Sorry about that, I did want to wrap it in code tags, but I wasn't sure how to do it.
    As for the code itself, I didn't post all of it on purpose, I just though it's irrelevant and makes it quite cluttered. Where you see "........." it's all code that produces output, but I'm not sure if it'll make any sense to people because it's mostly prodecures I've created. Here is the whole thing anyway:
    The timer (and I was hoping the loop as well) is activates after a key press:
    Code:
    Private Sub Form_KeyPress(KeyAscii As Integer)
    If KeyAscii = vbKeyEscape Then
    Dim bytEscape As Byte
    bytEscape = MsgBox("Exit?", 1, "Esc Command")
    If bytEscape = 1 Then
    Unload Me
    End If
    ElseIf KeyAscii = 44 Then
    Tmr1.Enabled = True
    Tmr1.Interval = 1
    End If
    End Sub
    There is a loop coded within the Timer event to make it cycle and change the values of the specific variables (A, B, C...) for each cycle:
    Code:
    Private Sub Tmr1_Timer()
    Do While Block1 < 4
    Select Case Block1
        Case 1
        strTrial = "0156789 !"
        A = vbRed
        B = vbGreen
        C = vbYellow
        D = vbWhite
        E = Purple
        F = vbCyan
        G = vbBlue
        P = x5
        O = y5
        Q = x
        R = y
    Call Timer
    Case 2
        strTrial = "0256789 !"
        A = Purple
        B = vbRed
        C = vbYellow
        D = vbBlue
        E = vbCyan
        F = vbWhite
        G = vbGreen
        P = x
        O = y
        Q = x2
        R = y2
    Call Timer
    Case 3
        strTrial = "0356789 !"
        A = vbRed
        B = Purple
        C = vbYellow
        D = vbBlue
        E = vbCyan
        F = vbWhite
        G = Purple
        P = x
        O = y
        Q = x2
        R = y2
    Call Timer
    End Select
        Block1 = Block1 + 1
        Loop
    
        
    End Sub
    This is the code for the Timer procedure, which is called after setting the variable values. It contains another loop to make it read through each letter of the string and do the associated events before moving to the next set of variables (from the first loop):
    Code:
    Public Sub Timer()
    Static bytCounter As Byte
    If bytCounter = 0 Then
    bytCounter = 1
    End If
    Do
    strStage = Mid(strTrial, bytCounter, 1)
        Select Case strStage
        Case "0"
        Gap.Visible = True
        Tmr1.Interval = 1000
        Case "1"
        Gap.Visible = False
        Segmented.Visible = False
        Amodal.Visible = False
        Modal.Visible = False
        Whole.Visible = True
        Tmr1.Interval = 1500
        Case "2"
        Gap.Visible = False
        Whole.Visible = False
        Modal.Visible = False
        Amodal.Visible = False
        Segmented.Visible = True
        Tmr1.Interval = 1500
        Case "3"
        Gap.Visible = False
        Whole.Visible = False
        Amodal.Visible = False
        Segmented.Visible = False
        Modal.Visible = True
        Tmr1.Interval = 1500
        Case "4"
        Gap.Visible = False
        Whole.Visible = False
        Modal.Visible = False
        Segmented.Visible = False
        Amodal.Visible = True
        Tmr1.Interval = 1500
        Case "5"
        Call Cue
        Tmr1.Interval = 50
        Case "6"
        Call CueOff
        Tmr1.Interval = 50
        Case "7"
        Call ColourChange
        Tmr1.Interval = 100
        Case "8"
        Fixation.Visible = True
        Tmr1.Interval = 900
        Case "9"
        Static Press As Integer
        Fixation.Visible = False
        Tmr1.Interval = 1
        Case " "
        Call ColourChange
        Call Probe
        Tmr1.Interval = 2000
        
        Case "!"
        Gap.Visible = True
        Tmr1.Interval = 1
        End Select
    If bytCounter >= Len(strTrial) Then
    bytCounter = 0
    Tmr1.Enabled = False
    
    End If
    bytCounter = bytCounter + 1
    Loop Until bytCounter >= Len(strTrial)
    
    End Sub
    That's it. It loops through everything as it's supposed to, but as you said, there is no output. When I run it in step mode it seems like the problem is in the timer intervals, it goes through them but doesn't seem to execute them. If there is no loop it works fine, which made me think it's something to do with the loop itself
    In worst case scenario I'll do it without a loop and variables will change based on keyboard input, but ideally I wanted it to loop by itself without waiting for the user to respond.

  8. #8
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,929

    Re: [RESOLVED] Help with timing procedures

    I presume Gap/SegmentedAmodal/etc are controls, and therefore changing the visibility is a kind of output you can check.

    Assuming they are controls, the problem is that there isn't a chance to update screen (which happens automatically when your code is no longer running). To force it to update quicker, tell the form (or each control individually) to refresh, eg: Gap.Refresh


    Note that using a Timer and a loop is a rather strange thing to do (it is usually one or the other, as they serve the same kind of purpose), and a quick check makes me think what you've got will cause odd behaviour.

  9. #9

    Thread Starter
    Junior Member
    Join Date
    Jan 2012
    Location
    UK
    Posts
    20

    Re: [RESOLVED] Help with timing procedures

    I see... Yes, if I remove the timer and just use the loop plus refreshing the controls I do get a rather 'subliminal' glimpse of the output. I have heard that a loop can function as a timer (or something like that), but I've never really uderstood how you can slow it down and make it do different parts of the code for different amounts of time. That's why I went for the timer/ loop combination (as you can tell I don't really know what I'm doing, it's only the second time I've ever had to program something), but apparently it doesn't work.
    Thanks for the info, at least now I can stop faffing about with it and move on to an input-driven progression (plan B).



    Edition: Eureka! I've just discovered the Sleep function! Life makes sense again
    Thanks again!
    Last edited by Pine_Apple; Jan 31st, 2013 at 07:22 AM.

  10. #10
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,929

    Re: [RESOLVED] Help with timing procedures

    A timer is meant for doing things at regular intervals, and a loop is meant to do things repeatedly.

    For this kind of situation I would probably use a timer along with the code I showed in post #2 (and no loop). A loop with Sleep (and no timer) can be used for the same effect, but it generally takes more code to deal with the timing.

    The important thing however is that you get the desired result, and understand the code.

Posting Permissions

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



Click Here to Expand Forum to Full Width