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
SystemImports
System.IO.PortsImports
System.MathImports
System.Threading.ThreadImports
System.IOImports
System.Timers.TimerImports
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 IfIf I = 1 Then
Rpm = ByteVal
End If
If I = 2 Then
T1HighCount = ByteVal
End IfIf I = 3 Then
T1LowCount = ByteVal
End If If I = 4 ThenT2HighCount = ByteVal
End IfIf I = 5 Then
T2LowCount = ByteVal
End If
If I = 6 Then
WheelPulsesHigh = ByteVal
End IfIf I = 7 Then
WheelPulsesLow = ByteVal
End IfI = 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 ThenGforceSignStr =
"^" ElseGforceSignStr =
"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 =
FalseCOMPort.DtrEnable =
FalseCOMPort.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 IfCOMPort.PortName = COMPortsBox.Text
' Default: 9600 Baud, 8 data bits, no parity, 1 stop bit
COMPort.ReadBufferSize = 40
TryCOMPort.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 =
"" ElseBaudRateBox.Text = COMPort.BaudRate
COMPort.RtsEnable =
FalseCOMPort.DtrEnable =
FalseCOMPort.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)
NextCOMPortsBox.Sorted =
TrueBaudRateBox.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 ThenSendByte = 1
End IfCOMPort.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 SubPrivate 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 leftIf 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 SingleChunkgv.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 SingleChunkgv.DrawString(
CStr(NextMarker), New Font("Verdana", 8, FontStyle.Regular), Brushes.Black, 1, i)NextMarker -= (ValueRange / HowManyChunks)
Next ' Step 4 Return bmp ' Step 5gv.Dispose()
End Function
End
Class
Display graph while viewing graph data in realtime.