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.

PublicClass MaxiTester

Dim XmoveAsInteger = 3

Private OldValueAsSingle = 0

Private NewValueAsSingle = 0

' This variable hold the weight of the car.

Dim WeightAsInteger = 0

Dim SpeedAsInteger = 0

Dim RpmAsInteger = 0

Dim PowerAsDouble = 0

Dim TorqueAsDouble = 0

Dim GforceAsDouble

Dim TempOfAirAsSingle

Dim AtmosPressureAsSingle

Dim FrontalAreaAsSingle

Dim DragCoeffAsSingle

Dim SaeCorrectionAsDouble

Dim AirDensityAsDouble

Dim AerodynamicDragAsDouble

Dim TotalForceAsDouble

Dim RoadSpeedAsDouble

Dim EngineRpmAsInteger

Dim ElapsedTimeAsInteger

Dim DutyCycleAsInteger

Dim Gforce20AsDouble = 0

Dim Gforce19AsDouble = 0

Dim Gforce18AsDouble = 0

Dim Gforce17AsDouble = 0

Dim Gforce16AsDouble = 0

Dim Gforce15AsDouble = 0

Dim Gforce14AsDouble = 0

Dim Gforce13AsDouble = 0

Dim Gforce12AsDouble = 0

Dim Gforce11AsDouble = 0

Dim Gforce10AsDouble = 0

Dim Gforce9AsDouble = 0

Dim Gforce8AsDouble = 0

Dim Gforce7AsDouble = 0

Dim Gforce6AsDouble = 0

Dim Gforce5AsDouble = 0

Dim Gforce4AsDouble = 0

Dim Gforce3AsDouble = 0

Dim Gforce2AsDouble = 0

Dim Gforce1AsDouble = 0

Dim T1LowCountAsInteger

Dim T1HighCountAsInteger

Dim T2LowCountAsInteger

Dim T2HighCountAsInteger

Dim ZCALAsInteger = 2265

Dim BitScaleFactorAsInteger = 180

Dim T2CALAsInteger = 4403

Dim ZactualAsInteger

Dim KAsInteger = 697

Dim AccelerationAsDouble

Dim WheelPulsesHighAsInteger

Dim WheelPulsesLowAsInteger

Dim WheelRevolutionsAsDouble

Dim DistanceAsDouble

Dim GraphValueAsSingle

Dim GforceTotalAsDouble

Dim GforceTotal1AsDouble

Dim GforceTotal2AsDouble

Dim PinsAsLong

Dim GforceAverageAsDouble

Dim MilliSecondsPassedAsInteger

Dim FileRecAsString

Dim StartTimeAsDate

Dim RecordsWrittenAsInteger = 0

Dim PinNumberAsInteger

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

Dim objStreamWriterAsNew 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).

PublicDelegateSub StringSubPointer(ByVal BufferAsString)

DimWithEvents COMPortAsNew SerialPort' Make a new System.IO.Ports.SerialPort instance, which is able to send events

PrivateSub Receiver(ByVal senderAsObject,ByVal eAs SerialDataReceivedEventArgs)Handles COMPort.DataReceived

Dim RXByteAsByte

Dim RXArray(4)AsChar

Dim IAsInteger = 0

Dim JAsInteger = 0

Dim ByteValAsInteger = 0

Dim SpeedstrAsString

Dim RpmstrAsString

Dim PowerstrAsString

Dim TorqueStrAsString

Dim GforceAverageStrAsString

Dim GforceSignStrAsString

Dim TiltStrAsString

Dim DistanceStrAsString

Dim ElapsedTimeStrAsString

Dim MilliSecondsPassedStrAsString

Dim GsensorPeriodAsInteger

Dim GsensorHighPulseAsInteger

Dim GsensorLowPulseAsInteger

Dim WheelRevolutionsAsInteger

Dim GraphValueAsInteger

RXByte = COMPort.ReadByte

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

RXByte = COMPort.ReadByte

EndWhile

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

RXByte = COMPort.ReadByte

ByteVal =CInt(RXByte)

If I = 0Then

Speed = ByteVal

EndIf

If I = 1Then

Rpm = ByteVal

EndIf

If I = 2Then

T1HighCount = ByteVal

EndIf

If I = 3Then

T1LowCount = ByteVal

EndIf

If I = 4Then

T2HighCount = ByteVal

EndIf

If I = 5Then

T2LowCount = ByteVal

EndIf

If I = 6Then

WheelPulsesHigh = ByteVal

EndIf

If I = 7Then

WheelPulsesLow = ByteVal

EndIf

I = I + 1

EndWhile

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 > 0Then

GforceSignStr ="^"

Else

GforceSignStr ="V"

EndIf

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 =TrueThen

GraphValue = Int(GforceAverage * 90)

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

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

EndIf

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 RxStringAsNewString(GforceAverageStr)

Dim SpeedstringAsNewString(Speedstr)

Dim PowerstringAsNewString(Powerstr)

Dim ElapsedTimeStringAsNewString(ElapsedTimeStr)

Dim TorqueStringAsNewString(TorqueStr)

Dim RpmStringAsNewString(Rpmstr)

Dim GforceSignStringAsNewString(GforceSignStr)

Dim TiltStringAsNewString(TiltStr)

Dim DistanceStringAsNewString(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)

EndSub

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

PrivateSub Display(ByVal BufferAsString)

Received.Text = Buffer

EndSub

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

PrivateSub systemTimer_Elapsed(ByVal senderAs System.Object,ByVal eAs System.Timers.ElapsedEventArgs)Handles Timer1.Elapsed

If RecordsWritten < 20000Then

'Write a line of text.

objStreamWriter.WriteLine(FileRec)

RecordsWritten = RecordsWritten + 1

MilliSecondsPassed = MilliSecondsPassed + 200

EndIf

EndSub

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

PrivateSub Disspeed(ByVal BufferAsString)

SpeedOut.Text = Buffer

EndSub

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

PrivateSub Dispower(ByVal BufferAsString)

PowerOut.Text = Buffer

EndSub

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

PrivateSub DisTime(ByVal BufferAsString)

ElapsedTimeOut.Text = Buffer

EndSub

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

PrivateSub DisTorque(ByVal BufferAsString)

TorqueOut.Text = Buffer

EndSub

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

PrivateSub DisRpm(ByVal BufferAsString)

RpmOut.Text = Buffer

EndSub

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

PrivateSub DisSign(ByVal BufferAsString)

GforceSignOut.Text = Buffer

EndSub

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

PrivateSub DisTilt(ByVal BufferAsString)

TiltOut.Text = Buffer

EndSub

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

PrivateSub DisDistance(ByVal BufferAsString)

DistanceOut.Text = Buffer

EndSub

' This subroutine handles a change in Baud Rate.

PrivateSub BaudRate(ByVal senderAsObject,ByVal eAs EventArgs)Handles BaudRateBox.SelectedIndexChanged

COMPort.BaudRate =CInt(BaudRateBox.Text)

EndSub

' This subroutine handles a change of COM ports.

PrivateSub COMPortsBox_SelectedIndexChanged(ByVal senderAsObject,ByVal eAs EventArgs)Handles COMPortsBox.SelectedIndexChanged

If COMPort.IsOpenThen

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.

EndIf

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

COMPort.ReadBufferSize = 40

Try

COMPort.Open()

Catch exAs Exception

' MsgBox(ex.Message)

EndTry

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 COMPortIsNothingThen

BaudRateBox.Text =""

Else

BaudRateBox.Text = COMPort.BaudRate

COMPort.RtsEnable =False

COMPort.DtrEnable =False

COMPort.ReceivedBytesThreshold = 40

EndIf

EndSub

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

PrivateSub MaxiTester_Load(ByVal senderAsObject,ByVal eAs EventArgs)HandlesMyBase.Load

ForEach COMStringAsStringInMy.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 = 0To 7

ComboBoxPinNumber.Items.Add(CStr(Pins))

Next Pins

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

EndSub

' 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!

PrivateSub MaxiTester_Closing(ByVal senderAsObject,ByVal eAs ComponentModel.CancelEventArgs)HandlesMyBase.Closing

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

'Close the file.

objStreamWriter.Close()

Timer1.Stop()

EndSub

PrivateSub Button1_Click(ByVal senderAs System.Object,ByVal eAs System.EventArgs)Handles Button1.Click

Dim SendByteAsInteger

' Get Pin Number

SendByte = PinNumber

COMPort.Write(Chr(SendByte))

' Get Pin State

If RadioButtonOff.Checked =TrueThen

SendByte = 0

EndIf

If RadioButtonOn.Checked =TrueThen

SendByte = 1

EndIf

COMPort.Write(Chr(SendByte))

EndSub

' This subroutine handles a change in Pin Number.

PrivateSub PicPinNumber(ByVal senderAsObject,ByVal eAs EventArgs)Handles ComboBoxPinNumber.SelectedIndexChanged

PinNumber =CInt(ComboBoxPinNumber.Text)

EndSub

PrivateFunction DisplayGuidelinesAndChart(ByVal PicBoxAs PictureBox,ByVal chunksAsInteger,ByVal XMoveAsInteger,ByVal NewValueAsSingle,ByVal MinAsSingle,ByVal MaxAsSingle)As Bitmap

' Step 1

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

Dim bmAsNew Bitmap(PicBox.Width, PicBox.Height)

Dim grAs Graphics = Graphics.FromImage(bm)

' Step 2

' Get the total height available and split it into chunks

Dim totalAsInteger = PicBox.Height

Dim chunkAsSingle = total / chunks

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

For iAsSingle = chunkTo totalStep 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

IfNot IsNothing(PicBox.Image)Then

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

EndIf

' Step 4

' Plot the new value.

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

' the PictureBox

Dim ValueRangeAsSingle = Max - Min

Dim vScaleAsSingle = 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 > 0Then 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()

EndFunction

PrivateFunction DisplayVerticalValues(ByVal PBAs PictureBox,ByVal HowManyChunksAsSingle, _

ByVal MinValueAsSingle,ByVal MaxValueAsSingle)As Bitmap

' Step 1

Dim bmpAsNew Bitmap(PB.Width, PB.Height)

Dim gvAs 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 TotalPixelsAsInteger = PB.Height

Dim SingleChunkAsSingle = TotalPixels / HowManyChunks

For iAsSingle = SingleChunkTo TotalPixelsStep 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 NextMarkerAsInteger = MaxValue

Dim ValueRangeAsSingle = MaxValue - MinValue

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

For iAsSingle = 0To TotalPixelsStep 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()

EndFunction

EndClass

[63784 byte] By [HOODEY] at [2007-12-28]