Serialport Stream

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 72 Antworten in diesem Thema. Der letzte Beitrag () ist von Haudruferzappeltnoch.

    Definiere

    Haudruferzappeltnoch schrieb:

    auf die Daten gucken
    Du kannst eine Gegenstelle implementieren und einfach ohne Event in einem Timer-Tick- oder Button-Click-Event die vorhandenen Dagten auslesen wie auch immer (Bytes oder String) und Dir ansehen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Also wenn ich per Button-Klick jetzt meinen Serialport abfrage mit BytesToRead, sagt er 0. Ok das verstehe ich.
    Jetzt schicke ich ihm ein Signal (das kann von der Gegenstelle ausgehend schon ein String sein?), dann ist BytesToRead nicht mehr 0.
    ReadExisting gibt mir dieses Signal und ChrW(26) das Eof Zeichen. Aber das Eof-Zeichen hat die Gegenstelle auch geschickt.
    Ist das soweit korrekt?

    Was ist wenn der Port kein ChrW(26) bekommt? Bleibt BytesToRead dann 0? Oder wird da endlos weitergelesen?

    Das wollte ich quasi per Try and Error nachgucken.
    Das EOF-Zeichen heißt: »Ich als Gerät-am-anderen-Ende habe Dir momentan nix mehr zu sagen.« Das ist wie das Klischee-"Over" bei Funkgerätgesprächen. Solange der eine nicht "Over" sagt, heißt das für den anderen, dass der eine noch was sagen will. Wenn das Gerät also warumauchimmer kein Signal bekommt, hat es auch keinen Grund, der SerialPort-Endstelle, also quasi Deinem Programm eine Antwort zu erteilen. Und ohne Antwort kein EOF-Signal. Wenn das Gerät aber ungültige Daten bekommt, also diese nicht verarbeiten kann, sollte es dies auch dem Programm mitteilen, natürlich gefolgt von einem EOF-Signal. Das ist aber eine Spezifikationsfrage des Geräts, also siehe Gerätedoku.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Haudruferzappeltnoch schrieb:

    (das kann von der Gegenstelle ausgehend schon ein String sein?)
    Das sollte in der Beschreibung der Gegenstelle stehen.
    Das nennt sich Übertragungsprotokoll.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Haudruferzappeltnoch schrieb:

    Wann bekommt das Gerät denn selbst ein Signal in diesem Prozess?
    Wenn Du das programmtechnisch organisierst.
    Oder ist das bloß ein Sender aber kein Empfänger?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Haudruferzappeltnoch schrieb:

    Das Gerät sendet doch das Signal? Wann bekommt das Gerät denn selbst ein Signal in diesem Prozess?
    Dann ist folgende Aussage von Dir für mich nicht erklärbar:

    Haudruferzappeltnoch schrieb:

    Jetzt schicke ich ihm ein Signal
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Mit "ihm" meinte ich den Serialport.
    Das Gerät ist nur passiv im Ablauf. Das kann meinetwegen sein was will. Hauptsache es gibt seriell lesbaren Strom aufs Kabel. Das sind aber immer Bytes hätte ich gedacht, gut wenn die Bytes als String konvertierbar sind dann sind das Strings, so meint ihr das oder?

    Also ich weiß nicht wie das EoF repräsentiert wird, aber sagen wir das ist ein volles Byte "11111111"
    Dann schickt die Gegenstelle etwas das mir BytesToRead = 1 gibt, dann wäre das bsp. "0101101011111111" Weil das Eof angehangen wird.

    Aber was macht der Serialport wenn nur "01011010" einläuft, also kein eof und trotzdem daten?

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Achsooo …

    Haudruferzappeltnoch schrieb:

    Was ist wenn der Port kein ChrW(26) bekommt? Bleibt BytesToRead dann 0? Oder wird da endlos weitergelesen?
    Wenn der Port kein ChrW(26) bekommt, bekommt er (wohl) auch kein EOF-Signal. Daher wird der Port weiterhin warten, bis was kommt. Und BytesToRead müsste dementsprechend auch 0 bleiben.
    Ich frag mich nur gerade: Kannst Du all die Sachen nicht vor Ort testen?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Haudruferzappeltnoch schrieb:

    Das sind aber immer Bytes hätte ich gedacht
    In der untersten Ebene des Systems gehen da ausschließlich Bytes aufs Kabel.
    Höhere Programmiersprachen (z.B. .NET) machen dann daraus ggf. Strings, wenn mit Encoding und den Strring-Methoden gearbeitet wird.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Haudruferzappeltnoch
    Guck dir das mal an.
    Da sind noch ein paar Sachen drin die überarbeitet werden müssten, aber nix was das Serialport betrifft. (Denke ich)
    Wenn du wissen willst was das für Bytes sind, wandele den String halt um.

    VB.NET-Quellcode

    1. ​Public Class Form1
    2. ' Das Delegat muss die selbe Signature haben
    3. Delegate Sub TextBoxCallback(ByVal text As String)
    4. Private WithEvents myComPort As IO.Ports.SerialPort
    5. ' Bei den meisten Geräten ist ein Abschlußzeichen erforderlich, meistens
    6. ' wird ChrW(13) oder ChrW(10) oder beide benötigt
    7. ' - Wählt was eure Gegenstelle benötigt:
    8. ' Private EndOfCommand As String = Constants.vbCr.ToString
    9. ' Private EndOfCommand As String = Constants.vbLf.ToString
    10. Private EndOfCommand As String = Constants.vbCrLf.ToString
    11. Private Sub Form1_Load(ByVal sender As System.Object, _
    12. ByVal e As System.EventArgs) Handles MyBase.Load
    13. ' Mal nachschauen, ob es hier SerialPorts gibt
    14. Dim str() As String = IO.Ports.SerialPort.GetPortNames()
    15. ' Wenn nein, dann beenden:
    16. If str.Length = 0 Then
    17. MsgBox("No Serialport available!", MsgBoxStyle.Critical)
    18. Me.Close()
    19. End If
    20. ' Eine Instance von SerialPort erstellen
    21. ' Im Normalfall ist das COM1:
    22. Me.myComPort = New IO.Ports.SerialPort(str(0))
    23. ' Die folgenden vier Einstellungen müssen denen der
    24. ' Gegenstelle entsprechen
    25. Me.myComPort.BaudRate = 9600
    26. Me.myComPort.DataBits = 8
    27. Me.myComPort.StopBits = IO.Ports.StopBits.One
    28. Me.myComPort.Parity = IO.Ports.Parity.None
    29. ' Wichtig! Hier wird eingestellt nach wieviel Bytes im Eingangspuffer
    30. ' das DataReceived Event gefeuert wird
    31. Me.myComPort.ReceivedBytesThreshold = 1
    32. ' Und nun öffnen wir den Port
    33. Me.myComPort.Open()
    34. End Sub
    35. ''' <summary>
    36. ''' Wird ausgelöst wenn die Comm die in ReceivedBytesThreshold eingestellte
    37. ''' Anzahl Bytes empfangen hat
    38. ''' </summary>
    39. Private Sub myComPort_DataReceived( _
    40. ByVal sender As Object, _
    41. ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _
    42. Handles myComPort.DataReceived
    43. Select Case e.EventType
    44. Case IO.Ports.SerialData.Chars
    45. ' Ein Zeichen wurde empfangen und im Eingabepuffer platziert.
    46. Case IO.Ports.SerialData.Eof
    47. ' Das Dateiendezeichen wurde empfangen und im
    48. ' Eingabepuffer platziert.
    49. End Select
    50. Dim msg As String = Me.myComPort.ReadExisting
    51. Me.ShowText(msg)
    52. End Sub
    53. ''' <summary>
    54. ''' Wird ausgelöst wenn sich die Steuerleitungen geändert haben
    55. ''' </summary>
    56. Private Sub myComPort_PinChanged(ByVal sender As Object, ByVal e As _
    57. System.IO.Ports.SerialPinChangedEventArgs) Handles myComPort.PinChanged
    58. Select Case e.EventType
    59. Case IO.Ports.SerialPinChange.Break
    60. ' Bei der Eingabe wurde ein "break" erkannt.
    61. Case IO.Ports.SerialPinChange.CDChanged
    62. ' Der Zustand des CD-Signals (Carrier Detect) hat sich geändert.
    63. ' Mit diesem Signal wird angezeigt, ob ein Modem mit einer
    64. ' Telefonleitung verbunden ist und ein Datenträgersignal
    65. ' erkannt wurde.
    66. Case IO.Ports.SerialPinChange.CtsChanged
    67. ' Der Zustand des CTS-Signals (Clear to Send) hat sich geändert.
    68. ' Mit diesem Signal wird angegeben, ob Daten über den seriellen
    69. ' Anschluss gesendet werden können.
    70. Case IO.Ports.SerialPinChange.DsrChanged
    71. ' Zustand des DSR-Signals (Data Set Ready) hat sich geändert.
    72. ' Mit diesem Signal wird angezeigt, ob das Gerät am seriellen
    73. ' Anschluss betriebsbereit ist.
    74. Case IO.Ports.SerialPinChange.Ring
    75. 'Ein Ringindikator wurde erkannt.
    76. End Select
    77. End Sub
    78. ''' <summary>
    79. ''' Wird ausgelöst wenn ein Fehler in der Übertragung endeckt wurde
    80. ''' </summary>
    81. Private Sub myComPort_ErrorReceived( _
    82. ByVal sender As Object, _
    83. ByVal e As System.IO.Ports.SerialErrorReceivedEventArgs) _
    84. Handles myComPort.ErrorReceived
    85. Select Case e.EventType
    86. Case IO.Ports.SerialError.Frame
    87. ' Die Hardware hat einen Rahmenfehler erkannt.
    88. Case IO.Ports.SerialError.Overrun
    89. ' Ein Zeichenpufferüberlauf ist aufgetreten. Das nächste
    90. ' Zeichen geht verloren.
    91. Case IO.Ports.SerialError.RXOver
    92. ' Ein Eingabepufferüberlauf ist aufgetreten.
    93. ' Die Kapazität des Eingabepuffers ist erschöpft,
    94. ' oder es wurde ein Zeichen nach dem Dateiendezeichen
    95. ' (EOF, end-of-file) empfangen.
    96. Case IO.Ports.SerialError.RXParity
    97. ' Die Hardware hat einen Paritätsfehler erkannt.
    98. Case IO.Ports.SerialError.TXFull
    99. ' Die Anwendung hat versucht, ein Zeichen zu übertragen, aber
    100. ' die Kapazität des Ausgabepuffers war erschöpft.
    101. End Select
    102. Me.ShowText("ERROR" & vbCrLf)
    103. End Sub
    104. ''' <summary>
    105. ''' Da die Daten aus einem anderem Thread kommen müssen wir die Ausgabe
    106. ''' über Invoke machen
    107. ''' </summary>
    108. Private Sub ShowText(ByVal text As String)
    109. If Me.TextBox1.InvokeRequired Then
    110. Dim d As New TextBoxCallback(AddressOf ShowText)
    111. Me.Invoke(d, New Object() {text})
    112. Else
    113. Me.TextBox1.Text = Me.TextBox1.Text & text
    114. End If
    115. End Sub
    116. ''' <summary>
    117. ''' Hier wird der Command zusammengesetzt und versendet
    118. ''' </summary>
    119. ''' <param name="command"></param>
    120. ''' <remarks></remarks>
    121. Private Sub Send(ByVal command As String)
    122. Me.myComPort.Write(command & Me.EndOfCommand)
    123. End Sub
    124. Private Sub Button1_Click(ByVal sender As System.Object, _
    125. ByVal e As System.EventArgs) Handles Button1.Click
    126. Me.Send("Ein Befehl, den die Gegenstelle kennt!")
    127. End Sub
    128. End Class

    Naifu schrieb:

    Wenn du wissen willst was das für Bytes sind, wandele den String halt um.
    Was soll das?
    Mit dem falschen Encoding geht das vor die Hose.
    Wenn er die Bytes haben will, liest er sie mit Public Function Read (buffer As Byte(), offset As Integer, count As Integer) As Integer aus.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    Stimmt, das hättet Ihr @Haudruferzappeltnoch aber auch schon vor dreißig Posts mittelten können.
    Abgesehen davon, die meisten Gegenstellen senden ASCII oder Binärdaten mit Protokoll. Dann geht das mit dem String eh in die Hose.
    Also, was soll was?

    Naifu schrieb:

    Stimmt, das hättet Ihr @Haudruferzappeltnoch aber auch schon vor dreißig Posts mittelten können.


    Ich hab im aufgefordert mal im ObjectBrowser mal nach den SerialPort zu schauen, allein das lesen der MethodenNamen hätte ihm klargemacht, das mehr möglich ist. Kam aber nicht sweiter zu, weder ob er das mal getan hat oder nicht, ich glaube aber weniger dran, denn dann hätte er wohl weitere Fragen gehabt.
    Tatsächlich wurde ja bereits die ReadToEnd und CopyTo Methode vorgeschlagen gleich zu Anfang, hab ich probiert, hat sich aufgehangen. Das hab ich soweit geschrieben
    .Read Methode hatte ich selbst auch probiert, hat sich auch aufgehangen. Dachte das wird das gleiche Problem sein, daher nicht mehr erwähnt.
    Dadurch sind wir hier gelandet. Weil ich gefragt hab was da wohl passieren mag.
    Also ReadExisting geht ja, kann es sein, dass man mit den Parameter bei .Read noch bestimmte Fälle abdecken muss?
    In dem Programmsnippet was ich schon nutze Post 15, habe ich ja auch die Read Methode drin, da geht es auch. Aber auch da hängt es sich manchmal! auf wenn ich den komischen Sleep nicht drin hab.

    Also ja ich weiß es nunmal nicht, was da der Knackpunkt ist deswegen frag ich.

    Haudruferzappeltnoch schrieb:

    hat sich aufgehangen.
    Kannst Du das mal etwas näher beschreiben?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    1. Ich mach nen ComPort ready, mit Baudrate etc.
    2. Button.Click mal reingucken; prüft erst BytesToRead. Die sind 0 also nix da, super
    3. Jetzt sendet die Gegenstelle
    4. Button.Click wieder gucken, BytesToRead nicht 0 also geht er weiter,
    -mit ReadExisting, krieg ich genau das raus was ich soweit hier verstanden habe
    -mit allen anderen Methoden steppt der Debugger da rein und verschwindet. Das Programm reagiert nicht mehr.

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. If SP1.BytesToRead > 0 Then
    3. txtBarcode.Text = SP1.ReadExisting()
    4. End If
    5. End Sub


    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. If SP1.BytesToRead > 0 Then
    3. Dim b(1023) As Byte
    4. txtBarcode.Text = SP1.Read(b, 0, b.Length).ToString 'hier hatte ich auch ReadToEnd oder CopyTo probiert mit dem BaseStream, ist ja immer noch die Frage wann da was drin ist und wie sich der zu dieser Methode unterscheidet
    5. End If
    6. End Sub

    Haudruferzappeltnoch schrieb:

    Das Programm reagiert nicht mehr.


    Der GUI Thread ist blockiert, du willst mehr lesen als da ist, also hängste in dieser Zeile fest, lege den Byte array so groß an wie du ihn brauchst(SP1.BytesToRead hat den Wert ja), und lese nur so viele wie auch da. Kannst auch einen größeren Buffer nehmen, aber lese nur so viel wie da. Ein SP hat auch Properties, im Objectbrowser wäre das sichtbar gewesen, wenn du einen SerialPort aus der ToolBox auf Form ziehst, und dann im Eigenschaftenfenster schaust, ReadTimeout, WriteTimeout default beides -1, steht für Endlos, kannste aber festlegen, aber dann würde eine Exception geworfen, wenn nicht ausreichend gelesen werden konnte.

    Ich erwähnte ja schon das ich Threads verwende, wenn ein Nebenthread kontrolliert festhängt(endlessloop +boolean flag zum verlassen(immer nur lesen was da ist), oder mit async/await arbeiten) kein Thema, alles reagiert weiterhin wunderbar.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Takafusa“ ()