Forum: PC-Programmierung weiter nach Antwort vom Serial Port


von Thomas G. (heckesepp)


Angehängte Dateien:

Lesenswert?

Hallo Gemeinde,

ich habe ein Interface ( iSMIF von der Fa. EMIS ) um eine 
Schrittmotorkarte (SMC 800) anzusteuern. Die Befehle werden in ASCII 
über die serielle Schnittstelle übermittelt. Das Senden und Empfangen 
funktioniert einwandfrei.
Das Interface sendet eine 6 zurück, wenn es bereit ist den nächsten 
Befehl zu empfangen. Die Zeit dazu ist unterschiedlich, da es ja länger 
dauert 10.000 Schritte zu fahren als z.B. nur 500 Schritte. Das 
Empfangen habe ich nach langem Googeln über das SerialPort.DataReceived 
Ereignis hinbekommen und lasse es mir in einer ListBox anzeigen. Soweit 
so prima.
Nun zu meinem Problem ; ich will ja mehr als nur einmal verschiedene 
Schritte fahren ( mein Ziel ist sowas in Richtung Plotter bzw ganz 
einfache CNC Steuerung ). Wenn ich mehrere Schritte, z.B. mit einer 
Schleife, an das Interface schicke wird das SerialPort.DataReceived 
Ereignis nicht bei jedem Durchlauf ausgelöst, sondern erst am Ende. Ich 
muss aber vor jedem Schritt warten bis das Interface mit der 6 meldet 
das es bereit für den nächsten Befehl ist.
Wie kann ich erreichen das bei jedem Schleifendurchlauf das 
SerialPort.DataReceived Ereignis ausgelöst wird.

Vielen Dank an alle die Interesse und vielleicht eine Lösung zu meinem 
Problemchen haben.

LG Tommy G.

hier mein bisheriger Code oder in der angehängten Datei

Option Strict On
Option Explicit On
Imports System
Imports System.IO
Imports System.Windows.Forms
Imports Microsoft.VisualBasic
Imports System.Drawing
Imports System.IO.Ports

Public Class Rückantwort_Test_DataReceived

    Dim PufferString As String
    Private Delegate Sub DelegateSub()
    Private Datenanzeigen As New DelegateSub(AddressOf Anzeigen)


    Private Sub btnVerbinden_Click(sender As Object, e As 
System.EventArgs) Handles btnVerbinden.Click

        SerialPort1.PortName = "COM3"
        SerialPort1.Parity = Parity.None
        SerialPort1.BaudRate = 115200
        SerialPort1.DataBits = 8
        SerialPort1.StopBits = StopBits.One
        SerialPort1.Open()
        liboTHG.Items.Add("Verbunden mit COM 3")

        btnVerbinden.Enabled = False
        btnTrennen.Enabled = True

    End Sub

    Private Sub btnTrennen_Click(sender As Object, e As 
System.EventArgs) Handles btnTrennen.Click

        SerialPort1.Close()
        liboTHG.Items.Add("COM 3 getrennt")

    End Sub

    Private Sub Rückantwort_Test_Load(sender As Object, e As 
System.EventArgs) Handles Me.Load

        btnTrennen.Enabled = False

    End Sub

    Private Sub Rückantwort_Test_FormClosing(sender As Object, e As 
System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing

        SerialPort1.Close()

    End Sub

    Private Sub btnLeeren_Click(sender As Object, e As System.EventArgs) 
Handles btnLeeren.Click

        liboTHG.Items.Clear()

    End Sub

    Private Sub btnVor_Click(sender As Object, e As System.EventArgs) 
Handles btnVor.Click

        Dim Takt As String = txtTakt.Text

        For i = 1 To 3 Step 1

            SerialPort1.Write("T0," & vbCr)
            SerialPort1.Write("L1,x" & Takt & vbCr)
            liboTHG.Items.Add("L1,x" & Takt)
            liboTHG.Items.Add("----------------------")

        Next

    End Sub

    Private Sub btnZurück_Click(sender As Object, e As System.EventArgs) 
Handles btnZurück.Click

        Dim Takt As String = txtTakt.Text

        SerialPort1.Write("T0," & vbCr)
        SerialPort1.Write("L1,x-" & Takt & vbCr)
        liboTHG.Items.Add("L1,x-" & Takt)
        liboTHG.Items.Add("----------------------")


    End Sub

    Private Sub SerialPort1_DataReceived(ByVal sender As Object, _
                                ByVal e As 
System.IO.Ports.SerialDataReceivedEventArgs) _
                                Handles SerialPort1.DataReceived

        Dim enc As System.Text.Encoding = New 
System.Text.ASCIIEncoding()

        With SerialPort1

            Try
                ' Alle Bytes einzeln lesen
                For I As Integer = 1 To .BytesToRead
                    ' 1 Byte lesen
                    Dim ByteArray() As Byte = 
{CByte(.BaseStream.ReadByte)}
                    ' Array in String
                    PufferString = enc.GetString(ByteArray)
                    ' Delegaten aufrufen
                    Me.Invoke(Datenanzeigen)
                Next

            Catch ex As Exception

                MessageBox.Show(ex.Message, "Fehler beim Empfangen ...")

            End Try

        End With

    End Sub

    Private Sub Anzeigen()


        ' Text am Ende hinzufügen
        liboTHG.Items.Add(Asc(PufferString))
        liboTHG.Items.Add("----------------------")

    End Sub

von Karl H. (kbuchegg)


Lesenswert?

Thomas G. schrieb:

> Wie kann ich erreichen das bei jedem Schleifendurchlauf das
> SerialPort.DataReceived Ereignis ausgelöst wird.

Gar nicht.
Du stellst deine Strategie um.

Du hast eine Liste von Befehlen. Und jedesmal wenn dein DataReceived 
anschlägt und du eine 6 empfängst, siehst du in dieser Tabelle nach, ob 
ein weiterer Befehl zur Steuerung zu schicken ist. Wenn ja, dann machst 
du das.


D.h. man könnte das ganze auch so auffassen.
Die Steuerung fordert mit ihrer 'Fertig'-Meldung den jeweils nächsten 
Befehl an. Den allerersten Befehl schickst du konventionell auf die 
Reise und durch das Rücksenden der '6' triggert die Steuerung selber das 
Senden des nächsten Befehls (falls es noch einen gibt)

von Thomas G. (heckesepp)


Lesenswert?

Erst einmal vielen Dank für die schnelle Antwort.

In die Richtung hatte ich auch schon gedacht, aber noch nichts 
ausprobiert.
Könntest du mir bitte deine Idee näher erklären? Ich wüsste im Moment 
nicht wie und wo ich da ansetzen sollte. Das Programm habe ich mit 
VB.net Studio 2010 unter WIN XP geschrieben. Es würde reichen wenn du 
mir einen ungefähren Weg unterbreiten könntest und ich dann versuche den 
umzusetzen. Ein Code - Schnipsel währe natürlich ein Sahnehäubchen.
Vielen Dank im Voraus für deine Bemühungen.

LG Tommy G.

von Karl H. (kbuchegg)


Lesenswert?

Was gibts da grossartig schwieriges


dim Befehle(100) as string
dim AnzahlBefehle as integer
dim AktuellerBefehl as integer


irgendwo stellst du deine Befehlslisten zusammen (ich kenn ja deine 
Befehle nicht, also nehm ich einfach was aus dem was du vorgegeben hast

  Befehle(1) =  "L1,x" & Takt & vbCr
  Befehle(2) =  "L1,x" & Takt & vbCr
  Befehle(3) =  "L1,x-" & Takt & vbCr
  Befehle(4) =  "L1,x" & Takt & vbCr

  AnzahlBefehle = 4
  AktuellerBefehl = 1

und den ersten Befehl setzt du direkt ab

  SerialPort1.Write("T0," & vbCr)


Wird die DataReceived aufgerufen, dann weißt du, dass der letzte Befehl 
(bei positiver Rückmeldung) fertig abgearbeitet wurde

    Private Sub SerialPort1_DataReceived(ByVal sender As Object, _
                                ByVal e As
System.IO.Ports.SerialDataReceivedEventArgs) _
                                Handles SerialPort1.DataReceived

        Dim enc As System.Text.Encoding = New
System.Text.ASCIIEncoding()

        With SerialPort1

            Try
                ' Alle Bytes einzeln lesen
                For I As Integer = 1 To .BytesToRead
                    ' 1 Byte lesen
                    Dim ByteArray() As Byte =
{CByte(.BaseStream.ReadByte)}
                    ' Array in String
                    PufferString = enc.GetString(ByteArray)
                    ' Delegaten aufrufen
                    Me.Invoke(Datenanzeigen)



     if AktuellerBefehl < AnzahlBefehle then
        SerialPort1.Write( Befehle(AktuellerBefehl) )
        AktuellerBefehl = AktuellerBefehl + 1
     end if

                Next

            Catch ex As Exception

                MessageBox.Show(ex.Message, "Fehler beim Empfangen ...")

            End Try

        End With

    End Sub


so ungefähr. Ich kenn weder dein Board noch welche Befehle es will noch 
hab ich jetzt die VB Syntax dazu im Kopf. Aber vom Prinzip her sollte 
klar sein, wie das laufen kann.

von Thomas G. (heckesepp)


Lesenswert?

Hi,

vielen Dank für deine Antwort. Leider kann man aus einem separatem Thred 
nicht so einfach auf eine laufende Form zugreifen.
Aber; ich habe mein Problemchen mit einem Timer - Aufruf gelöst. 
Funktioniert bei z.B. 100 mal 10 Schritte genau so gut wie bei 1 mal 
25000 Schritte.
Der Lösungsansatz mit dem Timer wurde hier im Forum schon mal erwähnt. 
Gefunden hatte ich ihn beim googeln. Sollte Interesse bestehen, bin ich 
gerne bereit zu helfen oder meinen funktionierenden Code hier 
einzustellen.

Vielen Dank auch an alle Leser, auch wenn sonst keiner eine Lösung 
hatte.

Dieser Beitrag kann nun als erledigt angesehen werden.


LG Tommy

von Karl H. (kbuchegg)


Lesenswert?

Thomas G. schrieb:
> Hi,
>
> vielen Dank für deine Antwort. Leider kann man aus einem separatem Thred
> nicht so einfach auf eine laufende Form zugreifen.

Dann musst du eben über einen Invoke und eine Hilfsfunktion gehen.

von Hans (Gast)


Lesenswert?

Hallo,

hat jemand von euch dieses Interface schon einmal mit C# angesteuert 
statt VB ?

Leider kann ich nämlich keine Rückantwort des Interface erhalten.

Grüße Hans

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.