to many speed / to many deviations on time everything

已答复 to many speed / to many deviations on time everything

  • 2012年4月14日 12:47
     
     

    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

        Private Sub Form2_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

            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月16日 7:26
    版主
     
     

    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日 14:18
     
      包含代码

    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:42
     
     已答复 包含代码

    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月17日 20:21
     
     

    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.