Display graph while viewing graph data in realtime.

I am recieving bytes of data from t he comm port perfoming calculations and displaying the result.

I am new to Vb however in my code i was told I have to use delegates in order to display information the screen.

I also need t o display a graph.. How do I used delegates for the graph. I have only seen example using string pointers.

When I click on the button to generate graph the display reading start freak out...

Also sometime I get an error saying that the graph object already exist and the program crashes

my code below

Imports System

Imports System.IO.Ports

Imports System.Math

Imports System.Threading.Thread

Imports System.IO

Imports System.Timers.Timer

Imports System.Drawing.Drawing2D

' Imports the System, System.IO.Ports and System.Threading.Thread namespaces so that e.g.

' System.IO.Ports.SerialPort may just be written as SerialPort, and System.EventArgs may just be

' written as EventArgs.

Public Class MaxiTester

Dim Xmove As Integer = 3

Private OldValue As Single = 0

Private NewValue As Single = 0

' This variable hold the weight of the car.

Dim Weight As Integer = 0

Dim Speed As Integer = 0

Dim Rpm As Integer = 0

Dim Power As Double = 0

Dim Torque As Double = 0

Dim Gforce As Double

Dim TempOfAir As Single

Dim AtmosPressure As Single

Dim FrontalArea As Single

Dim DragCoeff As Single

Dim SaeCorrection As Double

Dim AirDensity As Double

Dim AerodynamicDrag As Double

Dim TotalForce As Double

Dim RoadSpeed As Double

Dim EngineRpm As Integer

Dim ElapsedTime As Integer

Dim DutyCycle As Integer

Dim Gforce20 As Double = 0

Dim Gforce19 As Double = 0

Dim Gforce18 As Double = 0

Dim Gforce17 As Double = 0

Dim Gforce16 As Double = 0

Dim Gforce15 As Double = 0

Dim Gforce14 As Double = 0

Dim Gforce13 As Double = 0

Dim Gforce12 As Double = 0

Dim Gforce11 As Double = 0

Dim Gforce10 As Double = 0

Dim Gforce9 As Double = 0

Dim Gforce8 As Double = 0

Dim Gforce7 As Double = 0

Dim Gforce6 As Double = 0

Dim Gforce5 As Double = 0

Dim Gforce4 As Double = 0

Dim Gforce3 As Double = 0

Dim Gforce2 As Double = 0

Dim Gforce1 As Double = 0

Dim T1LowCount As Integer

Dim T1HighCount As Integer

Dim T2LowCount As Integer

Dim T2HighCount As Integer

Dim ZCAL As Integer = 2265

Dim BitScaleFactor As Integer = 180

Dim T2CAL As Integer = 4403

Dim Zactual As Integer

Dim K As Integer = 697

Dim Acceleration As Double

Dim WheelPulsesHigh As Integer

Dim WheelPulsesLow As Integer

Dim WheelRevolutions As Double

Dim Distance As Double

Dim GraphValue As Single

Dim GforceTotal As Double

Dim GforceTotal1 As Double

Dim GforceTotal2 As Double

Dim Pins As Long

Dim GforceAverage As Double

Dim MilliSecondsPassed As Integer

Dim FileRec As String

Dim StartTime As Date

Dim RecordsWritten As Integer = 0

Dim PinNumber As Integer

' Get a StreamReader class that can be used to read the file

Dim objStreamWriter As New StreamWriter("c:\test.txt", True)

' Declare a type-safe pointer to subroutines, which use one string as argument (like Display).

' It is used as a pointer to the subroutine, which should handle a given event with string data (like

' a received string, which should be displayed).

Public Delegate Sub StringSubPointer(ByVal Buffer As String)

Dim WithEvents COMPort As New SerialPort ' Make a new System.IO.Ports.SerialPort instance, which is able to send events

Private Sub Receiver(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) Handles COMPort.DataReceived

Dim RXByte As Byte

Dim RXArray(4) As Char

Dim I As Integer = 0

Dim J As Integer = 0

Dim ByteVal As Integer = 0

Dim Speedstr As String

Dim Rpmstr As String

Dim Powerstr As String

Dim TorqueStr As String

Dim GforceAverageStr As String

Dim GforceSignStr As String

Dim TiltStr As String

Dim DistanceStr As String

Dim ElapsedTimeStr As String

Dim MilliSecondsPassedStr As String

Dim GsensorPeriod As Integer

Dim GsensorHighPulse As Integer

Dim GsensorLowPulse As Integer

Dim WheelRevolutions As Integer

Dim GraphValue As Integer

RXByte = COMPort.ReadByte

While (COMPort.BytesToRead > 0) And (CInt(RXByte) <> 255)

RXByte = COMPort.ReadByte

End While

While (COMPort.BytesToRead > 0) And (I < 9)

RXByte = COMPort.ReadByte

ByteVal = CInt(RXByte)

If I = 0 Then

Speed = ByteVal

End If

If I = 1 Then

Rpm = ByteVal

End If

If I = 2 Then

T1HighCount = ByteVal

End If

If I = 3 Then

T1LowCount = ByteVal

End If

If I = 4 Then

T2HighCount = ByteVal

End If

If I = 5 Then

T2LowCount = ByteVal

End If

If I = 6 Then

WheelPulsesHigh = ByteVal

End If

If I = 7 Then

WheelPulsesLow = ByteVal

End If

I = I + 1

End While

GsensorHighPulse = (T1HighCount * 256) + T1LowCount

GsensorLowPulse = (T2HighCount * 256) + T2LowCount

GsensorPeriod = GsensorLowPulse + GsensorHighPulse

WheelRevolutions = ((WheelPulsesHigh * 256) + WheelPulsesLow) / 4

Distance = WheelRevolutions * 1.82

Zactual = ZCAL * GsensorPeriod / T2CAL

Acceleration = K * (GsensorHighPulse - Zactual) / GsensorPeriod

Gforce = Acceleration / 90

If Gforce > 0 Then

GforceSignStr = "^"

Else

GforceSignStr = "V"

End If

Gforce20 = Gforce19

Gforce19 = Gforce18

Gforce18 = Gforce17

Gforce17 = Gforce16

Gforce16 = Gforce15

Gforce15 = Gforce14

Gforce14 = Gforce13

Gforce13 = Gforce12

Gforce12 = Gforce11

Gforce11 = Gforce10

Gforce10 = Gforce9

Gforce9 = Gforce8

Gforce8 = Gforce7

Gforce7 = Gforce6

Gforce6 = Gforce5

Gforce5 = Gforce4

Gforce4 = Gforce3

Gforce3 = Gforce2

Gforce2 = Gforce1

Gforce1 = Gforce

GforceTotal1 = Gforce1 + Gforce2 + Gforce3 + Gforce4 + Gforce5 + Gforce6 + Gforce7 + Gforce8 + Gforce9 + Gforce10

GforceTotal2 = Gforce11 + Gforce12 + Gforce13 + Gforce14 + Gforce15 + Gforce16 + Gforce17 + Gforce18 + Gforce19 + Gforce20

GforceTotal = GforceTotal1 + GforceTotal2

GforceAverage = GforceTotal / 20

If GraphRadioButton.Checked = True Then

GraphValue = Int(GforceAverage * 90)

'PictureBoxGraph.Image = DisplayGuidelinesAndChart(PictureBoxGraph, 12, 3, GraphValue, 0, 100)

PictureBoxGraph.Image = DisplayGuidelinesAndChart(PictureBoxGraph, 10, 3, GraphValue, 0, 100)

End If

RoadSpeed = (Speed / 4) * 1.8

EngineRpm = Rpm * 60

Rpmstr = EngineRpm

Speedstr = RoadSpeed * 3.6

DistanceStr = Distance

AerodynamicDrag = 0.5 * AirDensity * (RoadSpeed ^ 2) * DragCoeff * FrontalArea

TotalForce = (Weight * GforceAverage * 9.81) + AerodynamicDrag

Power = RoadSpeed * TotalForce * SaeCorrection * 0.001341

Torque = Power * 5252 / EngineRpm

GforceAverageStr = GforceAverage

TiltStr = Int(GforceAverage * 90)

Powerstr = Int(Power)

TorqueStr = Int(Torque)

ElapsedTime = DateDiff("s", StartTime, Now())

ElapsedTimeStr = ElapsedTime

MilliSecondsPassedStr = MilliSecondsPassed

FileRec = MilliSecondsPassedStr + " " + Powerstr + " " + TorqueStr

Dim RxString As New String(GforceAverageStr)

Dim Speedstring As New String(Speedstr)

Dim Powerstring As New String(Powerstr)

Dim ElapsedTimeString As New String(ElapsedTimeStr)

Dim TorqueString As New String(TorqueStr)

Dim RpmString As New String(Rpmstr)

Dim GforceSignString As New String(GforceSignStr)

Dim TiltString As New String(TiltStr)

Dim DistanceString As New String(DistanceStr)

' Send RxString to the Display subrotine and return immediately.

Received.BeginInvoke(New StringSubPointer(AddressOf Display), RxString)

' Send SpeedString to the Display subrotine and return immediately.

SpeedOut.BeginInvoke(New StringSubPointer(AddressOf Disspeed), Speedstring)

' Send PowerString to the Display subrotine and return immediately.

PowerOut.BeginInvoke(New StringSubPointer(AddressOf Dispower), Powerstring)

' Send ElapsedTimeString to the Display subrotine and return immediately.

ElapsedTimeOut.BeginInvoke(New StringSubPointer(AddressOf DisTime), ElapsedTimeString)

' Send TorqueString to the Display subrotine and return immediately.

TorqueOut.BeginInvoke(New StringSubPointer(AddressOf DisTorque), TorqueString)

' Send RpmString to the Display subrotine and return immediately.

RpmOut.BeginInvoke(New StringSubPointer(AddressOf DisRpm), RpmString)

' Send GforceSignString to the Display subrotine and return immediately.

GforceSignOut.BeginInvoke(New StringSubPointer(AddressOf DisSign), GforceSignString)

' Send TiltString to the Display subrotine and return immediately.

TiltOut.BeginInvoke(New StringSubPointer(AddressOf DisTilt), TiltString)

' Send DistanceString to the Display subrotine and return immediately.

DistanceOut.BeginInvoke(New StringSubPointer(AddressOf DisDistance), DistanceString)

End Sub

' Text display routine, which displays the received string to any text in the Received TextBox form.

Private Sub Display(ByVal Buffer As String)

Received.Text = Buffer

End Sub

' This subroutine will fire when the elapsed time event

' has been reached.

' The label is set to the current time after the

' interval has been reached.

Private Sub systemTimer_Elapsed(ByVal sender As System.Object, ByVal e As System.Timers.ElapsedEventArgs) Handles Timer1.Elapsed

If RecordsWritten < 20000 Then

'Write a line of text.

objStreamWriter.WriteLine(FileRec)

RecordsWritten = RecordsWritten + 1

MilliSecondsPassed = MilliSecondsPassed + 200

End If

End Sub

' Text display routine, which displays the received string to any text in the Received TextBox form.

Private Sub Disspeed(ByVal Buffer As String)

SpeedOut.Text = Buffer

End Sub

' Text display routine, which displays the received string to any text in the Received TextBox form.

Private Sub Dispower(ByVal Buffer As String)

PowerOut.Text = Buffer

End Sub

' Text display routine, which displays the received string to any text in the Received TextBox form.

Private Sub DisTime(ByVal Buffer As String)

ElapsedTimeOut.Text = Buffer

End Sub

' Text display routine, which displays the received string to any text in the Received TextBox form.

Private Sub DisTorque(ByVal Buffer As String)

TorqueOut.Text = Buffer

End Sub

' Text display routine, which displays the received string to any text in the Rpm Label form.

Private Sub DisRpm(ByVal Buffer As String)

RpmOut.Text = Buffer

End Sub

' Text display routine, which displays the received string to any text in the Rpm Label form.

Private Sub DisSign(ByVal Buffer As String)

GforceSignOut.Text = Buffer

End Sub

' Text display routine, which displays the received string to any text in the Received TextBox form.

Private Sub DisTilt(ByVal Buffer As String)

TiltOut.Text = Buffer

End Sub

' Text display routine, which displays the received string to any text in the Received TextBox form.

Private Sub DisDistance(ByVal Buffer As String)

DistanceOut.Text = Buffer

End Sub

' This subroutine handles a change in Baud Rate.

Private Sub BaudRate(ByVal sender As Object, ByVal e As EventArgs) Handles BaudRateBox.SelectedIndexChanged

COMPort.BaudRate = CInt(BaudRateBox.Text)

End Sub

' This subroutine handles a change of COM ports.

Private Sub COMPortsBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles COMPortsBox.SelectedIndexChanged

If COMPort.IsOpen Then

COMPort.RtsEnable = False

COMPort.DtrEnable = False

COMPort.Close()

Application.DoEvents() ' Let all applications finish before the whole process goes to sleep.

Sleep(500) ' Wait 0.5 second for port to close as this do not happen immediately.

End If

COMPort.PortName = COMPortsBox.Text ' Default: 9600 Baud, 8 data bits, no parity, 1 stop bit

COMPort.ReadBufferSize = 40

Try

COMPort.Open()

Catch ex As Exception

' MsgBox(ex.Message)

End Try

StartTime = Now()

TempTextbox.Text = "32"

PressureTextBox.Text = "1013"

AreaTextBox.Text = "2"

DragTextBox.Text = "0.45"

WeightTextBox.Text = "920"

TempOfAir = CInt(TempTextbox.Text)

AtmosPressure = CInt(PressureTextBox.Text)

FrontalArea = CInt(AreaTextBox.Text)

DragCoeff = DragTextBox.Text

Weight = CInt(WeightTextBox.Text)

SaeCorrection = (1.18 * ((990 / AtmosPressure) * Sqrt((TempOfAir + 273.15) / 298))) - 0.18

AirDensity = 0.0412236 * AtmosPressure / (TempOfAir + 273.15)

Timer1.Start()

If COMPort Is Nothing Then

BaudRateBox.Text = ""

Else

BaudRateBox.Text = COMPort.BaudRate

COMPort.RtsEnable = False

COMPort.DtrEnable = False

COMPort.ReceivedBytesThreshold = 40

End If

End Sub

' This subroutine is activated when the form is loaded. It does all the basic initializations.

' RTS/CTS hardware flow control is necessary for Max-i communication. Note that the standard UART 16C550

' has no hardware flow control - except for UART's from Texas Instruments.

' The minimum FIFO size is calculated on the basis of a 1.4 mS response time, which is the absolute minimum

' for Windows applications.

Private Sub MaxiTester_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load

For Each COMString As String In My.Computer.Ports.SerialPortNames ' Load all available COM ports.

COMPortsBox.Items.Add(COMString)

Next

COMPortsBox.Sorted = True

BaudRateBox.Items.Add("9600")

BaudRateBox.Items.Add("57600")

' Add the pin numbers 0 to 15 to cboPinNumber

For Pins = 0 To 7

ComboBoxPinNumber.Items.Add(CStr(Pins))

Next Pins

picValues.Image = DisplayVerticalValues(picValues, 20, 0, 100)

End Sub

' This subroutine is activated when the form is closed. It closes the COM port. Without such a close command,

' the garbage collector may close the COM port while it is still in use!

Private Sub MaxiTester_Closing(ByVal sender As Object, ByVal e As ComponentModel.CancelEventArgs) Handles MyBase.Closing

If COMPort.IsOpen Then COMPort.Close() ' Close COM port when the form is terminated with [X]

'Close the file.

objStreamWriter.Close()

Timer1.Stop()

End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim SendByte As Integer

' Get Pin Number

SendByte = PinNumber

COMPort.Write(Chr(SendByte))

' Get Pin State

If RadioButtonOff.Checked = True Then

SendByte = 0

End If

If RadioButtonOn.Checked = True Then

SendByte = 1

End If

COMPort.Write(Chr(SendByte))

End Sub

' This subroutine handles a change in Pin Number.

Private Sub PicPinNumber(ByVal sender As Object, ByVal e As EventArgs) Handles ComboBoxPinNumber.SelectedIndexChanged

PinNumber = CInt(ComboBoxPinNumber.Text)

End Sub

Private Function DisplayGuidelinesAndChart(ByVal PicBox As PictureBox, ByVal chunks As Integer, ByVal XMove As Integer, ByVal NewValue As Single, ByVal Min As Single, ByVal Max As Single) As Bitmap

' Step 1

' Grab the current image (the latest version of the chart)

Dim bm As New Bitmap(PicBox.Width, PicBox.Height)

Dim gr As Graphics = Graphics.FromImage(bm)

' Step 2

' Get the total height available and split it into chunks

Dim total As Integer = PicBox.Height

Dim chunk As Single = total / chunks

' Tack missing guidelines to right hand side on the Graphics object.

For i As Single = chunk To total Step chunk

gr.DrawLine(Pens.WhiteSmoke, PicBox.Width - XMove, i, PicBox.Width, i)

Next i

' Step 3

' Draw this grabbed image, placing it XMove pixels to the left

If Not IsNothing(PicBox.Image) Then

gr.DrawImage(PicBox.Image, -XMove, 0)

End If

' Step 4

' Plot the new value.

' Calculate the scaling required to make full use of the height of

' the PictureBox

Dim ValueRange As Single = Max - Min

Dim vScale As Single = PicBox.Height / ValueRange

' Apply the scale to the current value

NewValue *= vScale

' Step 5

' Shift start point from top left to bottom left.

gr.TranslateTransform(0, PictureBoxGraph.Height)

' Step 6

' Draw the next line segment on the Graphics object.

' If Min is > 0 then you need to shift the drawing down once again,

' this time to put the Min value on the horizontal axis

If Min > 0 Then gr.TranslateTransform(0, Min * vScale)

gr.DrawLine(Pens.Black, _

PictureBoxGraph.Width - 1 - XMove, -OldValue, _

PictureBoxGraph.Width - 1, -NewValue)

OldValue = NewValue

' Step 7

' Return the Bitmap .

Return bm

' Step 8

' All done

gr.Dispose()

End Function

Private Function DisplayVerticalValues(ByVal PB As PictureBox, ByVal HowManyChunks As Single, _

ByVal MinValue As Single, ByVal MaxValue As Single) As Bitmap

' Step 1

Dim bmp As New Bitmap(PB.Width, PB.Height)

Dim gv As Graphics = Graphics.FromImage(bmp)

' Step 2

' Draw guidelines on values strip

' Get the total height available and split it into chunks

' This value represents a number of pixels

Dim TotalPixels As Integer = PB.Height

Dim SingleChunk As Single = TotalPixels / HowManyChunks

For i As Single = SingleChunk To TotalPixels Step SingleChunk

gv.DrawLine(Pens.WhiteSmoke, 0, i, PB.Width, i)

Next i

' Step 3

' Draw Numbers as Text, correctly spaced vertically

' Begin with the highest value allowed

Dim NextMarker As Integer = MaxValue

Dim ValueRange As Single = MaxValue - MinValue

' Draw the numbers, decrementing values proportionately each time through the loop

For i As Single = 0 To TotalPixels Step SingleChunk

gv.DrawString(CStr(NextMarker), New Font("Verdana", 8, FontStyle.Regular), Brushes.Black, 1, i)

NextMarker -= (ValueRange / HowManyChunks)

Next

' Step 4

Return bmp

' Step 5

gv.Dispose()

End Function

End Class



Answer this question

Display graph while viewing graph data in realtime.

  • Display graph while viewing graph data in realtime.