RS232 ansteuern für absoluten Anfänger! HILFE!

gedönse

Grünschnabel
Moin, ich hab ein ganz triviales Problem. Ich möchte mit Visual Studio 2008 ein Messgerät über RS232 ansteuern (Befehle senden und auslesen). Dafür möchte ich die vorgesehene Klasse SerialPorts nutzen. Da ich aber so gut wie keine Erfahrung mit sowas habe (1 Semester Grundlagen VBA), brauche ich dringend hilfe. Ich habe schon die letzten zwei Tage alles durchforstet, aber ich raffe garnichts. Kann mir jemand einen Ansatz liefern der für einen **** wie mich verständlich ist? Vielleicht hat jemand auch ne Lösung die ich nur anpassen muss?!

Ich bin langsam echt am verzweifeln, das kann doch nicht so schwer sein. Die Befehle zum ansteuern hab ich schon mit einem Sniffer und Hyperterminal rausgefunden.

Vielen Dank,

Mfg Gedönse
 
Ganz ehrlich, ich weiß überhuapt nicht wie ich anfangen soll. Wie beginne ich z.B. den Aufruf der Class? Wie kann ich die Werte auslesen und in eine Excel-Datei schreiben? Wie kann ich die Datenaufnahme zeitlich steuern? Ich habe mir jetzt schon Literatur besorgt, vielleicht hilft mir die ja weiter. Ich dachte hier hätte jemand schon mal sowas gemacht. Mfg Gedönse
 
Hallo,

das Beispiel in der MSDN liefert doch schon mal eine ganz gute Grundlage.
Kurz in Stichpunkten formuliert, funktioniert das etwa so:

- Initialisieren (Portname, Baudrate, Parität usw. einstellen).
- Den Port öffen (Open)
- Einen Befehlen senden (Write)
- Das Ergebnis (Lesen)
- Den Port schließen (Close)

Das Speichern der Daten ist wieder eine andere Aufgabe. Schreibe die Ergebnisse doch erstmal eine csv-Datei, die sich mit Excel leicht importieren lässt.

Wie du dir die zeitliche Steuerung vorstellst, musst du noch mal genauer beschreiben.

Gruß
MCoder
 
Danke für deine Antwort Mcoder, das Beispiel hatte ich mir schon angeschaut. Funktioniert das auch ohne 2. Pc? Der zeitliche Ablauf soll der Messgeschwindigkeit angepaat werden können, sprich ich drücke Start und das Programm wiederholt 10 sec. den Messvorgang bzw. den Befehl. Hmm, ich denke ich verstehe schon ein wenig mehr, aber ganz so ist der Groschen noch nicht gefallen. Mfg Gedönse
 
Der 2. PC ist in deinem Falle des Messgerät. Einen sehr einfachen Ablauf habe ich mal aufgeschrieben. Versuche erst mal überhaupt mit dem MessgerätVerbindung aufzunehmen und Kommandos abzusetzen. Eine zeitliche Steuerung kann man später über einen Timer realisieren, aber versuche erstmal die grundlegende Kommunikation zum Laufen zu bringen.

Hier der einfache Ablauf:
C#:
SerialPort serialport = new SerialPort();

// Initialisierung
// TODO: Entsprechend den Erfordernissen des Messgerätes anpassen
serialport.BaudRate     = 115200;
serialport.Parity       = Parity.Even;
serialport.DataBits     = 8;
serialport.StopBits     = StopBits.One;
serialport.RtsEnable    = true;
serialport.ReadTimeout  = 1000;
serialport.WriteTimeout = 1000;

// Öffnen
serialport.PortName = "COM1"; //TODO: ggf. den Port anpassen
serialport.Open();

// Kommando senden
byte [] send_buffer = { ... }; // TODO: Kommandobytes einfügen
serialport.Write(send_buffer, 0, send_buffer.Length);

// Antwort lesen
byte [] read_buffer = new byte[100];
serialport.Read( read_buffer, 0, NN /* TODO: Anzahl der zu lesenden Bytes*/ );

// Port schliessen
serialport.Close()
Gruß
MCoder
 
So, hier mein Zwischenstand:

PHP:
Public Class Form1

    ' Das Delegat muss die selbe Signature haben
    Delegate Sub TextBoxCallback(ByVal text As String)

    Private WithEvents myComPort As IO.Ports.SerialPort

    ' Bei den meisten Geräten ist ein Abschlußzeichen erforderlich, meistens 
    '  wird ChrW(13) oder ChrW(10) oder beide benötigt 
    '  - Wählt was eure Gegenstelle benötigt:
    Private EndOfCommand As String = Constants.vbCr.ToString
    ' Private EndOfCommand As String = Constants.vbLf.ToString
    ' Private EndOfCommand As String = Constants.vbCrLf.ToString

    Private Sub Form1_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load

        ' Mal nachschauen, ob es hier SerialPorts gibt
        Dim str() As String = IO.Ports.SerialPort.GetPortNames()

        ' Wenn nein, dann beenden:
        If str.Length = 0 Then
            MsgBox("No Serialport available!", MsgBoxStyle.Critical)
            Me.Close()
        End If

        ' Eine Instance von SerialPort erstellen
        ' Im Normalfall ist das COM1:
        Me.myComPort = New IO.Ports.SerialPort(str(0))

        ' Die folgenden vier Einstellungen müssen denen der 
        ' Gegenstelle entsprechen
        Me.myComPort.BaudRate = 9600
        Me.myComPort.DataBits = 8
        Me.myComPort.StopBits = IO.Ports.StopBits.One
        Me.myComPort.Parity = IO.Ports.Parity.None

        ' Wichtig! Hier wird eingestellt nach wieviel Bytes im Eingangspuffer 
        ' das DataReceived Event gefeuert wird
        Me.myComPort.ReceivedBytesThreshold = 1

        ' Und nun öffnen wir den Port
        Me.myComPort.Open()
    End Sub

    ''' <summary>
    ''' Wird ausgelöst wenn die Comm die in ReceivedBytesThreshold eingestellte 
    ''' Anzahl Bytes empfangen hat
    ''' </summary>
    Private Sub myComPort_DataReceived( _
        ByVal sender As Object, _
        ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _
        Handles myComPort.DataReceived

        Select Case e.EventType
            Case IO.Ports.SerialData.Chars
                ' Ein Zeichen wurde empfangen und im Eingabepuffer platziert.

            Case IO.Ports.SerialData.Eof
                ' Das Dateiendezeichen wurde empfangen und im 
                '  Eingabepuffer platziert. 

        End Select
        Dim msg As String = Me.myComPort.ReadExisting
        Me.ShowText(msg)
    End Sub

    ''' <summary>
    ''' Wird ausgelöst wenn sich die Steuerleitungen geändert haben
    ''' </summary>
    Private Sub myComPort_PinChanged(ByVal sender As Object, ByVal e As  _
        System.IO.Ports.SerialPinChangedEventArgs) Handles myComPort.PinChanged
        Select Case e.EventType
            Case IO.Ports.SerialPinChange.Break
                ' Bei der Eingabe wurde ein "break" erkannt.

            Case IO.Ports.SerialPinChange.CDChanged
                ' Der Zustand des CD-Signals (Carrier Detect) hat sich geändert.
                ' Mit diesem Signal wird angezeigt, ob ein Modem mit einer 
                '  Telefonleitung verbunden ist und ein Datenträgersignal 
                '  erkannt wurde.

            Case IO.Ports.SerialPinChange.CtsChanged
                ' Der Zustand des CTS-Signals (Clear to Send) hat sich geändert.
                '  Mit diesem Signal wird angegeben, ob Daten über den seriellen
                '  Anschluss gesendet werden können. 

            Case IO.Ports.SerialPinChange.DsrChanged
                ' Zustand des DSR-Signals (Data Set Ready) hat sich geändert.
                '  Mit diesem Signal wird angezeigt, ob das Gerät am seriellen
                '  Anschluss betriebsbereit ist.

            Case IO.Ports.SerialPinChange.Ring
                'Ein Ringindikator wurde erkannt. 

        End Select
    End Sub

    ''' <summary>
    ''' Wird ausgelöst wenn ein Fehler in der Übertragung endeckt wurde
    ''' </summary>
    Private Sub myComPort_ErrorReceived( _
        ByVal sender As Object, _
        ByVal e As System.IO.Ports.SerialErrorReceivedEventArgs) _
        Handles myComPort.ErrorReceived

        Select Case e.EventType
            Case IO.Ports.SerialError.Frame
                ' Die Hardware hat einen Rahmenfehler erkannt.

            Case IO.Ports.SerialError.Overrun
                ' Ein Zeichenpufferüberlauf ist aufgetreten. Das nächste 
                '  Zeichen geht verloren. 

            Case IO.Ports.SerialError.RXOver
                ' Ein Eingabepufferüberlauf ist aufgetreten.
                ' Die Kapazität des Eingabepuffers ist erschöpft,
                '  oder es wurde ein Zeichen nach dem Dateiendezeichen 
                '  (EOF, end-of-file) empfangen. 

            Case IO.Ports.SerialError.RXParity
                ' Die Hardware hat einen Paritätsfehler erkannt.

            Case IO.Ports.SerialError.TXFull
                ' Die Anwendung hat versucht, ein Zeichen zu übertragen, aber 
                ' die Kapazität des Ausgabepuffers war erschöpft. 

        End Select
        Me.ShowText("ERROR" & vbCrLf)
    End Sub

    ''' <summary>
    '''  Da die Daten aus einem anderem Thread kommen müssen wir die Ausgabe 
    '''  über Invoke machen
    ''' </summary>
    Private Sub ShowText(ByVal text As String)
        If Me.TxtMesswert.InvokeRequired Then
            Dim d As New TextBoxCallback(AddressOf ShowText)
            Me.Invoke(d, New Object() {text})
        Else
            Me.TxtMesswert.Text = Me.TxtMesswert.Text & text
        End If
    End Sub

    ''' <summary>
    ''' Hier wird der Command zusammengesetzt und versendet
    ''' </summary>
    ''' <param name="command"></param>
    ''' <remarks></remarks>
    Private Sub Send(ByVal command As String)
        Me.myComPort.Write(command & Me.EndOfCommand)
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles BtnStart.Click

        'Messung starten

        TxtMesswert.Clear()

        Me.Send("M")

    End Sub

    Private Sub BtnBeenden_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnBeenden.Click

        'Messung beenden

        Me.myComPort.Close()
        Me.Close()

    End Sub
End Class

Das funktioniert soweit, dass die Antwort, die ich durch den Befehl "M" an das Messgerät schicke, mit dem Messwert M, 1,234 beantwortet wird. Wie kann ich den Befehl jetzt zeitlich ablaufen lassen und diese Werte dann speichern?

Mfg Gedönse
 
Wie kann ich den Befehl jetzt zeitlich ablaufen lassen und diese Werte dann speichern?
Füge zu der Form einen Timer hinzu und installiere eine Methode für den Timer-Event. Den Code von 'Button1_Click' kannst du dann in der Timer-Methode ausführen.
Zum Speichern kannst du z.B. mit den Klassen FileStream und StreamWriter eine Dateiausgabe realisieren. Dazu solltest du auch genug Beispiele finden.

Gruß
MCoder
 
Mahlzeit! Also ich kriege das nicht hin. Es soll folgendermaßen ablaufen. Ich drücke den Button und er gibt einen Befehl aus. Dieser Befehl soll mit einem Intervall von 500ms wiederholt werden, bis die Zeit von 10 Sekunden abgelaufen ist. Muss ich den Button in den Timer integrieren oder andersrum? Mfg Gedönse
 

Neue Beiträge

Zurück