Saturday, April 14, 2012 12:47 PM
For my thesis (last year high school now), I build a laser projector. I am building a program in VB2010 what sends constant data (coordinates) to the laser projector. It’s important that the moments of data sending ore correctly. The program simulates the pictures who the laser projector must send in a picture box. The pictures can also make some effects like zoom-in, zoom-out, scroll and x, y and z rotations.
The problem is now that the program works very slow if the program must make all the calculations of the effects, must draw many lines between the coordinates in the picturebox for the simulation and send data to the laser projector. All these things are based on different timers. How more I ask from the PC (complicated pictures with many coordinates, many effects at the same time) how slower he works.
Now, the graphics in the picturebox are half-drawn and the PC sends the coordinates to slow to the laser projector. Mainly the time between the data transfer of different pictures is to slow. Now, I send always buffers who describes al whole picture to the laser projector. I use a serial port (virtual COM port) at a speed of 256000bps for data transfer.
How can I make the speed of the timers higher whit a greater tolerance? It must be the first priority from the PC that the coordinates to send, are at the right time.
I know just a little bit of computers. I know only how to program in VB after years of self-learning.
Program: (Forum1 calculate the graphics, form2 send the data)
Calculations for effects (called from a timer)
Thank you for helping,
Monday, April 16, 2012 7:26 AMModerator
We will try to involve some senior engineers in this case.
MSDN Community Support | Feedback to us
Monday, April 16, 2012 2:18 PM
I can't really help - but I'm curious, and I will try to give some hints:
- A VB application is running in user mode. High system load can always cause delays. Possiby, for highest reliability, you need to write a driver. But for now...:
- A Winforms timer (Timer1) has the lowest precision. Alternative: System.Timers.Timer. If that's not enough, start a new Thread and synchronize execution to Stopwatch.GetTimeStamp. You can increase the thread priority for this purpose to Highest.
- The code is not compilable as many declarations are missing.
- I've accustomed myself to using English identifiers only, in case I'll have to discuss something in an international context. As an ambitious student, your future work will probably also be found there.
- For painting, use the Graphics object you receive in the paint event or in OnPaint (parameter e.Graphics). A different approach is drawing on a Bitmap instead and display that one.
- Dispose disposable objects, like Pens. See the Using statement.
- Use picturebox1.clientsize.width instead of picturebox1.width (same for height). A picturebox might have a border.
- Switch Option Strict On (if you didn't already)
- If possible, avoid very long lines. Split them. For example, the first line can be:
Dim index As Integer = color_co(tekening_nummer, 1) - 1 Dim color = System.Drawing.Color.FromArgb(Rood_data(index), groen_data(index), blauw_data(index)) Using penseel As New System.Drawing.Pen(Color) End Using
- Put equal calculations into a parameterized function.
- Replace And by AndAlso where applicable.
- Precalculate unchanging values outside the loop. For example, Math.Cos(Z_hoek * 0.0246) can be calculated once before the loop.
- Use constants wherever possible.
- Edited by Armin Zingler Monday, April 16, 2012 2:21 PM item added
Monday, April 16, 2012 2:42 PM
As the X and Y values are function values of your scientific calculation, I suggest calculating them only once per "teller" (whatever it is). Currently you calculate them twice, one time as the start of the line, and one time as the end of the line. If you put them into an array of points, you can call Graphics.DrawLines.
I don't know what exactly your code is doing, but after redesign, this is an optimized version. Of course, keep your own code also :-) because I'm not sure if it's free of faults.
Private Sub teken_afbeelding( _ ByVal g As Graphics, ByVal Rect As Rectangle, _ ByVal tekening_nummer As Integer, ByVal schaal As Integer, _ ByVal H_verplaatsing As Integer, ByVal V_verplaatsing As Integer, _ ByVal X_hoek As Integer, ByVal Y_hoek As Integer, ByVal Z_hoek As Integer, _ ByVal blanking As Integer) Dim X_buff, Y_buff As Integer Dim index As Integer = color_co(tekening_nummer, 1) - 1 Dim color = System.Drawing.Color.FromArgb(Rood_data(index), groen_data(index), blauw_data(index)) Using penseel As New System.Drawing.Pen(color) Const Scale As Double = 0.0246 Dim buffer_teller As Integer aantal_co_doorgeefluik = 0 g.Clear(color.Black) Dim Cos_Y_hoek_Scaled = Math.Cos(Y_hoek * Scale) Dim Cos_X_hoek_Scaled = Math.Cos(X_hoek * Scale) Dim Cos_Z_hoek_Scaled = Math.Cos(Z_hoek * Scale) Dim Sin_Z_hoek_Scaled = Math.Sin(Z_hoek * Scale) Dim schaal_Scaled = schaal / 100 Dim Inv_Pic_Width = 4096 / Rect.Width Dim Inv_Pic_Height = 4096 / Rect.Height Dim Inv2_Rect_Width = 256 / Rect.Width Dim Inv2_Rect_Height = 256 / Rect.Height Dim Half_Pic_width = Rect.Width / 2 Dim Half_Pic_Height = Rect.Height / 2 Dim points(aantal_co(tekening_nummer) - 1) As Point For teller As Integer = 0 To aantal_co(tekening_nummer) - 1 If teller - blanking >= 0 Then index = color_co(tekening_nummer, teller) penseel.Color = System.Drawing.Color.FromArgb(Rood_data(index), groen_data(index), blauw_data(index)) Else penseel.Color = System.Drawing.Color.FromArgb(0, 0, 0) End If X_buff = CInt((((((X_co(tekening_nummer, teller) - 2048) * Cos_Z_hoek_Scaled - (Y_co(tekening_nummer, teller) - 2048) * Sin_Z_hoek_Scaled) * Cos_Y_hoek_Scaled) * schaal_Scaled) + H_verplaatsing) / Inv_Pic_Width + Half_Pic_width) Y_buff = CInt((((((X_co(tekening_nummer, teller) - 2048) * Sin_Z_hoek_Scaled + (Y_co(tekening_nummer, teller) - 2048) * Cos_Z_hoek_Scaled) * Cos_X_hoek_Scaled) * schaal_Scaled) + V_verplaatsing) / Inv_Pic_Height + Half_Pic_Height) points(teller).X = X_buff points(teller).Y = Y_buff If X_buff >= 0 AndAlso X_buff < Rect.Width AndAlso Y_buff >= 0 AndAlso Y_buff < Rect.Height Then master_buffer(buffer_teller) = CByte(255 - X_buff * Inv2_Rect_Width) master_buffer(buffer_teller + 1) = CByte(255 - Y_buff * Inv2_Rect_Height) master_buffer(buffer_teller + 2) = 0 If teller - blanking >= 0 Then master_buffer(buffer_teller + 3) = color_co(tekening_nummer, teller) Else master_buffer(buffer_teller + 3) = 0 End If aantal_co_doorgeefluik = aantal_co_doorgeefluik + 1 End If buffer_teller = buffer_teller + 4 Next g.DrawLines(penseel, points) End Using End Sub
You pass an additional graphics object and a rectangle, which can be the ClientRectangle property of the control.
Tuesday, April 17, 2012 8:21 PM
Thanks a lot for al that information!
You told me a lot of things I didn't know about Visual basic until now.
Yesterday I was busy to remake my software and put in al the new things you told my. I hope I can finish my work now and that it works a lot faster.
Now, I'm busy to find more information about the new way of timing.