# to many speed / to many deviations on time everything

### 问题

• Hello,

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)

Private Sub teken_afbeelding(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, X_buff_2, Y_buff_2 As Integer

Dim penseel As New System.Drawing.Pen(System.Drawing.Color.FromArgb(Rood_data(color_co(tekening_nummer, 1) - 1), groen_data(color_co(tekening_nummer, 1) - 1), blauw_data(color_co(tekening_nummer, 1) - 1)))

Dim buffer_teller As Integer

aantal_co_doorgeefluik = 0

PictureBox1.CreateGraphics.Clear(Color.Black)

For teller As Integer = 0 To aantal_co(tekening_nummer) - 1

If teller - blanking >= 0 Then

penseel.Color = System.Drawing.Color.FromArgb(Rood_data(color_co(tekening_nummer, teller)), groen_data(color_co(tekening_nummer, teller)), blauw_data(color_co(tekening_nummer, teller)))

Else

penseel.Color = System.Drawing.Color.FromArgb(0, 0, 0)

End If

X_buff = (((((X_co(tekening_nummer, teller) - 2048) * Math.Cos(Z_hoek * 0.0246) - (Y_co(tekening_nummer, teller) - 2048) * Math.Sin(Z_hoek * 0.0246)) * Math.Cos(Y_hoek * 0.0246)) * (schaal / 100)) + H_verplaatsing) / (4096 / PictureBox1.Width) + PictureBox1.Width / 2

Y_buff = (((((X_co(tekening_nummer, teller) - 2048) * Math.Sin(Z_hoek * 0.0246) + (Y_co(tekening_nummer, teller) - 2048) * Math.Cos(Z_hoek * 0.0246)) * Math.Cos(X_hoek * 0.0246)) * (schaal / 100)) + V_verplaatsing) / (4096 / PictureBox1.Height) + PictureBox1.Height / 2

If X_buff >= 0 And X_buff < PictureBox1.Width And Y_buff >= 0 And Y_buff < PictureBox1.Height Then

master_buffer(buffer_teller) = CByte(255 - X_buff * (256 / PictureBox1.Width))

master_buffer(buffer_teller + 1) = CByte(255 - Y_buff * (256 / PictureBox1.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

If aantal_co(tekening_nummer) - 1 <> teller Then

X_buff_2 = (((((X_co(tekening_nummer, teller + 1) - 2048) * Math.Cos(Z_hoek * 0.0246) - (Y_co(tekening_nummer, teller + 1) - 2048) * Math.Sin(Z_hoek * 0.0246)) * Math.Cos(Y_hoek * 0.0246)) * (schaal / 100)) + H_verplaatsing) / (4096 / PictureBox1.Width) + PictureBox1.Width / 2

Y_buff_2 = (((((X_co(tekening_nummer, teller + 1) - 2048) * Math.Sin(Z_hoek * 0.0246) + (Y_co(tekening_nummer, teller + 1) - 2048) * Math.Cos(Z_hoek * 0.0246)) * Math.Cos(X_hoek * 0.0246)) * (schaal / 100)) + V_verplaatsing) / (4096 / PictureBox1.Height) + PictureBox1.Height / 2

End If

PictureBox1.CreateGraphics.DrawLine(penseel, X_buff, Y_buff, X_buff_2, Y_buff_2)

Next

End Sub

Form2:

Public Class Form2

Private Sub Form2_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing

Dim buffer() As Byte = {0, 0, 0, 0}

SerialPort1.Write(buffer, 0, 4)

SerialPort1.Close()

End Sub

Timer1.Enabled = True

SerialPort1.Open()

End Sub

Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick

Dim buffer(Form1.aantal_co_doorgeefluik * 4 + 4) As Byte

For teller2 As Integer = 0 To (Form1.aantal_co_doorgeefluik * 4) Step 4

buffer(teller2) = Form1.master_buffer(teller2)

buffer(teller2 + 1) = Form1.master_buffer(teller2 + 1)

buffer(teller2 + 2) = 0

buffer(teller2 + 3) = Form1.master_buffer(teller2 + 3)

Next

Try

SerialPort1.Write(buffer, 0, Form1.aantal_co_doorgeefluik * 4)

Catch

Timer1.Enabled = False

End Try

If Form1.projectie_teller >= Form1.aantal_co(Form1.loop_effect_nummer) Then

Form1.projectie_teller = 0

End If

End Sub

End Class

Thank you for helping,

Ruben Hollevoet

2012年4月14日 12:47

### 答案

• 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.

2012年4月16日 14:42

### 全部回复

• Hi Ruben,

We will try to involve some senior engineers in this case.

Thanks,

Shanks Zen
MSDN Community Support | Feedback to us

2012年4月16日 7:26
• 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.

Armin

2012年4月16日 14:18
• 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.

2012年4月16日 14:42
• 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.