Private CommunicationInProgress as boolean = false
Private Sub DownloadParams()
SetValue("I11", "5")
While CommunicationInProgress = true
system.threading.thread.sleep(10)
End While
SetValue("I12", "3")
...
End Sub
This doesn't really end up working correctly. The app hangs for me.
Nonetheless, I ended up getting it working exactly the way I wanted to. First of all, I found that my drive was using screwy line endings. It would always reply with LF (0x0A), after you send it a message followed by CR (0x0D). Then, if it replyed with text (either the stupid ERR03, or the value I'm requesting), it would reply with "Response CR LF". So It made it awkward. So I couldn't use any of the built in SerialPort.Read* functions. Here's what I came up with:
Private Function SerialPortRead() As String
' This function attempts to properly read the serial port, and return the data.
' Drive. Always replies with {0A} first.
' Then if there is data, it is returned, followed by {0D} {0A}
Dim strData As String
' This will attempt to read the first byte. If we can't get that, then we
' should get the timeout we're looking for.
Try
strData = SerialPort1.ReadTo(Chr(&HA))
If (strData.Length > 0) Then
MsgBox("Drive returned data before initial LF:" & _
vbNewLine & ShowNonPrint(strData)) 'This should be empty. always.
End If
Catch ex As Exception
MsgBox("Coud not read to initial LF: " & vbNewLine & ex.Message)
End Try
' Now read and trim the CR LF from the remaining data.
strData = SerialPort1.ReadExisting()
If (strData.Length > 0) Then
Try
strData = strData.Substring(0, strData.Length - 2)
Catch ex As Exception
MsgBox("Serial data out of sync." & vbNewLine & vbNewLine _
& ShowNonPrint(strData))
End Try
End If
Return strData
End Function
So that works to correctly parse any data that the drive spits back. ShowNonPrint() is what I wrote to show me text, with the CR's and LF's printed out as their hex values.
I'm no longer using the SerialPort.DataReceived event at all. I was at first, but successive read functions would spit out read requests too fast, and the DataReceived handler would end up mashing all of the responses together. So here's my ReadValueFromDrive() function:
Private Function ReadValueFromDrive(ByVal strName As String) As String
Dim strData As String
SerialPort1.DiscardInBuffer()
SerialPort1.WriteLine(strName) ' write it with 0x0D at the end.
' Allow __ms for reply.
System.Threading.Thread.Sleep(My.Settings.ReadDelay)
strData = SerialPortRead()
'MsgBox("SerialPortRead returned: " & vbNewLine & ShowNonPrint(strData))
Return strData
End Function
And my WriteValueToDrive() function:
Private Function WriteValueToDrive(ByVal strName As String, ByVal strValue As String)
Dim bResult As Boolean = False
Dim strResponse As String = ""
Dim strCommand As String = strName + "=" + strValue
SerialPort1.DiscardInBuffer()
SerialPort1.WriteLine(strCommand) 'Writes the line with 0x0D ending
System.Threading.Thread.Sleep(My.Settings.WriteDelay) 'Wait 10ms for a full reply.
strResponse = SerialPortRead()
If strResponse = "" Then
' The drive just responded with a newline. so we're fine.
bResult = True
Else
bResult = False 'We must have gotten an error.
MsgBox("Response from drive after write attempt for " & strName & ": " & ShowNonPrint(strResponse))
End If
Return bResult
End Function
Now, I left generous delays in there, to ensure all the data was in the buffer before I attempted to read it. Well when doing 12 parameters (maybe more in the future), this caused the GUI to hang a lot. So I implemented the successive reads and writes in a BackgroundWorker. (I can include that code, if anyone would like me to).
I really appreciate everyone's help with this. It did end up being much more straightforward than I expected. I think I was just caught in the thought that the reads would have to be done from the Delegate, and this was really confusing me. I'm successfully able to read and write all parameters to the drive now.