locked
Serial communication problem reading single charactor. PLEASE HELP!!!! RRS feed

  • Question

  • I've posted a few messages regarding my trials and tribulations reading data in from a serial device.  I've just about finished working through this - but have the following major roadblock. 

     

    I'm working with an application that sends and receives data from another pc.  I've been tasked with the duty of making sure that the other PC is ready to receive information.  The method chosen may not be the best - but it is what it is. 

     

    The application I'm working with uses a routine called SendCommand(command as string) to send a message to the other PC to handle an operational request.   Sending the message is easy enough - the problem lies in trying to process the return message.  All previous return messages received from the other PC always have a carriage return and line feed (in that order) as a means of showing the message is complete and to process it.  This new "check" that we are trying to implement works like this:

     

    My VB application sends the control SYN (chr(22)) character.

    In response, one of three things will happen from the other pc:

    1.) it will immediately respond with string "$" (with no carriage return or line feed) - meaning it is ready to receive.

    2.) it will respond with string "%" (with no carriage return or line feed) - meaning it is not ready to receive.

    3.) it will send nothing (meaning the RS-232 link is down) - not likely - but should be considered

     

    The problem lies within the existing code (I think...) because it expects all messages to end with a carriage return and line feed.  Here is that part of the code:

     

    Code Snippet

    Private Sub DataAvailable(ByVal sender As Object, ByVal e As EventArgs) Handles Serial.DataAvailable

    Dim BytesIn As Integer = Serial.Available

    ''Serial.Available = Public Overrides ReadOnly Property Available() As Integer

    ''Member of: Sax.Communications.SerialConnection

    Dim SingleChunk(BytesIn - 1) As Byte

    Dim Index As Integer

    Dim ThisCharactor As Char

    ' Protect the Buffer to stop other threads writing to it

    Serial.Read(SingleChunk, 0, BytesIn)

    '' Serial.Read = Public Overrides Function Read(ByVal buffer() As Byte, ByVal offset  ''As Integer, ByVal count As Integer) As Integer

    ''Member of: Sax.Communications.SerialConnection

     

     

    For Index = 0 To (BytesIn - 1)

    ThisCharactor = Chr(SingleChunk(Index))

    If ThisCharactor = Chr(10) Then

    If SerialBuffer = "+OK" Then ' the message sent was recieved ok

    TransmittedOK = True

    ResultEvent.Set()

    MainForm.DebugInfo.AddToLog(SerialBuffer)

    ElseIf SerialBuffer = "-CHK" Then ' transmission checksum error, send again

    TransmittedOK = False

    ResultEvent.Set()

    AddProgress("Checksum error")

    MainForm.DebugInfo.AddToLog(SerialBuffer)

    Else ' message to be processed by the main app.

    InstructionList.Items.Add(SerialBuffer)

    End If

    SerialBuffer = ""

    ElseIf SingleChunk(Index) >= 32 Then ' add the charactor to the incomming data buffer

    SerialBuffer = SerialBuffer & ThisCharactor

    End If

    Next Index

    End Sub

     

    So, how do I write a condition that only deals with the "$", "%", or nothing scenario listed above?  ANY HELP WITH THIS WOULD BE VERY MUCH APPRECIATED!

     

    Thanks,

    javasource

    Monday, July 23, 2007 3:07 PM

Answers

  • Just add a boolean member to your class that indicates what kind of response you're expecting.  Something like Private mQueryingReady As Boolean.  Set it to True when you send SYN, false when you send regular commands.  DataAvailable() can then use the flag to interpret the expected response.  Start a Timer when you send to detect a problem with the connection.

    BTW: your code in DataAvailable() is wrong.  Serial.Read() will return anywhere between 1 and "BytesIn" bytes.  It will work in the debugger but not when deployed.  You'll have to add code that can detect when the full response is received.  In your case: look for cr/lf when mQueryingReady is false.
    Monday, July 23, 2007 3:19 PM
  • The solution to this problem took a bit of experimenting...

     

    I created a Sub to send the message to the other app.  I start a timer at this point - as their is no need sending the next message down the line until the right condition has been met.

     

      I ended up creating a Select Case statement that checks the incoming data.  Using the Boolean value as recommended caused some major hang-ups, as the order of incoming messages was indeterminate.  I decided to stay clear of it.  Instead, any unprocessed messages that are RECEIVED get stored in a listbox.  THey in turn, are processed as they are received.  Once the appropriate character is returned from the othe pc, I stop the timer.  This way, the next message can be sent - and I haven't loaded the other receive buffer with data it might not be able to process.

     

    In retrospect, the solution seemed pretty easy.  Thanks for the responses, if anything they helped open my mind to new possibilities.

    Wednesday, August 8, 2007 4:11 PM

All replies

  • Just add a boolean member to your class that indicates what kind of response you're expecting.  Something like Private mQueryingReady As Boolean.  Set it to True when you send SYN, false when you send regular commands.  DataAvailable() can then use the flag to interpret the expected response.  Start a Timer when you send to detect a problem with the connection.

    BTW: your code in DataAvailable() is wrong.  Serial.Read() will return anywhere between 1 and "BytesIn" bytes.  It will work in the debugger but not when deployed.  You'll have to add code that can detect when the full response is received.  In your case: look for cr/lf when mQueryingReady is false.
    Monday, July 23, 2007 3:19 PM
  • nobugz,

     

    Thank you so much for the incredibly quick response...

     

    fyi - this code is not mine.  In fact, I'm not really a VB guy - been asked to do this because I've some computer programming experience.  I've put myself though a ton of reading and instructional videos this last few months - but I'm still a 'newbie' in the VB world...

     

    I've another post at: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1880149&SiteID=1 that shows the entire Serial form code.  Could you look at that post?

     

    I hate to even ask, but could you actually show me how to do this?  I've experimented with this over the last week - trying everything I can muster up...

     

    Thanks again!

     

    javasource

     

     

     

    Monday, July 23, 2007 3:47 PM
  • You're asking too much.  We can help you get unstuck.  Writing the app is your job.  Just post back when you have a specific question or problem.
    Monday, July 23, 2007 4:17 PM
  • Sounds fair.. just so frustrated with this problem... that's all.

     

    First question:  How is the DataAvailable() code wrong?  Curiously, this has worked just fine in deployment... and you have me really curious now.  You said, "Serial.Read() will return anywhere between 1 and "BytesIn" Bytes.  Could you give an example as to where this is wrong?

     

    Thanks,

    javasource

    Monday, July 23, 2007 4:34 PM
  • Second question, do you mean to use the timer to resend until I receive the specific result I'm expecting (in this case, "$", "%", or nothing?  Or do you mean something else?

     

     

    Monday, July 23, 2007 4:42 PM
  • The solution to this problem took a bit of experimenting...

     

    I created a Sub to send the message to the other app.  I start a timer at this point - as their is no need sending the next message down the line until the right condition has been met.

     

      I ended up creating a Select Case statement that checks the incoming data.  Using the Boolean value as recommended caused some major hang-ups, as the order of incoming messages was indeterminate.  I decided to stay clear of it.  Instead, any unprocessed messages that are RECEIVED get stored in a listbox.  THey in turn, are processed as they are received.  Once the appropriate character is returned from the othe pc, I stop the timer.  This way, the next message can be sent - and I haven't loaded the other receive buffer with data it might not be able to process.

     

    In retrospect, the solution seemed pretty easy.  Thanks for the responses, if anything they helped open my mind to new possibilities.

    Wednesday, August 8, 2007 4:11 PM