Serialport Stream

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

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

    Um nochmal zu verdeutlichen was @Takafusa meint.

    VB.NET-Quellcode

    1. If SP1.BytesToRead > 0 Then
    2. Dim b(SP1.BytesToRead-1) As Byte
    3. txtBarcode.Text = SP1.Read(b, 0, b.Length).ToString
    4. End If

    Das ToString verstehe jetzt aber nicht, du wolltest doch die Bytes haben, jetzt hast du sie und machst was?
    Du schreibst in txtBarcode die die Anzahl der gelesenen Bytes rein. :?: :?: :?:
    Lese das mal durch, da steht jede Menge informativer Kram drin.
    Naja .Read sagte man mir ja sind die Bytes. Post 34
    Dass die Methode die Anzahl der Bytes wiedergibt, macht für mich wenig Sinn, da Takafusa ja sagt die Anzahl der Bytes muss ich als Argument übergeben.
    Die Text-Eigenschaft ist ein String habs nur deswegen umgewandelt. Ich dachte der Integer wäre der Byte-Wert im Dezimalsystem

    Meinetwegen auch so, wo ichs mir angucke ist in diesem Fall ja egal. Ich geh mal schwer davon aus der Buffer darf ruhig größer sein? Angenommen da kommen ne ganze Menge an Bytes, dann sollte der Buffer wohl auch entsprechend kleiner sein dürfen. Für sowas ist der nur da, um große Datenmengen in kleinere Pakete zu teilen oder? Zumindest isses so bei den Streams

    VB.NET-Quellcode

    1. Dim hold as Integer
    2. If Sp1.BytesToRead > 0 Then
    3. Dim b(1023) as Byte
    4. hold = SP1.Read(b, 0, SP1.BytesToRead)
    5. End If


    "Liest eine Anzahl von Bytes aus dem SerialPort-Eingabepuffer und schreibt diese Bytes am angegebenen Offset in ein Bytearray"

    Was bedeutet denn "am Offset schreiben"?

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

    Wenn du nun die Bytes zuu einem String machen willst:(Encoding beachten)

    VB.NET-Quellcode

    1. Dim b() As Byte = {&H48, &H61, &H75, &H64, &H72, &H75, &H66, &H65, &H72, &H7A, &H61, &H70, &H70, &H65, &H6C, &H74, &H6E, &H6F, &H63, &H68}
    2. Dim x As String = System.Text.Encoding.ASCII.GetString(b, 0, b.Length())
    3. MessageBox.Show(x)

    Haudruferzappeltnoch schrieb:

    Und kann man das irgendwie veranschaulichen mit den Bytes dem Buffer.
    Ich meine warum will ich das denn an unterschiedlichen Stellen im Buffer haben?

    Da gibt es 1001 Szenarien in denen man gebrauchen könnte.
    Das ist dann aber nur für diejenigen interessant die sich mit den Port auskennen und komplexere Verarbeitungssysteme haben.
    Für deine Skills reicht es vorerst zu wissen wo was hin geschrieben wird.
    Und irgendwie bist du schon wieder bei Strings, du wolltest doch die Bytes und die stehen eben in deinem Buffer b(), beginnend bei 0 (dem Offset).
    Wo ist denn jetzt konkret dein Problem?
    Oder betreiben wir hier Konversation über die Aufzucht und Hege des SerialPorts?

    Naifu schrieb:

    die stehen eben in deinem Buffer b()

    Das hier wusste ich zum Beispiel nicht. Dann macht das auch Sinn mit dem Offset.
    Und die Read-Methode füllt den Buffer dann. Ich dachte der Buffer hilft nur beim Auslesen

    Dann hätte ich noch eine Frage zum ReadExisting. Da steht in der Doku "liest alle Bytes im Stream und im Eingabepuffer des SerialPort".
    Wann stehen denn die Daten im Eingabepuffer und wann im Stream?

    Haudruferzappeltnoch schrieb:

    Wann stehen denn die Daten im Eingabepuffer und wann im Stream?

    Warum interessiert dich das?
    ReadExisting, ließt eben alles was zu bekommen ist.
    Aber dann sind wir ja wieder bei String, was du nicht wolltest.

    Haudruferzappeltnoch schrieb:

    warum will ich das denn an unterschiedlichen Stellen im Buffer haben?
    Beispiel:
    Es wird ein Bild übertragen in Häppchen zu 1000 Byte.
    Wenn das Bild 1000000 Byte lang ist, hast Du 1000 Übertragungen á 1000 Byte.
    Und jedes Häppchen muss unmittelbar auf das vorherige Häppchen in den Zielspeicher eingetragen werden, damit das Format noch stimmt.
    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!
    @Naifu
    Mich interessierts, weil ich nicht weiß was der Eingabepuffers eines Serialports ist und was der BaseStream.
    Da mindestens eins von diesen Wörtern in jeder Beschreibung vorkommt in der Microsoft Doku des Serialports, die du auch verlinkt hast, wäre das schon relevant denke ich sonst kann ich da doch nichts mit anfangen.
    @Haudruferzappeltnoch So ad hoc weiß ich das auch nicht zu klären.
    Hast Du mal einen Link, wo beide Begriffe vorkommen?
    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!
    SerialPort
    Jede Methode benutzt diese Begriffe in der Erklärung. ReadExisting benutzt beide wie oben zitiert Post 47

    Dort ist folgender Hinweis zu finden:
    "The SerialPort class buffers data, but the stream object contained in the SerialPort.BaseStream property does not. Therefore, the SerialPort object and the stream object might differ on the number of bytes that are available to read. When bytes are buffered to the SerialPort object, the BytesToRead property includes these bytes in its value; however, these bytes might not be accessible to the stream contained in the BaseStream property"

    Da steht BaseStream und Eingabepuffer können unterschiedliche Mengen an Bytes haben. Aber kein Beispiel.
    Die BytesToRead Eigenschaft scheint beide Werte zu summieren, wenn Bytes gebuffert werden.
    @Haudruferzappeltnoch AHa.
    SerialPort.BaseStream ist für andere Klasse gedacht, wenn die einen Stream übergeben bekommen wollen.
    Für Dich ist der (gegenwärtig) uninteressant, lass ihn einfach links liegen. ;)
    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!
    Habe hier einen Beispielcode der etwas tut was ich nicht verstehe. Ich versuche so stumpf wie möglich den Input(gescannter Barcode) zu lesen.

    VB.NET-Quellcode

    1. Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SP1.DataReceived
    2. If SP1.BytesToRead > 0 Then
    3. Debug.WriteLine(SP1.BytesToRead)
    4. Dim b(SP1.BytesToRead) As Byte
    5. SP1.Read(b, 0, SP1.BytesToRead)
    6. Debug.WriteLine(String.Join("", b))
    7. End If
    8. End Sub

    Nach zweimal den gleichen Barcode scannen steht in der Ausgabe:

    Quellcode

    1. 14
    2. 48495352485748484950484848500
    3. 8
    4. 48495352485748484950484848500


    Also BytesToRead wird weniger beim zweiten Mal, aber im Array b steht weiterhin dasselbe und vor allem mehr Bytes als BytesToRead sagt.
    @Haudruferzappeltnoch Keine Ahnung.
    Wenn das DataReceived-Event kommt, sind Daten verfügbar, da musst Du nicht die Anzahl der verfügbaren Bytes abfragen.
    Da der Scanner einen Text sendet, solltest Du auch mit den String- nicht aber mit Byte-Methoden des SerialPorts arbeiten:
    SerialPort.ReadExisting() docs.microsoft.com/de-de/dotne…?view=dotnet-plat-ext-6.0
    Da Deine Strings mit 00 enden (das ist die C-String-Ende-Kennung) solltest Du diese noch abschneiden:

    VB.NET-Quellcode

    1. Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SP1.DataReceived
    2. Dim txt = SP1.ReadExisting()
    3. Debug.WriteLine(txt)
    4. End Sub
    und feddich.
    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!
    Wenn ReceivedBytesThreshold = 1 ist dann wird der Event beim ersten Byte gefeuert.
    Der Rest trudelt dann noch ein.
    Nach deinem Debug.WriteLine sind alle angekommen und deshalb funz es.
    Also entweder so wie @RodFromGermany gezeigt hat.
    Oder eben so:

    VB.NET-Quellcode

    1. Dim txt As String = System.Text.Encoding.ASCII.GetString(b).TrimEnd(vbNullChar)

    BTW Dein Array ist zu groß.
    Danke euch, ich kann noch nicht ganz aufdröseln was genau der Unterschied zwischen den Scans ist. Nach dem ersten Event macht er da denn irgendwas mit dem ReceivedBytesThreshold?

    Was heißt mein Array ist zu groß, macht das Probleme? Oder meinst du nur das sollte b(SP1.BytesToRead - 1) sein? Ich denke daher kommt die 0 dann am Ende. Ich hab es so verstanden die Puffergröße ist nicht so relevant, solange sie klein ist.

    Kann das auch dieses Problem verursachen? Ich werde es nochmal versuchen morgen.
    Mit dem ReadExisting habe ich angefangen. Da bekam ich auch ein Problem, deshalb wollte ich es mir so wie oben nochmal anschauen. Ich werde auch das Problem dann evtl. nochmal reproduzieren

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

    Haudruferzappeltnoch schrieb:

    b(SP1.BytesToRead - 1)
    Das ist leider in VB.NET so, da alte BASIC-Versionen 1 als Startindex haben.
    Deshalb legt VB.NET die Arrays um ein Element größer an, damit alte Algotithmen da laufen.
    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 nochmal bitte zum Verständnis, ReadExisting funktioniert bedingt.

    VB.NET-Quellcode

    1. Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SP1.DataReceived
    2. If SP1.BytesToRead > 0 Then
    3. Debug.WriteLine(SP1.BytesToRead)
    4. Dim str As String = SP1.ReadExisting
    5. Debug.WriteLine(str)
    6. End If
    7. End Sub
    8. 'Ausgabe Scan1:
    9. '14
    10. '01540900120002
    11. 'Ausgabe Scan2:
    12. '9
    13. '01540900120002

    Aber ohne BytesToRead Abfrage wieder Käse (entspricht Post 55 und das meinte ich das hätte ich versucht, nur komisch dass es mit BytesToRead funktioniert):

    VB.NET-Quellcode

    1. Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SP1.DataReceived
    2. If SP1.BytesToRead > 0 Then
    3. 'Debug.WriteLine(SP1.BytesToRead)
    4. Dim str As String = SP1.ReadExisting
    5. Debug.WriteLine(str)
    6. End If
    7. End Sub
    8. 'Ausgabe Scan 1:
    9. '01540900120002
    10. 'Ausgabe Scan 2:
    11. '015409001
    12. '20002

    Der liest da einfach den Code in zwei getrennten Abschnitten beim zweiten Scan. In der Exe macht er natürlich nur den Murks, da gibts ja keine Debugger-Ausgabe

    Das hier funktioniert in der exe da gibt es ein zeitliches Problem. Das Lesen geht zu schnell oder so interpretiere ich das zumindest:

    VB.NET-Quellcode

    1. Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SP1.DataReceived
    2. If SP1.BytesToRead > 0 Then
    3. Threading.Thread.Sleep(1)
    4. Dim str As String = SP1.ReadExisting
    5. Show(str)
    6. End If
    7. End Sub

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

    Haudruferzappeltnoch schrieb:

    Threading.Thread.Sleep(1)
    ist eventuell schlecht, da dieser Thread angehalten wird.
    Probier mal, ob Task.Wait() besser funktioniert.
    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!