Results 1 to 6 of 6

Thread: [RESOLVED] Looking for advice on updating VB6 high-speed DAQ/Charting loop

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2014
    Location
    VB6 dinosaur land
    Posts
    1,190

    Resolved [RESOLVED] Looking for advice on updating VB6 high-speed DAQ/Charting loop

    The current project I'm migrating from VB6 has code like this (I've simplified it and added some comments):

    vb Code:
    1. StartTimer = Timer
    2. Penetration = 0 'variable for how far into the test it is
    3. Do
    4.     Penetration = (elapsed(StartTimer) / TestLength)
    5.     If Penetration > 1.1 Then Penetration = 1.1
    6.     Meter.Width = Label1.Width * Penetration 'acts as a progress bar
    7.     Meter.Refresh
    8.     DoEvents 'so Meter will really refresh
    9.     OutputVoltage = FullScale * Penetration
    10.     Call VoltsOut(OutputVoltage)
    11.    
    12.     Call ReadVoltage(Analog1, Analog2, Analog3, Analog4)
    13.    
    14.     i = i + 1
    15.    
    16.     TimeHistory(0, i) = elapsed(StartTimer)
    17.     TimeHistory(1, i) = Analog1
    18.     TimeHistory(2, i) = Analog2
    19.     TimeHistory(3, i) = Analog3
    20.     TimeHistory(4, i) = Analog4
    21.    
    22. Loop Until (Penetration >= 1) Or (Analog1 > TestSpec)
    The processor is also being upgraded to a Core 2 Duo E7400 (from mid 90s CPU!).

    So if it wasn't obvious, it's ramping voltage from 0 to FullScale over TestLength and storing input values into an array. It generally collects 30,000-50,000 records depending on TestLength so approximately 2,000 per second. Since a timer can't accurately handle that frequency, I'm assuming I'm stuck keeping it in a Do...Loop (or similar construct) or possibly using API functions as in game loops. If this is a fair assessment, which would be preferred?

    The UI isn't too critical while this is running as the operator is just waiting for the test to complete. However, I would like to improve the flickering and would prefer to display a live chart of the curves generated instead of using a control like a progress bar (Meter above). Hence, I believe I will need to move this loop into it's own thread (something I need to learn to do). I've read a few of the CodeBank submissions on threading but don't have a handle on whether I should start one BGW to do the whole DAQ and charting or TWO BGWs (one for DAQ and one to Chart). If the latter, I'd appreciate some pointers on how that code structure may look vs just spawning a single BGW. FWIW, I am not intending to plot ALL the points, of course - I was thinking maybe every 100th point.

    Any other tips that may help?

    Thanks!

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,102

    Re: Looking for advice on updating VB6 high-speed DAQ/Charting loop

    Yeah, you aren't going to get a timer firing that fast. A game loop could get you there. I would also suggest that the loop be run entirely on a background process, perhaps a BackGroundWorker component (which has the convenient feature of allowing you to raise ReportProgress events, which are raised on the UI thread, so that you can use them to update the UI). As you might guess, I wrote that after reading your first paragraph and before reading your second. You're already looking in that direction.

    You probably want to look at the Stopwatch object, which is a pretty high precision timer with a variety of ElapsedX methods to get timing in various means.

    So, you'd move that label.width into a local variable (so that the background process isn't touching the UI), scrap the DoEvents and the Refresh in favor of raising the ReportProgress event, and go from there. One possible issue with this is that it might end up running too fast. It depends on what the VoltsOut and ReadVoltage methods do, and how much time they take. Without those two, the loop would run thousands of times in a millisecond, which would be too fast for the UI to update, anyways. If VoltsOut or ReadVoltage are sufficient to slow it down, then all might be well. Otherwise, you may have to add a counter and only raise the ReportProgress event every N iterations of the loop.

    This may still result in flickering. If the control that is flickering has a DoubleBuffered property exposed, then set that to true. When a control refreshes, the first thing it does is paint the area white, then paint it again with the proper color. If things happen just right, you will get to see that white on the screen, though for only about 1/60th of a second, which results in a flash. DoubleBuffered will remove that, but not all controls expose it. All controls do HAVE the property, they just don't all expose it for no reason that I can understand. If the control you want to use doesn't expose it, getting around that is simple, but there's no point in discussing it until you need it.
    My usual boring signature: Nothing

  3. #3

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2014
    Location
    VB6 dinosaur land
    Posts
    1,190

    Re: Looking for advice on updating VB6 high-speed DAQ/Charting loop

    Quote Originally Posted by Shaggy Hiker View Post
    So, you'd move that label.width into a local variable (so that the background process isn't touching the UI), scrap the DoEvents and the Refresh in favor of raising the ReportProgress event, and go from there. One possible issue with this is that it might end up running too fast. It depends on what the VoltsOut and ReadVoltage methods do, and how much time they take. Without those two, the loop would run thousands of times in a millisecond, which would be too fast for the UI to update, anyways. If VoltsOut or ReadVoltage are sufficient to slow it down, then all might be well. Otherwise, you may have to add a counter and only raise the ReportProgress event every N iterations of the loop.
    That was my thought exactly anyway (every 100th point in my OP) just so I'm not trying to plot all 30,000+ points. And I expect it may be significantly more with the newer hardware as well.

    Those calls are writing and reading a DAQ card.

    I did a quick test before bed:

    vb.net Code:
    1. Do
    2.             Call DoWork(Analog1) 'do the function calls to simulated DIO card
    3.  
    4.             i = i + 0.2 'changed to single to get more points (~ 675) to fit on my axis range of 65-200
    5.  
    6.             Chart1.Series("Series0").Points.AddXY(i, Analog1)
    7.  
    8.             Application.DoEvents()
    9.         Loop Until (i > 200)

    This worked surprisingly well (25-30% CPU and no flickering), but of course it's not real DIO hardware and my PC is better than a C2D E7400. Using a BGW may well be TOO fast. LOL. I'll head that direction and test that. I certainly won't need more than one.

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,102

    Re: Looking for advice on updating VB6 high-speed DAQ/Charting loop

    You shouldn't need taht Application.DoEvents, even with that loop. You should be able to just write Chart1.Refresh and get the update. Refresh is supposed to cause the control to immediately repaint. If you used .Invalidate, then the paint event would just be queued up and you wouldn't see the paint until the loop ended, but .Refresh is imperative. Having said that, in my experience, if the loop is fast enough, the refresh eventually quits and the painting stops happening. Application.DoEvents will work in those cases, it just comes at a serious cost in performance. So, updating the control every N iterations is the way to go.
    My usual boring signature: Nothing

  5. #5

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2014
    Location
    VB6 dinosaur land
    Posts
    1,190

    Re: Looking for advice on updating VB6 high-speed DAQ/Charting loop

    Quote Originally Posted by Shaggy Hiker View Post
    Having said that, in my experience, if the loop is fast enough, the refresh eventually quits and the painting stops happening. Application.DoEvents will work in those cases, it just comes at a serious cost in performance. So, updating the control every N iterations is the way to go.
    OK. I recall having to add that DoEvents to the VB6 version 6 years ago so the "progress bar" would refresh. They must have done something to speed things up. In fact, that was the first time I had to touch this code.

  6. #6
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,102

    Re: [RESOLVED] Looking for advice on updating VB6 high-speed DAQ/Charting loop

    It's not so much about speeding things up, but I don't remember anything like the .Refresh method in VB6 (though it's been well over a decade, so I could be wrong). What DoEvents does is pause execution so that the UI thread can pump messages. When you alter a control, the control invalidates, which means that a Paint message is added to the queue. The UI can only process those messages when it gets a chance, so if the code is running a loop, no messages get processed until the loop finishes. DoEvents let the loop pause so that the messages get painted. The same thing happens in .NET (and all of windows, actually), but the .Refresh method doesn't just add a message to the message queue, it tells the UI to redraw that control right then.
    My usual boring signature: Nothing

Tags for this Thread

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