Werte aus einer seriellen Schnittstelle bearbeiten

  • VB.NET

Es gibt 22 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

    Werte aus einer seriellen Schnittstelle bearbeiten

    Hallo,

    ich habe mich in letzter Zeit viel mit VB auseinandergesetzt, man muss dazu sagen bis vor ein paar Wochen hatte ich nichtmal eine Ahnung was VB ist.
    Ich muss derzeit ein Projekt machen und komme einfach nicht mehr weiter. Zum Projekt:
    Ich soll eine serielle Schnittstelle auslesen und diesen Wert dann weiterverarbeiten. Mittlerweile habe ich es hinbekommen den Wert in einer RichtTextBox darzustellen.
    Allerdings passt er noch nicht so ganz. Mit der seriellen Schnittstelle ist ein Datenlogger für Temperatur angeschlossen. Dieser lässt sich mit einfachen ASCII-Zeichen steuern. In meinem Fall ist die Taste "D" das Zeichen um die aktuelle Temperatur zu erhalten. Jetzt zu meiner Frage:
    Der Wert der aus der Schnittstelle kommt ist bspw. bei 21,45 Grad und angezeigt wird mir dann 2145. Wie kann ich zum einem ein Komma beim angezeigten Wert hinzufügen und wie kriege ich es hin das immer nur der aktuelle Wert in der RichTextBox steht?
    Ich würde mich über Hilfe freuen da ich anscheinend selber zu blöd bin.

    Mit freundlichen Grüßen



    Quellcode

    1. Public Class Form1
    2. Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    3. SerialPort1.PortName = "COM14"
    4. SerialPort1.BaudRate = 19200
    5. SerialPort1.Parity = IO.Ports.Parity.None
    6. SerialPort1.NewLine = vbCr
    7. SerialPort1.Encoding = System.Text.Encoding.UTF8
    8. SerialPort1.Open()
    9. End Sub
    10. Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    11. Me.SerialPort1.Write("D")
    12. End Sub
    13. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    14. Me.Invoke(Sub() Me.TextBox1.AppendText(Me.SerialPort1.ReadExisting))
    15. End Sub
    Wenn ich bspw. mich mit Hyperterminal mit der Schnittstelle verbinde und anschließend 3 mal D drücke erhalte ich z.B. 2145:2146:2145.
    Gibt es denn keine Funktion um der Textbox z.B. zu sagen sie soll nach zwei Zeichen ein Komma senden?
    Das mitgelieferte Programm der Firma zeigt mir den Wert auch mit Komma an.
    Wenn der Wert als Ganzzahl(wobei falsch da String) immer das hundertfache ist(also immer 2 Nachkommastellen haben sollte), kannst einfach mit String.Insert ein Komma einfügen.

    VB.NET-Quellcode

    1. Dim s As String = "1234"
    2. s = s.Insert(s.Length - 2, ",")


    Edit: Sogar doppelt falsch da 0000 nicht das hundertfache von 0 sein kann

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

    Wenn ich es mit dem Code von Nolde probiere, bekomme ich in meiner TextBox immer nur die Zahl 2 eingetragen.
    Habe ich es an der falschen Stelle eingesetzt oder muss ich etwas beachten bei einem String?

    Quellcode

    1. Public Class Form1
    2. Dim s As String = "1234"
    3. Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    4. SerialPort1.PortName = "COM14"
    5. SerialPort1.BaudRate = 19200
    6. SerialPort1.Parity = IO.Ports.Parity.None
    7. SerialPort1.NewLine = vbCr
    8. SerialPort1.Encoding = System.Text.Encoding.UTF8
    9. SerialPort1.Open()
    10. End Sub
    11. Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    12. Me.SerialPort1.Write("D")
    13. End Sub
    14. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    15. Me.Invoke(Sub() Me.TextBox1.AppendText(Me.SerialPort1.ReadExisting(s = s.Insert(s.Length - 2, ","))))
    16. End Sub
    Also du solltest schleunigst auf Option Strict On umstellen, SerialPort.ReadExisting hat eine überladung welche einen Integer als Argument haben will(index as Integer), du kloppst einen String rein. Also wie gehabt lesen(ohne Argument), den Wert einer variablen zuweisen und dann weiter...

    VB.NET-Quellcode

    1. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    2. Dim s As String = Me.SerialPort1.ReadExisting()
    3. s = s.Insert(s.Length - 2, ",")
    4. Me.Invoke(Sub() Me.TextBox1.AppendText(s))
    5. End Sub


    Um Fehlern vorzubeugen, sollte du noch prüfen ob die Länge des String auch > 2 ist, wenn bei 0 Grad z.B. 0 ausgegeben wird, würde eine Exception geworfen werden, da der String nicht lang genug ist.

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

    Option Strict On habe ich nun eingefügt.
    Ich musste bei s.Insert den Wert auf -3 stellen um 21,34 zu erhalten, bei -2 kam 2,134. Das funktioniert schonmal Super danke :)
    Wenn ich jetzt allerdings den Button öfters drücke also ca. 3 mal dann kommt immer die Fehlermeldung:
    Das angegebene Argument liegt außerhalb des gültigen Wertebereichs.
    Parametername: startIndex
    Hat diese Fehlermeldung etwas mit der String-Abfrage zu tun bzw. könnte ich damit diesen Fehler vorbeugen?
    Bei 0 Grad sendet das Gerät 0000
    @antidzn Willkommen im Forum. :thumbup:
    Temperatur ist ein numerischer Wert mit einer Einheit, nicht aber ein String. Behandle ihn also entsprechend.
    Konvertiere also den empfangenen String in einen numerischen Wert, rechne ihn in die richtige Einheit um und zeige ihn an.

    VB.NET-Quellcode

    1. Dim s As String = "1234"
    2. Dim value = CInt(s)
    3. temperature = value / 100.0
    4. Label1.Text = String.Format("{0:0.00} °C", temperature)

    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).
    VB-Fragen über PN / Konversation werden ignoriert!
    Hallo Rod,
    erstmal danke.
    Ich habe versucht deinen Lösungsvorschlag zu befolgen allerdings bekomme ich nur dauerhaft fehlermeldungen, habe ich es richtig in das Projekt eingefügt?

    Quellcode

    1. Public Class Form1
    2. Dim s As String = "1234"
    3. Dim value = CInt(s)
    4. Private Property temperature As Object
    5. Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    6. SerialPort1.PortName = "COM14"
    7. SerialPort1.BaudRate = 19200
    8. SerialPort1.Parity = IO.Ports.Parity.None
    9. SerialPort1.NewLine = vbCr
    10. SerialPort1.Encoding = System.Text.Encoding.UTF8
    11. SerialPort1.Open()
    12. End Sub
    13. Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    14. Me.SerialPort1.Write("D")
    15. End Sub
    16. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    17. Dim s As String = Me.SerialPort1.ReadExisting()
    18. Me.Invoke(Sub() Me.TextBox1.AppendText(s))
    19. temperature = value / 100.0
    20. Label1.Text = String.Format("{0:0.00} °C", temperature)
    21. End Sub

    antidzn schrieb:

    habe ich es richtig in das Projekt eingefügt?
    Du hast es richtig verstanden und deswegen falsch umgesetzt.
    Die von Dir genannten Fehler dürften vom Typ illegaler threadübergreifender Vorgang sein.
    Du kopierst Code in Dein Projekt ohne Sinn und Verstand :!: (Sorry.)
    Dim s As String = "1234" steht für einen gerade von der Schnittstelle eingelesenen String.
    Private Property temperature As Object wäre hier ein Double.
    Bei Dir hat temperature immer denselben Wert von 12.34.
    =====
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Property temperature As Double
    3. Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    4. SerialPort1.PortName = "COM14"
    5. SerialPort1.BaudRate = 19200
    6. SerialPort1.Parity = IO.Ports.Parity.None
    7. SerialPort1.NewLine = vbCr
    8. SerialPort1.Encoding = System.Text.Encoding.UTF8
    9. SerialPort1.Open()
    10. End Sub
    11. Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    12. Me.SerialPort1.Write("D")
    13. End Sub
    14. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    15. Dim s As String = Me.SerialPort1.ReadExisting()
    16. temperature = CInt(s) / 100.0
    17. Me.Invoke(Sub() Me.TextBox1.AppendText(String.Format("{0:0.00} °C", temperature)))
    18. End Sub
    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).
    VB-Fragen über PN / Konversation werden ignoriert!
    Ja der Fehler ist illegaler threadübergreifender Vorgang.
    Aber ich finde nicht heraus wie ich es deklarieren muss ohne diesen Fehler zu erhalten und auf der Hilfe Seit von Microsoft checke ich gar nichts zu dem Fehler.


    //edit
    Mittlerweile habe ich es hinbekommen ohne den Fehler.
    Allerdings wird mir als Wert immer nur 12,34 Grad angezeigt
    Hängt es mit dem String 1234 zusammen?

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

    Alles was in SerialPort1_DataReceived passiert läuft in einem anderen Thread. Die Controls aber, sind nicht in diesem Thread erstellt worden, sondern im Thread der GUI. Auf Controls/SteuerElemente greift man nur in dem Thread direkt zu in dem sie erstellen wurden, du kannst aber mit Invoke/BeginInvoke auf die Controls zugreifen, wie du es schon mit der TextBox1 gemacht hast.
    Irgendwie komme ich einfach nicht weiter sitze jetzt seit fast 3 Std. hier und versuche es irgendwie hinzubringen, finde aber auch nichts dazu im Internet. Zumindest sagt mir das ganze nichts. Es liegt immer noch daran das mir als Wert 12,34 Grad angezeigt werden. Somit weiß ich das ich das Problem mit dem double immer noch vorhanden ist. Könnte mir einer evtl einen Tipp geben?

    Quellcode

    1. Public Class Form1
    2. Dim s As String = "1234"
    3. Dim value = CInt(s)
    4. Dim temperature As Object
    5. Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    6. SerialPort1.PortName = "COM14"
    7. SerialPort1.BaudRate = 19200
    8. SerialPort1.Parity = IO.Ports.Parity.None
    9. SerialPort1.NewLine = vbCr
    10. SerialPort1.Encoding = System.Text.Encoding.UTF8
    11. SerialPort1.Open()
    12. End Sub
    13. Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    14. Me.SerialPort1.Write("D")
    15. End Sub
    16. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    17. Dim s As String = Me.SerialPort1.ReadExisting()
    18. Me.Invoke(Sub() Me.TextBox1.AppendText(s))
    19. End Sub
    20. Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
    21. temperature = value / 100.0
    22. TextBox1.Text = String.Format("{0:0.00} °C", temperature)
    23. End Sub
    Ich rate dir dringendst eines der kostenlosen Bücher über vb.net zu studieren, sonst wirst du immer wegen kleinigkeiten Stunden damit verbringen tausende von Varianten zu probieren, welche nicht funktionieren.

    Achtung der Code ist mit einer kleinen Copy&Paste-Bremse versehen.

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    3. SerialPort1.PortName = "COM14"
    4. SerialPort1.BaudRate = 19200
    5. SerialPort1.Parity = IO.Ports.Parity.None
    6. SerialPort1.NewLine = vbCr
    7. SerialPort1.Encoding = System.Text.Encoding.UTF8
    8. SerialPort1.Open()
    9. End Sub
    10. Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    11. Me.SerialPort1.Write("D")
    12. End Sub
    13. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    14. Dim temperaturStr As String = "1234"'data received through serialport
    15. Dim temperaturDbl As Double
    16. If Double.TryParse(temperaturStr, temperaturDbl) Then
    17. temperaturDbl = temperaturDbl / 100 * 100
    18. Me.Invoke(Sub() Me.TextBox1.Text = temperaturDbl.ToString())
    19. End If
    20. End Sub
    21. End Class


    Edit: Du änderst den Text der TextBox im TextBox.textChanged-Event, so wird das Event immer wieder gefeuert, du hängst also in einer dauerhaften Schleife, ist doch Unsinn oder?

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

    antidzn schrieb:

    Allerdings wird mir als Wert immer nur 12,34 Grad angezeigt
    Hängt es mit dem String 1234 zusammen?
    In Post #12 ist ein
    Spoiler
    Spoiler
    , klick da mal drauf.
    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).
    VB-Fragen über PN / Konversation werden ignoriert!
    Soo nachdem ich es endlich geschafft habe kommen nun die nächsten Fehlermeldungen :(
    Ungültige Konvertierung von der Zeichenfolge in Typ Integer.
    Ich habe bemerkt nach ein paar Messungen springt der Wert sehr merkwürdig.
    z.B. 2165:2155:2165:21:45
    Also der : kommt zu früh
    Ich habe überlegt es mit Try Catch zu verhindern weiß aber nicht ob es damit überhaupt funktioniert.

    Quellcode

    1. Public Class Form1
    2. Dim s As String = "1234"
    3. Dim value = CInt(s)
    4. Dim temperature As String
    5. Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    6. SerialPort1.PortName = "COM14"
    7. SerialPort1.BaudRate = 19200
    8. SerialPort1.Parity = IO.Ports.Parity.None
    9. SerialPort1.NewLine = vbCr
    10. SerialPort1.Encoding = System.Text.Encoding.UTF8
    11. SerialPort1.Open()
    12. End Sub
    13. Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    14. Me.SerialPort1.Write("D")
    15. End Sub
    16. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    17. s = Me.SerialPort1.ReadExisting()
    18. value = CInt(s.Replace(":", ""))
    19. Me.Invoke(Sub() Me.TextBox1.AppendText(s))
    20. End Sub
    21. Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
    22. temperature = value / 100.0
    23. TextBox1.Text = String.Format("{0:0.00} °C", temperature)
    24. End Sub
    @antidzn Ich bin dann mal draußen.
    So was von Beratungsresistenz und Leseschwäche ist mir schon lange nicht mehr untergekommen. X(

    antidzn schrieb:

    VB.NET-Quellcode

    1. Dim temperature As String

    RodFromGermany schrieb:

    VB.NET-Quellcode

    1. Private Property temperature As Double
    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).
    VB-Fragen über PN / Konversation werden ignoriert!