Author Topic: capturing HEX data of serial port continuously  (Read 4779 times)

bachphi

  • Hero Member
  • *****
  • Posts: 642
    • View Profile
capturing HEX data of serial port continuously
« 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

I am not quite able to translate the code to VB using the online converter.

Here is my current code:

Code: [Select]
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!
===================================================
This is NOT alt.read.my.mind.
No such thing is sh^t-for-brains unless you are posting to alt.read.my.mind.
===================================================

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: capturing HEX data of serial port continuously
« Reply #1 on: July 25, 2016, 12:00:55 PM »
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.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: capturing HEX data of serial port continuously
« Reply #2 on: July 25, 2016, 12:08:34 PM »
Here is an example:
Code: [Select]
    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

bachphi

  • Hero Member
  • *****
  • Posts: 642
    • View Profile
Re: capturing HEX data of serial port continuously
« Reply #3 on: July 25, 2016, 01:52:30 PM »
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.

Code: [Select]
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
===================================================
This is NOT alt.read.my.mind.
No such thing is sh^t-for-brains unless you are posting to alt.read.my.mind.
===================================================

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: capturing HEX data of serial port continuously
« Reply #4 on: July 25, 2016, 02:03:58 PM »
Is the packet always a fixed number of bytes?

bachphi

  • Hero Member
  • *****
  • Posts: 642
    • View Profile
Re: capturing HEX data of serial port continuously
« Reply #5 on: July 25, 2016, 02:07:44 PM »
its packet can vary
===================================================
This is NOT alt.read.my.mind.
No such thing is sh^t-for-brains unless you are posting to alt.read.my.mind.
===================================================

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: capturing HEX data of serial port continuously
« Reply #6 on: July 25, 2016, 02:21:33 PM »
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?

bachphi

  • Hero Member
  • *****
  • Posts: 642
    • View Profile
Re: capturing HEX data of serial port continuously
« Reply #7 on: July 25, 2016, 03:13:06 PM »
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.
===================================================
This is NOT alt.read.my.mind.
No such thing is sh^t-for-brains unless you are posting to alt.read.my.mind.
===================================================

bachphi

  • Hero Member
  • *****
  • Posts: 642
    • View Profile
Re: capturing HEX data of serial port continuously
« Reply #8 on: July 26, 2016, 04:17:57 PM »
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.

Code: [Select]
    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
===================================================
This is NOT alt.read.my.mind.
No such thing is sh^t-for-brains unless you are posting to alt.read.my.mind.
===================================================

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: capturing HEX data of serial port continuously
« Reply #9 on: July 26, 2016, 05:47:15 PM »
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

bachphi

  • Hero Member
  • *****
  • Posts: 642
    • View Profile
Re: capturing HEX data of serial port continuously
« Reply #10 on: July 26, 2016, 09:58:47 PM »
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). 

Code: [Select]
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



« Last Edit: July 26, 2016, 10:46:25 PM by bachphi »
===================================================
This is NOT alt.read.my.mind.
No such thing is sh^t-for-brains unless you are posting to alt.read.my.mind.
===================================================

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5262
    • View Profile
    • AdvancedHMI
Re: capturing HEX data of serial port continuously
« Reply #11 on: July 26, 2016, 10:28:29 PM »
I may have misunderstood the 128. Does a 128 value always come to mark the start of transmission?

bachphi

  • Hero Member
  • *****
  • Posts: 642
    • View Profile
Re: capturing HEX data of serial port continuously
« Reply #12 on: July 26, 2016, 10:34:28 PM »
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.
===================================================
This is NOT alt.read.my.mind.
No such thing is sh^t-for-brains unless you are posting to alt.read.my.mind.
===================================================

bachphi

  • Hero Member
  • *****
  • Posts: 642
    • View Profile
Re: capturing HEX data of serial port continuously
« Reply #13 on: July 26, 2016, 10:37:18 PM »
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.
===================================================
This is NOT alt.read.my.mind.
No such thing is sh^t-for-brains unless you are posting to alt.read.my.mind.
===================================================