AdvancedHMI Software
General Category => Support Questions => Topic started by: bachphi on July 25, 2016, 11:47:11 AM
-
I have a device that continuously sending hex data messages. The message format consist of MessageID, one or more parameters and checksum. The checksum is a 2's complement 8-bit checksum.
On my DataReceived event, I validate the checksum condition, then display its data in a text box. But not all data is displayed. I think it is suffering the condition that was mentioned here http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport (http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport)
I am not quite able to translate the code to VB using the online converter.
Here is my current code:
Dim RXArray() As Char ' Text buffer. Must be global to be accessible from more threads.
Dim RXCnt As Integer ' Length of text buffer. Must be global too.
Private Sub ComPort_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles ComPort.DataReceived
Dim nbytes As Integer = ComPort.BytesToRead
Dim comBuffer() As Byte = New Byte(nbytes - 1) {} 'create a byte array to hold the awaiting data
ComPort.Read(comBuffer, 0, nbytes) ' {179,254,128,25,170,12}
Dim intChkSum As Integer = 0 'validate received data
For i As Integer = 0 To nbytes - 1
intChkSum = (intChkSum + comBuffer(i)) And &HFF
Next
If intChkSum = 0 Then
'RXArray = Bytes2Hex(comBuffer)
RXArray = BitConverter.ToString(comBuffer).Replace("-", " ").ToCharArray() 'B3 FE 80 19 AA 0C'
RXCnt = RXArray.Length
Else
Exit Sub
End If
Me.Invoke(New MethodInvoker(AddressOf Display))
End Sub
Private Sub Display()
'Received.AppendText(New String(RXArray, 0, RXCnt) & Environment.NewLine)
Received.AppendText(New String(RXArray, 0, RXCnt) & vbCrLf)
End Sub
Could someone out there help me, please. Thanks!
-
The DataReceived event from the serial port will not always return all of the data in a single event. You need to accumulate the data until you receive something designating the end of the transmission such as a Carriage Return (0x13) or an ETX.
-
Here is an example:
Private InputStreamBuilder As String
Private Sub ComPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles BarcodeReader3.DataReceived
Dim BytesToRead As Integer = ComPort.BytesToRead
Dim BytesRead(BytesToRead - 1) As Byte
Dim NumberOfBytesRead As Integer
NumberOfBytesRead = ComPort.Read(BytesRead, 0, BytesToRead)
Dim i As Integer
Dim CRFound As Boolean
Do While i < NumberOfBytesRead
'* Add each received byte to a string
If BytesRead(i) >= 32 Then
InputStreamBuilder &= Chr(BytesRead(i))
ElseIf BytesRead(i) = 13 Then
CRFound = True
End If
i += 1
Loop
'* Check if we read all characters
If CRFound Then
'* Sync with main thread and indicate a valid barcode received
Me.BeginInvoke(DisplayReceivedData, InputStreamBuilder)
InputStreamBuilder = ""
End If
End Sub
Private Sub DisplayReceivedData(ByVal StringFromComPort As String)
'* Show the data from the COM port
End Sub
-
The device adhere to J1587/ J1708 protocol, there are no end delimiters like CR, ETX. However its message start with MID + data + checksum. MID should be 128. and checksum (2's sum of all bytes) should be equal to 0. How can I use the two conditions to build the telegram.
Private Sub ComPort_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles ComPort.DataReceived
Dim nbytes As Integer = ComPort.BytesToRead
Dim comBuffer(nbytes - 1) As Byte 'create a byte array to hold the awaiting data
Dim NumberOfBytesRead As Integer
NumberOfBytesRead = ComPort.Read(comBuffer, 0, nbytes) ' {128,254,179,25,170,12}
Dim i As Integer
If comBuffer(0) = 128 Then
Do While i < NumberOfBytesRead
InputStreamBuilder &= Hex(comBuffer(i))
i += 1
Loop
End If
Dim intChkSum As Integer = 0 'validate received data
For j As Integer = 0 To NumberOfBytesRead - 1
intChkSum = (intChkSum + comBuffer(j)) And &HFF
Next
If intChkSum = 0 Then
'RXArray = Bytes2Hex(comBuffer)
RXArray = BitConverter.ToString(comBuffer).Replace("-", " ").ToCharArray() '80 FE B3 19 AA 0C'
RXCnt = RXArray.Length
Else
Exit Sub
End If
Me.Invoke(New MethodInvoker(AddressOf Display))
End Sub
-
Is the packet always a fixed number of bytes?
-
its packet can vary
-
I guess you have 2 options. Calculate the checksum, if it isn't correct, then assume there are more characters. Or start a timer when the first character comes and after the delay assume everything has arrived. How much time is there between packets? Does the protocol specify a minimum amount of silence in between transmissions?
-
Good question, Archie. I think it's above my pay grade.:=)
The device communicate with baudrate 9600 bit/sec, so I figure that 1 bit takes 0.1042 ms. 8bit+1Start+1Stop = 10 bits time = 1.04 ms.Plus the product of 2 bit times and the message priority (which ranges from 1 to 8 ). so anywhere between 12 bits to 26 bits ( between 1.25 ms to 2.71 ms)
When sending data , I know to how to compute checksum and add it to the send cmd string. just that on the receiver side, I need to figure out using the two conditions that I mentioned.
-
I modified the code to check for first byte=128 and build the string until checksum = 0 , but it still not display right, what did I do wrong here? Thanks.
Private Sub ComPort_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles ComPort.DataReceived
UpdateFormDelegate1 = New UpdateFormDelegate(AddressOf UpdateDisplay)
Dim RecBuffBytes As Integer = ComPort.BytesToRead 'get data in the receiver buffer
Dim comBuffer(RecBuffBytes - 1) As Byte 'create a byte array to hold the awaiting data
Dim NumberOfBytesRead As Integer
NumberOfBytesRead = ComPort.Read(comBuffer, 0, RecBuffBytes) ' {128,254,179,25,170,12}
Dim i As Integer
Dim intChkSum As Integer = 0
If comBuffer(0) = 128 Then 'If the first byte = 128
Do While i < NumberOfBytesRead
intChkSum = (intChkSum + comBuffer(i)) And &HFF
If (intChkSum <> 0) Then
InputStreamBuilder &= Hex(comBuffer(i)) 'build the telegram till checksum is 0
i += 1
ElseIf (intChkSum = 0) Then
'InputStreamBuilder &= Hex(comBuffer(i))
Me.Invoke(UpdateFormDelegate1) ' Update display with the built hex string
End If
Loop
End If
End Sub
-
Keep in mind the data can come in multiple chunks, so the first byte is not always going to be 128
Do While i < NumberOfBytesRead
If comBuffer(i) >= 128 Then 'If the first byte = 128
InputStreamBuilder=""
else
intChkSum = (intChkSum + comBuffer(i)) And &HFF
If (intChkSum <> 0) Then
InputStreamBuilder &= Hex(comBuffer(i)) 'build the telegram till checksum is 0
i += 1
ElseIf (intChkSum = 0) Then
Me.Invoke(UpdateFormDelegate1) ' Update display with the built hex string
End If
end if
Loop
-
Archie, It's sort of working now after some infinite looping. I jumper pins 2 & 3 , send 1st packet then the next one. It's works fine with 2 'perfect' packets.
Next , I tested with packet1 (combine 1st perfect packet + first half of the second Good packet)
and packet2 ( the last 1/2 of second packet + 3rd perfect packet)
"80B70003C6" '1st perfect packet
"80A80C01CB" '2nd perfect packet
"80B70003C680A8" '1st non-perfect
"0C01CB80B70103C5" '2nd non-perfect.
It only display the 1st (80B70003C6) and the 3rd one(80B70103C5).
Do While i < NumberOfBytesRead
If comBuffer(i) = 128 Then 'Start building packet when the byte = 128
InputStreamBuilder = ""
intChkSum = comBuffer(i)
InputStreamBuilder &= comBuffer(i).ToString("X2")
Else
intChkSum = (intChkSum + comBuffer(i)) And &HFF
If (intChkSum <> 0) Then
InputStreamBuilder &= comBuffer(i).ToString("X2") 'continue to build the telegram till checksum is 0
ElseIf (intChkSum = 0) Then
InputStreamBuilder &= comBuffer(i).ToString("X2") ' add the last byte which is the checksum byte
Me.Invoke(UpdateFormDelegate1) ' Update display with the built hex string
End If
End If
i += 1
Loop
-
I may have misunderstood the 128. Does a 128 value always come to mark the start of transmission?
-
I think I got it now. The InputStreamBuilder still keeping track of the data, but intChkSum got initizalized to 0 when it get back in the second time. I changed it to static instead. I will test some more tomorrow.
-
I may have misunderstood the 128. Does a 128 value always come to mark the start of transmission?
yes, 128 is MID of the engine, it should always be the first when it's the response from engine.