Com-Port auslesen Feedback zum Anwendungsfall

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

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

    Com-Port auslesen Feedback zum Anwendungsfall

    Hallo,

    Ich habe ein Programm zum Auslesen eines ComPorts, das ich auch schon durch eure Hilfe zusammengebastelt habe. Es funktioniert nun endlich seit einiger Zeit ohne Fehler. Würdet ihr trotzdem noch einmal drüberschauen und mir sagen was man verbessern kann? Es soll minimalistisch sein.

    Der konkrete Anwendungsfall: Ein Scanner simuliert über USB einen Com-Port. Dieses Gerät wird ausgelesen. Eigentlich macht es nur Piep und der gelesene Barcode erscheint. Man sieht den Port-Status, kann ihn ändern und das Programm macht darauf aufmerksam, dass es mit geschlossenem ComPort nichts wird.

    Der Code:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private pPortname = "COM3"
    2. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    3. Timer1.Interval = 10000
    4. If Not SerialPort1.IsOpen Then
    5. Button1.Enabled = False
    6. SerialPort1.PortName = pPortname
    7. SerialPort1.BaudRate = 115200
    8. SerialPort1.DataBits = 8
    9. SerialPort1.Parity = IO.Ports.Parity.None
    10. SerialPort1.StopBits = IO.Ports.StopBits.One
    11. SerialPort1.DtrEnable = True
    12. SerialPort1.RtsEnable = True
    13. SerialPort1.Handshake = IO.Ports.Handshake.None
    14. SerialPort1.Open()
    15. End If
    16. If SerialPort1.IsOpen Then
    17. Button1.BackColor = Color.FromArgb(0, 200, 0)
    18. If Timer1.Enabled Then Timer1.Stop()
    19. Else
    20. Timer1.Start
    21. Button1.Enabled = True
    22. End If
    23. End Sub
    24. Private Sub btnOpen_Click(sender As Object, e As EventArgs) Handles Button1.Click
    25. If Not SerialPort1.IsOpen Then
    26. Button1.Enabled = False
    27. SerialPort1.PortName = pPortname
    28. SerialPort1.BaudRate = 115200
    29. SerialPort1.DataBits = 8
    30. SerialPort1.Parity = IO.Ports.Parity.None
    31. SerialPort1.StopBits = IO.Ports.StopBits.One
    32. SerialPort1.DtrEnable = True
    33. SerialPort1.RtsEnable = True
    34. SerialPort1.Handshake = IO.Ports.Handshake.None
    35. SerialPort1.Open()
    36. End If
    37. If SerialPort1.IsOpen Then
    38. Button1.BackColor = Color.FromArgb(0, 200, 0)
    39. If Timer1.Enabled Then Timer1.Stop()
    40. End If
    41. Button2.Enabled = True
    42. End Sub
    43. Private Sub btnClose_Click(sender As Object, e As EventArgs) Handles Button2.Click
    44. If SerialPort1.IsOpen Then
    45. SerialPort1.Close()
    46. Button1.BackColor = Color.FromArgb(180, 191, 185)
    47. Button1.Enabled = True
    48. Button2.Enabled = False
    49. Timer1.Start()
    50. End If
    51. End Sub
    52. Private Sub timePortClosed_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    53. Timer1.Stop()
    54. MessageBox.Show("Die Verbindung zum Port wurde getrennt!" & vbLf & "Sie können entweder das Programm neustarten oder Sie öffnen die Verbindung mit dem Öffnen-Knopf (Er wird dann grün)", "Nutzung Scanner", MessageBoxButtons.OK)
    55. Timer1.Start()
    56. End Sub
    57. Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
    58. If Timer1.Enabled Then Timer1.Stop()
    59. If SerialPort1.IsOpen Then SerialPort1.Close()
    60. End Sub
    61. Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    62. If SerialPort1.IsOpen Then
    63. Dim prüf As Integer
    64. System.Threading.Thread.Sleep(100)
    65. Me.Invoke(Sub() prüf = SerialPort1.BytesToRead)
    66. Dim COMBuffer() As Byte = New Byte(prüf - 1) {}
    67. Try
    68. SerialPort1.Read(COMBuffer, 0, prüf)
    69. Me.BeginInvoke(Sub() Read_Message(COMBuffer))
    70. System.Threading.Thread.Sleep(100)
    71. Catch ex As InvalidOperationException
    72. MessageBox.Show("2 " & ex.ToString)
    73. End Try
    74. End If
    75. End Sub
    76. Private Sub Read_Message(COMB As Byte())
    77. System.Threading.Thread.Sleep(0)
    78. Dim enc As New System.Text.ASCIIEncoding()
    79. Dim strbarcode As String = enc.GetString(COMB)
    80. While SerialPort1.IsOpen
    81. SerialPort1.Close()
    82. Button1.BackColor = Color.FromArgb(180, 191, 185)
    83. Button1.Enabled = True
    84. Button2.Enabled = False
    85. End While
    86. TextBox1.Text = strbarcode ''oder was man dann so macht mit dem Input
    87. While Not SerialPort1.IsOpen
    88. SerialPort1.Open()
    89. Button1.BackColor = Color.FromArgb(0, 200, 0)
    90. Button1.Enabled = False
    91. Button2.Enabled = True
    92. End While
    93. End Sub


    Ich habe die Controls so umbenannt, dass es sofort funktionieren würde, wenn ihr ein Form mit 2 Buttons, 1 TextBox, 1 Timer, und einem SerialPort habt, falls ihr selbst einen Scanner hättet.
    Die Spezifikationen wie BaudRate usw. habe ich dem Gerät entnommen. Was das genau ist weiß ich gar nicht ...

    Viele Grüße

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

    Hab mir von deinem Code noch nicht wirklich was durchgelesen, aber dem PortName pPortname würde ich auf jeden Fall nicht einfach "COM3" zuweisen und es dabei belassen.
    Was machst du, wenn der Scanner nicht den COM3 zugwiesen bekommt? Wie es aussieht hast du noch keine Möglichkeit geschaffen, den tatsächlichen Port des Scanners zu wählen. Das würde ich auf jeden Fall noch vorsehen.
    Stichwort SerialPort.GetPortNames()
    Dumm ist der, der dumm ist. Nicht andersrum!
    Ja die GetPortNames Methode stelle ich quasi händisch nach. Eigentlich steht da nicht "COM3", sondern der Eintrag den man in einer Settingsdatei machen kann. Heißt natürlich man schaut noch selbst nach welche Ports es gibt. Also änderbar ist der Portname ohne Programmänderung, aber nicht automatisiert. Um das Auslesen der Settingsdatei gings mir aber nicht deswegen habe ich das ersetzt. Macht natürlich den falschen Eindruck
    Vielleicht eher so (Pseudo):

    Quellcode

    1. Private pPortname = ReadConfig


    Bei GetPortNames selbst weiß ich nicht wie ich rausfinde welcher denn der richtige ist, gesetzt den Fall man hätte mehr als einen ComPort. Man könnte natürlich im laufenden Programm aus der Liste wählen. Dann kommt man um selber gucken aber auch nicht drum rum.

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

    @Haudruferzappeltnoch Ein Barcodescanner arbeitet wier eine Tastatur, er sendet einen String.
    Teste diesen Code (Port und Baudrate anpassen):

    VB.NET-Quellcode

    1. Imports System.Net
    2. Public Class Form1
    3. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    4. Me.ComboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames)
    5. If Me.ComboBox1.Items.Count > 0 Then
    6. Me.ComboBox1.SelectedIndex = 0
    7. Else
    8. Me.Button1.Enabled = False
    9. End If
    10. End Sub
    11. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    12. Me.SerialPort1.PortName = Me.ComboBox1.SelectedItem.ToString()
    13. Me.SerialPort1.BaudRate = 83400
    14. Me.SerialPort1.NewLine = Environment.NewLine
    15. Me.SerialPort1.Open()
    16. End Sub
    17. Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    18. Dim txt = Me.SerialPort1.ReadLine
    19. Me.Invoke(Sub() Me.TextBox1.AppendText(txt))
    20. End Sub
    21. Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
    22. Me.SerialPort1.Close()
    23. End Sub
    24. End Class

    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:

    änderbar ist der Portname ohne Programmänderung


    Aber auch nur als fixer Eintrag in deiner Config-Datei. Ist ja, wenn man so will, auch nichts anderes als im Code einfach "COMx" zuzuweisen. Du hast mit der Config-Datei ja das selbe Problem...was passiert wenn der angegebene Port nicht passt?

    Ich hab mal sowas hier gemacht, um mir nur die Scanner-COMPorts anzeigen zu lassen

    C#-Quellcode

    1. public IEnumerable<string> GetScannerComPorts()
    2. {
    3. try
    4. {
    5. using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity WHERE Caption like '%Barcode Scanner (COM%'"))
    6. {
    7. IEnumerable<string> ports = searcher.Get().Cast<ManagementBaseObject>().Select(x => x["Caption"].ToString());
    8. return SerialPort.GetPortNames().Where(sPort => ports.Any(port => port.Contains(sPort)));
    9. }
    10. }
    11. catch (ManagementException ex)
    12. {
    13. throw ex;
    14. }
    15. }


    Hab das allerdings nur mit dem PD9531 von Datalogic testen können.
    Dumm ist der, der dumm ist. Nicht andersrum!

    Haudruferzappeltnoch schrieb:

    eine System.IO.IOException
    mit welcher Fehlermeldung?
    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 Sieh mal in der Beschreibung nach, was für ein Zeilenende das Ding sendet und trage es hier ein:

    VB.NET-Quellcode

    1. Me.SerialPort1.NewLine = Environment.NewLine
    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 Was sagt denn die Bedienungsanleitung?
    Ruf mal beim Service der Herstellerfirma an.
    ====
    Ggf. gibt es im Handbuch Barcodes, mit denen man die Betriebsart des Scanners umschalten kann.
    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!

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

    Also da kann man durchaus einiges machen. Eine Erklärung zu den ausgelesenen Werte ist dort jedoch nicht zu finden.
    Die Betriebsarten sind als Bluetooth HID Keyboard, USB HID Scanner, USB Serial

    Mein Code hat dieses Problem ja auch gar nicht gehabt. Ich dachte vielleicht hätte man bei meiner Methode noch ein paar Dinge drehen können, anstatt eine andere zu nutzen.