Ask a questionAsk a question
 

AnswerEmpty serial Port Read Buffer

  • Tuesday, November 03, 2009 12:07 PMAngeloErre Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Is possible to empty read buffer of serial port component?

    I'm become crazy to find a solution :-S

    I am using this code
    ''''''''''''''''''''''''''''''''''
            SerialPort1.PortName = portabacchetta.Text
            SerialPort1.BaudRate = 9600
            SerialPort1.Parity = IO.Ports.Parity.None
            SerialPort1.DataBits = 8
            SerialPort1.StopBits = IO.Ports.StopBits.One
            SerialPort1.Handshake = IO.Ports.Handshake.None
            SerialPort1.RtsEnable = True
            SerialPort1.Open()

     Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived

            Rx = SerialPort1.ReadExisting 'or SerialPort1.ReadLine SerialPort1.ReadExisting
            SerialPort1.DiscardOutBuffer()
            Me.Invoke(New EventHandler(AddressOf DoUpdate))
        End Sub
        Public Sub DoUpdate()

            If Len(Rx) > 9 Then
                TextBox2.Text = ""
                TextBox2.Text = TextBox2.Text & Rx
                TextBox1.Text = TextBox2.Text.Substring(0, TextBox2.Text.Length - 1)




                If Rx = "000E41154A" Then
                    Label5.Text = "PROVA"

                End If
            End If
        End Sub

Answers

  • Wednesday, November 04, 2009 7:45 AMCarsten Kanstrup Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    How have you declared RX? In VB, all strings are immutable, meaning you cannot change its length or contents once it is declared. Therefore, your code may only work once. Besides, you still expect RX to survive until DoUpdate() gets up and running. If more data are received, this may not be the case.

    Try this instead:

    Public Delegate Sub StringSubPointer(ByVal Buffer As String)  ' Make a delegate to transfer the telegram

    Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) _
            Handles SerialPort1.DataReceived
        Me.BeginInvoke(New StringSubPointer(AddressOf DoUpdate), SerialPort1.ReadLine)
    End Sub

    Public Sub DoUpdate(ByVal Buffer As String)
        TextBox2.Text = Buffer

        .....

    End Sub


    Everything should be made as simple as possible, but not simpler. Any fool can write code that a computer can understand. Good programmers write code that humans understand.

All Replies

  • Tuesday, November 03, 2009 1:02 PMCarsten Kanstrup Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    What are you trying to do?

    1) You use ReadExisting, but expect to receive an entire telegram (you test for Len(Rx) and compare with "000E41154A"). ReadExisting may return only one character. If you use ASCII and terminate your telegram with a fixed character like CR or LF, use ReadLine instead.

    2) You discard the output buffer in the input routine. Why?

    3) You ask how to empty the read buffer, but don't make any attempt to do so.

    4) You don't transfer any content from your read routine to the display routine. You can do two things: You can read the telegram in the eventhandler for the DataReceived event, which is recommended if you use ReadLine, and then transfer the content to the UI thread in a delegate, or you can "wake" a subroutine on the UI thread and let this routine read from SerialPort. You have made a strange mix between these two methods. Since the DataReceived event may fire at any time, you cannot expect the buffer RX to survive as you do.

    I have written a very big SerialPort tutorial, which may be helpful to you: http://www.innovatic.dk/knowledg/SerialCOM/SerialCOM.htm

    Everything should be made as simple as possible, but not simpler. Any fool can write code that a computer can understand. Good programmers write code that humans understand.
  • Tuesday, November 03, 2009 1:38 PMAngeloErre Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Thank's a lot for you interest to my question!! :-)

    Let's explain my problem.

    I have an rfid read that comunicate with computer on com port. I have to read an rfid tag by antenna and compare this tag code with a string, but when i put the tag near RFID ANTENNA, i have thist situation:

    1) Firs time i have value: 0E28E1D7L
    2) SECOND TIME            E28E1D7
    3) THIRTH TIME              0000E28E1D7
    4) FORUTH TIME             000E28E1D7 
    5) FIFTH TIME                 E28E1D7

    is this probably an buffer problem?

    thank's a lot and excuse for my english
  • Tuesday, November 03, 2009 3:14 PMCarsten Kanstrup Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    No, I don't think that it is a buffer problem. It is probably due to the way you receive.

    The most important thing og ANY communication is to have a communication protocol, which makes it possible to recognize either the beginning or the end of a telegram. If you don't have such a protocol, the slightest error may bring you totally out of synchronization (as in your case).

    First, find out if the telegrams from your RFID reader is terminated with a given ASCII character. If they are, use ReadLine and set the NewLine character to this character. Then you can marshal the received telegram to the UI thread as described in my tutorial.





    Everything should be made as simple as possible, but not simpler. Any fool can write code that a computer can understand. Good programmers write code that humans understand.
  • Tuesday, November 03, 2009 5:41 PMDick Grier Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    This all looks correct to me.  You must parse the results of the reads, and not assume anything about the content until you have a full read (and discard any data that doesn't contribute).  What is the value of the little "box symbol?"  This is the delimiter that you will use to determine a full read -- that is, everything between two "box symbols" is one read.  I might presume that this is a vbCr character (Chr(13)), but only you can tell for sure, either by documentation, or simply observing the value as you step through the code.  Parsing will be straight forward, as soon as you know the value.

    Dick
    Dick Grier, MVP. Author of Visual Basic Programmer's Guide to Serial Communications 4. See www.hardandsoftware.net.
  • Tuesday, November 03, 2009 10:45 PMAngeloErre Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Ok, thank's a lot, i have solved with this solution, obtaining 12 char value, ad it is good for me :-D...thank's a lot.

    DoUpdate()
            If Len(Rx) > 9 Then
                codicetag = Rx.Remove(0, 2)
                TextBox2.Text = codicetag


    But now i have another problem, because i have to compare runtime the value i receive from serial port with a textBox valute ..ie
    it seems do not compare nothig :-( or probably it not work in runtime?..

    WITH OLD VB6 I DOES IT SO:
    Private Sub MSComm1_OnComm()
     Dim Rx$
        Rx$ = MSComm1.Input 
    If Len(Rx$) > 9 Then
    Text2.Text = "" Text2.Text = Text2.Text & Rx$ If Rx$ = "04158229FA" Then
    Text3.Text = "ciao"
    ElseIf Rx$ = "0F02D759C4" Then
    Text3.Text = "PIZZA"

    WHI IT DO NOT WORK IN VB.NET?

        Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
          
            Rx = SerialPort1.ReadLine()
            Me.Invoke(New EventHandler(AddressOf DoUpdate))
    
        End Sub
    
        Public Sub DoUpdate()
    
            If Len(Rx) > 9 Then
                codicetag = Rx.Remove(0, 2)
                TextBox2.Text = codicetag
    
            End If
    
    If TextBox2.Text = TextBox3.Text Then Label5.Text = "DOG" ElseIf TextBox2.Text = TextBox4.Text Then Label5.Text = "HOUSE" ElseIf TextBox2.Text = TextBox5.Text Then Label5.Text = "CAT" ElseIf TextBox2.Text = TextBox6.Text Then Label5.Text = "GARDEN" ElseIf TextBox2.Text = TextBox7.Text Then Label5.Text = "CAR" ElseIf TextBox2.Text = TextBox8.Text Then Label5.Text = "--GAME OVER ---" End If end sub
  • Wednesday, November 04, 2009 7:45 AMCarsten Kanstrup Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    How have you declared RX? In VB, all strings are immutable, meaning you cannot change its length or contents once it is declared. Therefore, your code may only work once. Besides, you still expect RX to survive until DoUpdate() gets up and running. If more data are received, this may not be the case.

    Try this instead:

    Public Delegate Sub StringSubPointer(ByVal Buffer As String)  ' Make a delegate to transfer the telegram

    Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) _
            Handles SerialPort1.DataReceived
        Me.BeginInvoke(New StringSubPointer(AddressOf DoUpdate), SerialPort1.ReadLine)
    End Sub

    Public Sub DoUpdate(ByVal Buffer As String)
        TextBox2.Text = Buffer

        .....

    End Sub


    Everything should be made as simple as possible, but not simpler. Any fool can write code that a computer can understand. Good programmers write code that humans understand.