per klick auf werte von com port zugreifen

  • VB.NET

Es gibt 21 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    per klick auf werte von com port zugreifen

    Hallo liebe VB-Gemeinde,

    Ich bin ein wenig "grün" mit dem Thema VB Programmierung und komm leider nicht auf die richtige Befehlskette für mein Vorhaben.
    Mein Ziel ist es Messdaten mittels Comm Port auszulesen per Ereignis (Tastatur oder Button Klick)
    Ich erhalte zwar schon Messdaten wenn ich selber auf die Messuhren klicke aber ich möchte das über die Software machen.
    Ich denke ich muss sowas wie ein "gib mir die aktuellen Messdaten" an die Messuhren senden allerdings komm ich genau da nicht weiter...
    Ich hoffe ihr habt vielleicht eine Idee wie ich das ansteuern kann.

    Hier mein bisheriger Code:

    VB.NET-Quellcode

    1. Imports System
    2. Imports System.Threading
    3. Imports System.IO.Ports
    4. Imports System.ComponentModel
    5. Public Class Form1
    6. Dim myPort1 As Array
    7. Dim myPort2 As Array
    8. Delegate Sub SetTextCallback(ByVal [text] As String)
    9. 'definieren der Ports per DropDown
    10. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    11. myPort1 = IO.Ports.SerialPort.GetPortNames()
    12. ComboBox1.Items.AddRange(myPort1)
    13. myPort2 = IO.Ports.SerialPort.GetPortNames()
    14. ComboBox2.Items.AddRange(myPort2)
    15. Button1.Enabled = True
    16. Button2.Enabled = False
    17. Button3.Enabled = True
    18. End Sub
    19. 'definieren und öffnen der Ports
    20. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    21. SerialPort1.PortName = ComboBox1.Text
    22. SerialPort1.BaudRate = 4800
    23. SerialPort1.DataBits = 7
    24. SerialPort1.StopBits = IO.Ports.StopBits.Two
    25. SerialPort1.Parity = IO.Ports.Parity.Even
    26. SerialPort1.ReceivedBytesThreshold = 1
    27. 'SerialPort1.DtrEnable = False
    28. SerialPort1.DtrEnable = True
    29. 'SerialPort1.RtsEnable = False
    30. SerialPort1.RtsEnable = True
    31. SerialPort1.ReadTimeout = 999
    32. SerialPort1.WriteTimeout = 999
    33. SerialPort2.PortName = ComboBox2.Text
    34. SerialPort2.BaudRate = 4800
    35. SerialPort2.DataBits = 7
    36. SerialPort2.StopBits = IO.Ports.StopBits.Two
    37. SerialPort2.Parity = IO.Ports.Parity.Even
    38. SerialPort2.ReceivedBytesThreshold = 1
    39. 'SerialPort2.DtrEnable = False
    40. SerialPort2.DtrEnable = True
    41. 'SerialPort2.RtsEnable = False
    42. SerialPort2.RtsEnable = True
    43. SerialPort2.ReadTimeout = 999
    44. SerialPort2.WriteTimeout = 999
    45. SerialPort1.Open()
    46. SerialPort2.Open()
    47. Button1.Enabled = False
    48. Button2.Enabled = True
    49. Button3.Enabled = True
    50. End Sub
    51. 'messung per knopfdruck starten
    52. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    53. 'SerialPort1.ReadExisting("FTDIBUS\VID_0403+PID_6001+MAO74PVOA\0000" & vbCrLf) -> hier sollte irgendwie ein Messe jetzt Signal hinein
    54. 'SerialPort2.ReadExisting("FTDIBUS\VID_0403+PID_6001+MAOHWY2WA\0000" & vbCrLf) -> hier sollte irgendwie ein Messe jetzt Signal hinein
    55. Button1.Enabled = False
    56. Button2.Enabled = True
    57. Button3.Enabled = True
    58. End Sub
    59. 'wenn beim port was reinkommt wird prozedur gestartet
    60. Private Sub SerialPort1_DataReceived(sender As System.Object, e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    61. Me.Invoke(Sub() ReceivedText1(SerialPort1.ReadExisting()))
    62. End Sub
    63. Private Sub ReceivedText1(ByVal [text] As String)
    64. RichTextBox1.Text &= [text]
    65. End Sub
    66. Private Sub SerialPort2_DataReceived(sender As System.Object, e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort2.DataReceived
    67. Me.Invoke(Sub() ReceivedText2(SerialPort2.ReadExisting()))
    68. End Sub
    69. Private Sub ReceivedText2(ByVal [text] As String)
    70. RichTextBox2.Text &= [text]
    71. End Sub
    72. 'schließen der Ports
    73. Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
    74. SerialPort1.Close()
    75. SerialPort2.Close()
    76. Button1.Enabled = True
    77. Button2.Enabled = False
    78. Button3.Enabled = False
    79. End Sub
    80. End Class
    @s0u1r3a9e2 Willkommen im Forum. :thumbup:
    Wenn an dem Port ein Gerät dran hängt, musst Du ihm wohl zunächst den Befehl senden, einen Messwert zu senden, den Du dann empfangen kannst.
    Vorausgesetzt, dass die Initialisierung richtig ist, sendest Du den Befehl, wartest eine gewisse Zeit und liest die Antwort aus.
    Dies wäre synchrone Abfrage,
    Asynchron wäre, dass Du den Befehl sendest und dann irgendwann im DataReceived-Event die Antwort bekommst.
    Da das Port in einem anderen Thread läuft als die GUI, musst Du zur Darstellung des empfangenen Wertes in den GUI-Thread invoken.
    Dazu findest Du hier im Forum beliebig viele Threads.
    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!
    Danke für die schnelle Antwort @RodFromGermany.

    RodFromGermany schrieb:

    Wenn an dem Port ein Gerät dran hängt, musst Du ihm wohl zunächst den Befehl senden, einen Messwert zu senden, den Du dann empfangen kannst.

    genau da hänge ich herum seit 3 Tagen )=
    Ich finde einfach nicht heraus wie ich diese synchrone Abfrage senden oder starten soll!? -> da bin ich zu unerfahren welche Möglichkeiten hier existieren bzw ob ich noch andere Einstellungen senden muss.

    Die Initialisierung sollte Richtig sein, da wenn ich auf den Messtastern die Messwerte durch drücken sende diese auch in den entsprechenden Textboxen erscheinen.
    Die Asynchrone Abfrage möchte ich gerne vermeiden.
    Die Daten erhalte ich schon über Invoken (leider nur wenn ich manuell Messdaten sende)

    Mir würde schon ein Schlagwort genügen in welche Richtung ich suchen soll (=
    @s0u1r3a9e2 Du musst einen String oder eine Byte-Folge senden:
    docs.microsoft.com/de-de/dotne…ite?view=netframework-4.8
    Beachte, dass Du das SerialPort.Encoding anpassen musst, wenn Du Strings sendest.
    Was Du da senden musst, entnimmst Du dem Handbuch des Geräts.
    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!
    Hallo!

    Falls jemand ähnliche Vorhaben hat, ich bin nach 3 Tagen herumprobieren endlich auf eine Lösungsmöglichkeit gekommen (=

    Zur Erklärung:
    Ich habe zwei Messuhren mit Opto RS232C Schnittstelle am Rechner per USB hängen die auf COM4 und COM5 bei mir hören.
    Mein Ziel war es per Knopfdruck oder Tastaturbefehl oder externem Signal die Messwerte zu erfassen.
    Hier meine Lösung für den Knopfdruck:

    VB.NET-Quellcode

    1. 'messung per knopfdruck starten
    2. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    3. SerialPort1.RtsEnable = True
    4. SerialPort2.RtsEnable = True
    5. System.Threading.Thread.Sleep(100)
    6. SerialPort1.RtsEnable = False
    7. SerialPort2.RtsEnable = False
    8. Button1.Enabled = False
    9. Button2.Enabled = True
    10. Button3.Enabled = True
    11. End Sub


    Mfg
    @s0u1r3a9e2 Du arbeitest also mit den Statussignalen, das ist natürlich ein wichtiger Hinweis, den Du uns geben musst.
    Solch eine Lösung ist mit noch nicht untergekommen. 8o
    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 freut mich einem so Erfahrenen User ein Smile abluchsen zu können ^^
    meine nächste Hürde wird jetzt sein das ganze noch mit Befehlen abnullen zu können...
    meine Ansätze wären da mit blabla.write zu arbeiten aber wie gesagt alles neuland für mich und ich muss das mit den bits und stellen als befehl senden mal überzuckern
    Aber vielleicht gibts auch hier eine Möglichkeit mit Statussignalen?

    Ich halte euch mal auf dem laufenden (=

    s0u1r3a9e2 schrieb:

    eine Möglichkeit mit Statussignalen
    Das hängt von der Gegenstelle ab.
    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!
    Hallo an die Gemeinde!

    Ein kleines Update was sich bei meinen Versuchen so getan hat, die Versuche mit dem abnullen hab ich mal stillgelegt, vll find ich bei meinen suchen ja zufällig was^^
    Mittlerweile hab ich die nächste Herausforderung zu meistern.

    Ich hab einen PT100 mit Hardware die über eine Modbus RS485 Schnittstelle auf USB ein COM Port erzeugt
    nach ewigen Grundlagenforschungen hab cih es endlich geschafft Ein Signal zur Schnittstelle zu senden um ein Messwert zu erhalten.

    Im Grunde funktioniert es aber noch nicht so wie ich möchte...
    Ich könnte ein wenig Ratschläge gebrauchen wie ich folgendes bewältige:
    0) ich erhalte (ASCII Text)
    1) diesen als Hex Code (7 Bytes)-> mit jetzigen codeschnippseln erhalte ich nur byte für byte mit jedem tastendruck /=
    2) in einen Puffer bringe,
    3) Die relevanten Bytes (4&5) hernehme
    4) und übersetze in ein 16bit unsinged integer
    5) und eine Kommastelle dazubastel

    Ich weiß scheint viel auf einmal zu sein aber ich komm einfach nicht dahinter
    Hier meine bisherigen schnippsel

    VB.NET-Quellcode

    1. 'Messung mit Tastatur starten
    2. Private Sub Form1_KeyDown(ByVal sender As System.Object, ByVal e As KeyEventArgs) Handles Me.KeyDown
    3. If e.KeyCode = Keys.F5 Then
    4. Dim Sendebefehl() As Byte = New Byte() {&H1, &H3, &H0, &H2, &H0, &H1, &H25, &HCA}
    5. SerialPort1.Write(Sendebefehl, 0, Sendebefehl.Length)
    6. 'System.Threading.Thread.Sleep(1000)
    7. End If
    8. Connect.Enabled = False
    9. Recieve.Enabled = True
    10. CloseApp.Enabled = True
    11. Reset.Enabled = True
    12. Zero.Enabled = True
    13. End Sub
    14. 'wenn beim port was reinkommt wird prozedur gestartet
    15. Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    16. Me.Invoke(Sub() ReceivedText1(Hex(SerialPort1.ReadByte())))
    17. End Sub
    18. Private Sub ReceivedText1(ByVal [text] As String)
    19. RichTextBox1.Text += [text]
    20. End Sub



    lg s0u1r3a9e2
    Hier bin ich wieder mit einem kleinen Update:

    Also punkt 1 bis 3 hab ich mal geschafft mit folgendem Code:

    VB.NET-Quellcode

    1. Dim input(sp1btr) As Byte
    2. SerialPort1.Read(input, 0, sp1btr)
    3. Dim hexasbyte = String.Format("&H{3:X2}{4:X2}", input(0), input(1), input(2), input(3), input(4), input(5), input(6))
    4. RichTextBox1.Text = hexasbyte
    5. SerialPort1.DiscardOutBuffer()
    6. End If


    bei nummer 4 sitze ich gerade den ganzen Tag und komme kein Stück weiter...
    Mal lässt er mich nicht byte in string umwandeln,
    Dann kommt ein Fehler weil der buffer mit dem offset irgendwie 0 ergibt?

    mir würde vielleicht nur ein Tipp helfen in welche Richtung ich schauen soll? :(

    lg aleks
    @Aleksander So was:

    VB.NET-Quellcode

    1. Dim by() As Byte = {0, 1, 2, &HD, &HA, 4, 5, 6, 7}
    2. Dim conv As Integer = BitConverter.ToInt16(by, 3)
    3. Label1.Text = conv.ToString("X4")
    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!
    Das &h weglassen

    VB.NET-Quellcode

    1. Dim hexasbyte = String.Format("{3:X2}{4:X2}", input(0), input(1), input(2), input(3), input(4), input(5), input(6))
    2. Dim x As Integer = Convert.ToInt32(hexasbyte, 16)
    3. Debug.Print(x)


    Evtl. musst du 3 und 4 tauschen (Little- oder Bigendian):

    VB.NET-Quellcode

    1. ... String.Format("{4:X2}{3:X2}", ...


    Wär natürlich einfacher, wenn du verrätst,wie das Ergebnis aussehen soll.
    @Eierlein Dann mach es doch gleich richtig:

    VB.NET-Quellcode

    1. Dim input(sp1btr) As Byte
    2. SerialPort1.Read(input, 0, sp1btr)
    3. Dim conv As Integer = BitConverter.ToInt16(input, 3)
    4. Label1.Text = conv.ToString("X4")
    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!

    Eierlein schrieb:

    LittleEndian Format
    bezieht sich auf UniCode, hier gehtr es offensichtlich um einen Int16-Wert, der sollte so stimmen.
    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!
    hui danke für die vielen Rückmeldungen!

    Ich werde obige Varianten auch noch ausprobieren da ich das nur mit Option strict off schaffe /=, habe aber mein Resultat mit einem kleinen Geistesblitz geschafft^^
    ->

    VB.NET-Quellcode

    1. Private Sub Form1_KeyDown(ByVal sender As System.Object, ByVal e As KeyEventArgs) Handles Me.KeyDown
    2. If e.KeyCode = Keys.F5 Then
    3. Dim output() As Byte = {&H1, &H3, &H0, &H2, &H0, &H1, &H25, &HCA}
    4. SerialPort1.Write(output, 0, 8)
    5. End If
    6. End Sub
    7. 'wenn beim port was reinkommt wird prozedur gestartet
    8. Private Sub SerialPort1_Input(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    9. Me.Invoke(Sub() ReceivedText1())
    10. End Sub
    11. Private Sub ReceivedText1()
    12. Dim btr As Byte = SerialPort1.BytesToRead
    13. Dim input(btr) As Byte
    14. SerialPort1.Read(input, 0, btr)
    15. Dim Ergebnis As UInteger = String.Format("&H{3:X2}{4:X2}", input(0), input(1), input(2), input(3), input(4), input(5), input(6))
    16. Dim Ergebnismitkomma As Decimal = Ergebnis / 10
    17. RichTextBox1.Text = Ergebnismitkomma
    18. End Sub

    Zur Erklärung: Ich sende auf den Modbus eben "13020125CA" 8Byte und erhalte 7Bytes wo byte 1-3 die Antwort vom Bus sind wer er ist und was er macht 4&5 ist der Messwert 6&7 die CRC Bytes

    Ich bin noch nicht ganz wirklich dahinter gekommen auf welche Art ich den Befehl senden muss aber mit HEX funktioniert es.
    Das Ergebnis von Stringformat als Uinteger Angezeigt und dann durch 10 dividiert hat meine Lösung gebracht :D
    Also so langsam komm ich auf den Geschmack mit den herum jonglieren der Nullen und Einsen gg

    Auf zur nächsten Challange!

    Aleksander schrieb:

    da ich das nur mit Option strict off schaffe
    Wieso?
    Wo klemmt es?
    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!
    So sollte es mit Strict On funktionieren:

    VB.NET-Quellcode

    1. ...
    2. Dim Ergebnis As UInteger = CUInt(String.Format("&H{3:X2}{4:X2}", input(0), input(1), input(2), input(3), input(4), input(5), input(6)))
    3. Dim Ergebnismitkomma As Decimal = CDec(Ergebnis / 10)


    Übrigens: Statt UInteger (4 Bytes) reicht UShort (2 Bytes).

    @RodFromGermany
    Wenn das Ergebnis stimmt, kommen die bytes 3 und 4 im BigEndian Format an.

    RodFromGermany schrieb:

    Aleksander schrieb:

    da ich das nur mit Option strict off schaffe
    Wieso?
    Wo klemmt es?


    bei Option Strict On schmeißt er mir meine kreuz und quer Deklarationen ^^
    @Eierlein Danke für den Tipp!

    habe auch

    VB.NET-Quellcode

    1. Dim btr As Byte = SerialPort1.BytesToRead
    durch

    VB.NET-Quellcode

    1. Dim btr As Byte = CByte(SerialPort1.BytesToRead)
    getauscht, dann ist alles "saubär"

    einzig: jetzt funktionieren meine Kommastellen wieder nicht ;(

    @Aleksander Dann hast Du das nicht verstanden. :/
    SerialPort.BytesToRead ist vom Typ Integer.
    Was passiert, wenn z.B. 12345 Bytes available sind? Dann kommt eine Overflow-Exception :!:
    Sauber wäre:

    VB.NET-Quellcode

    1. Dim btr As Integer = SerialPort1.BytesToRead
    Wenn Du mit Option Infer = On arbeitest, genügt

    VB.NET-Quellcode

    1. Dim btr = SerialPort1.BytesToRead
    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!