# Beckhoff TwinCat ADS OCX und VB.net



## Parallax (9 April 2008)

Hallo,

ich möchte in dem bei VS 2005 enthaltenem Visual Basic eine Softwäre für einen Beckhoff Industrie PC entwickeln. Dabei war eine Möglichkeit unter VB6 mit TwinCat eine dauerhafte Verbindung zwischen einer Variable und VB herzustellen das

CALL adsocx1.adsreadintegerconnect(blabla)

dies funktioniert zwar bei VB.net ebenfalls, allerdings wird die Variable nur einmal Aktualisiert und dann bleibt der Wert für alle Ewigkeit bestehen, auch wenn sich der Wert in TwinCat SystemManager ändert.

Hat dafür jemand eine Lösung

die "Connectete" Variable wird mittels eines Timers alle 50ms an zB
me.lblTest.Text = var1 übergeben

Aber wie gesagt die var1, welche Connected wurde wird nur bei Form Load geschrieben und dann nie wieder.

MFG
Parallax


----------



## drfunfrock (9 April 2008)

Das OCX-Ding ist veraltet. Bei jeder TwinCat-Demo ist auch ein .Net2.0 Interface dabei. Ich poste hier mal ein paar Klassen, die ich so verbrochen habe: 

*In Arbeit
*


----------



## Parallax (9 April 2008)

Danke für die Info....

nun allerdings noch eine paar kleine bitten

also.... 

so etwas ähnliches hab ich mir schon gedacht, allerdings kann ich auf Beckhoff.de keine neue version von dem OCX teil finden geschweige den wie man dass einbindet


könntest du mir bitte einen Link geben, damit ich mir das neuste ziehen kann...

zweites Problem:


also ich hab ein Form... 
dieses Form enthält eine Klasse, nämlich
Public Class frmMain

wo genau muss ich da nun was hinschreiben und was genau bedeutet das was ich da schreibe...^^

könntest du mir bitte anhand eines Beispiels erklären wir ich eine Integervariable (ich benutze in der regel die Addresse nach folgendem Schema: 61741,0,2,usw...) connectet und dann diesen wert in einer variable überträgt...


vielen dank für die anstrengung

mfg
Parallax


----------



## drfunfrock (9 April 2008)

*Teil1*

Also OCX ist out und .Net-Interface wird von Beckhoff geliefert. Hier ein Bsp. 

*Ankopplung Klasse Teil 1:*


```
Public Delegate Sub EventChangedVar(ByVal sender As Object, ByVal e As PLCVariableChangedEventArg)
Public Delegate Sub AsyncChangeEvent(ByRef v As System.Collections.Generic.List(Of PLCVarPoolElement))

Public Class PLCBase

    Private PLCThread As Thread
    Private prioA_thread As Thread
    Private prioB_thread As Thread
    Private prioC_thread As Thread
    Private RunThreads As Boolean

    Private timeA As Integer = 500
    Private timeB As Integer = 2000
    Private timeC As Integer = 4000
    Private timePLC As Integer = 500

    Private tcADS As TcAdsClient
    Private ADSAdress As String
    Private ADSPort As Integer
    Private ADSTimeout As Integer = 100
    Private ADSConnectState As ADSConnectState
    Private ADSState As TwinCAT.Ads.AdsState

    Private State As String

    Private VarDic As System.Collections.Generic.Dictionary(Of String, PLCVarPoolElement)

    Public Event OnPLCVarChange As PLCVarChangeHandler
    Public Event OnPLCConnectMsg As PLCConnectMsgHandler

    Private lock As New Object()



    Public Sub New(ByVal ADSAdress As String, ByVal ADSPort As Integer)
        MyBase.New()
        Me.ADSAdress = ADSAdress
        Me.ADSPort = ADSPort
        VarDic = New System.Collections.Generic.Dictionary(Of String, PLCVarPoolElement)
    End Sub

    Public Sub New(ByVal ADSAdress As String, ByVal ADSPort As Integer, ByVal Timeout As Integer)
        MyBase.New()
        Me.ADSAdress = ADSAdress
        Me.ADSPort = ADSPort
        Me.ADSTimeout = Timeout
        VarDic = New System.Collections.Generic.Dictionary(Of String, PLCVarPoolElement)
    End Sub

    Public Sub AddPLCVar(ByVal name As String, ByVal path As String, ByVal type As PLCType, ByVal timeclass As PLCTimeClass, Optional ByVal size As Integer = 1)
        VarDic.Add(name, New PLCVarPoolElement(name, path, type, timeclass, size))
    End Sub


    Protected Sub GetPLCVars()
        For Each element As PLCVarPoolElement In Me.VarDic.Values
            Dim var As PLCVariable
            Select Case element.PLCType
                Case PLCType.PLCArrayInteger
                    var = New PLCVarArrayInteger(Me, element.PLCPath, element.PLCSize, element.PLCTimeClass)
                Case PLCType.PLCArrayUInteger
                    var = New PLCVarArrayUInteger(Me, element.PLCPath, element.PLCSize, element.PLCTimeClass)
                Case PLCType.PLCBoolean
                    var = New PLCVarBoolean(Me, element.PLCPath, element.PLCTimeClass)
                Case PLCType.PLCDate
                    var = New PLCVarDate(Me, element.PLCPath, element.PLCTimeClass)
                Case PLCType.PLCDInteger
                    var = New PLCVarDInteger(Me, element.PLCPath, element.PLCTimeClass)
                Case PLCType.PLCUDInteger
                    var = New PLCVarUDInteger(Me, element.PLCPath, element.PLCTimeClass)
                Case PLCType.PLCInteger
                    var = New PLCVarInteger(Me, element.PLCPath, element.PLCTimeClass)
                Case PLCType.PLCUInteger
                    var = New PLCVarUInteger(Me, element.PLCPath, element.PLCTimeClass)
                Case PLCType.PLCDouble
                    var = New PLCVarDouble(Me, element.PLCPath, element.PLCTimeClass)
                Case PLCType.PLCString
                    var = New PLCVarString(Me, element.PLCPath, element.PLCSize, element.PLCTimeClass)
                Case Else
                    'var = Nothing
                    Throw New PLCException("PLC type is not implementet!")
            End Select
            element.PLCVariable = var
        Next
    End Sub

    Private Sub DropPLCVars()
        For Each element As PLCVarPoolElement In Me.VarDic.Values
            Try
                If Not (element.PLCVariable Is Nothing) Then
                    element.PLCVariable.Dispose()
                    element.PLCVariable = Nothing
                End If
            Catch ex As Exception
            End Try
        Next
    End Sub


    Protected Sub Connect()
        Me.tcADS = New TcAdsClient()
        Me.tcADS.Synchronize = True
        Me.tcADS.Connect(Me.ADSAdress, Me.ADSPort)
        Me.tcADS.Timeout = ADSTimeout
        AddHandler tcADS.AdsStateChanged, AddressOf AdsStateChangedEventHandler
    End Sub

    Protected Sub Disconnect()
        Try
            If Not (Me.tcADS Is Nothing) Then
                SyncLock Me.tcADS
                    Me.tcADS.Dispose()
                    Me.tcADS = Nothing
                End SyncLock
            End If
        Catch ex As TwinCAT.Ads.AdsException

        End Try
    End Sub

    Private Sub SendConnectMsg(ByVal msg As String)
        RaiseEvent OnPLCConnectMsg(Me, New PLCConnectMessageEventArg(msg))
    End Sub


    Private Sub PLCVarsRead(ByVal type As PLCTimeClass)


        Dim vars As System.Collections.Generic.List(Of PLCVarPoolElement) = New System.Collections.Generic.List(Of PLCVarPoolElement)
        SyncLock lock

            For Each element As PLCVarPoolElement In VarDic.Values
                If element.PLCTimeClass = type Then
                    Try
                        element.PLCVariable.Read()
                        If element.PLCVariable.Changed() Then
                            vars.Add(element)
                        End If
                    Catch ex As Exception
                        MsgBox(ex.Message.ToString)
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSCleanUp
                        Return
                    End Try
                End If
            Next
        End SyncLock
        If vars.Count > 0 Then
            RaiseEvent OnPLCVarChange(Me, New PLCVariableChangedEventArg(vars))
        End If
    End Sub

    Private Sub PLCVarsRead2(ByVal type As PLCTimeClass)


        Dim vars As System.Collections.Generic.List(Of PLCVarPoolElement) = New System.Collections.Generic.List(Of PLCVarPoolElement)
        SyncLock lock

            For Each element As PLCVarPoolElement In VarDic.Values
                If element.PLCTimeClass = type Then
                    Try
                        element.PLCVariable.Read()
                        vars.Add(element)
                    Catch ex As Exception
                        MsgBox(ex.Message.ToString)
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSCleanUp
                        Return
                    End Try
                End If
            Next
        End SyncLock
        If vars.Count > 0 Then
            RaiseEvent OnPLCVarChange(Me, New PLCVariableChangedEventArg(vars))
        End If
    End Sub


    Private Sub ADSCleanUp()
        DropPLCVars()
        Disconnect()
    End Sub
```


----------



## drfunfrock (9 April 2008)

*Teil2*

*Ankopplung Teil2

*

```
Private Sub ConnectStateMachine()
        While True
            Select Case Me.ADSConnectState
                Case BECKADS2.ADSConnectState.ADSInitialize
                    SendConnectMsg("Initialize " + Me.ADSAdress.ToString + ":" + Me.ADSPort.ToString)
                    Me.ADSConnectState = BECKADS2.ADSConnectState.ADSTryConnectToPLC
                    If Not RunThreads Then
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSExit
                    End If

                Case BECKADS2.ADSConnectState.ADSTryConnectToPLC
                    SendConnectMsg("Connecting " + Me.ADSAdress.ToString + ":" + Me.ADSPort.ToString)
                    Try
                        Connect()
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSWaitOnRun
                    Catch ex As TwinCAT.Ads.AdsException
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSTryConnectToPLC
                    End Try
                    If (Not RunThreads) Then
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSExit
                    End If

                Case BECKADS2.ADSConnectState.ADSWaitOnRun
                    SendConnectMsg("Check for PLC-state RUN at " + Me.ADSAdress.ToString + ":" + Me.ADSPort.ToString)
                    Try
                        If Me.ADSClient.ReadState().AdsState = TwinCAT.Ads.AdsState.Run Then
                            Me.ADSConnectState = BECKADS2.ADSConnectState.ADSCheckPLCProgram
                        End If
                    Catch ex As TwinCAT.Ads.AdsException
                        Disconnect()
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSTryConnectToPLC
                    End Try
                    If (Not RunThreads) Then
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSExit
                    End If

                Case BECKADS2.ADSConnectState.ADSCheckPLCProgram
                    SendConnectMsg("Check for PLC-program at " + Me.ADSAdress.ToString + ":" + Me.ADSPort.ToString)
                    Try
                        Dim plc_version As New PLCVarString(Me, ".VERSION", 1)
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSConnectFields
                        plc_version.Dispose()
                    Catch ex As TwinCAT.Ads.AdsException
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSCheckPLCProgram
                    End Try
                    If (Not RunThreads) Then
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSExit
                    End If

                Case BECKADS2.ADSConnectState.ADSConnectFields
                    SendConnectMsg("Connecting PLC vars at " + Me.ADSAdress.ToString + ":" + Me.ADSPort.ToString)
                    Try
                        Me.GetPLCVars()
                        Dim plc_version As New PLCVarString(Me, ".VERSION", 50)
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSConnectFields
                        plc_version.Dispose()
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSConnected

                    Catch ex As TwinCAT.Ads.AdsException
                        Me.DropPLCVars()
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSCheckPLCProgram
                    End Try
                    If (Not RunThreads) Then
                        Me.ADSConnectState = BECKADS2.ADSConnectState.ADSExit
                    End If

                Case BECKADS2.ADSConnectState.ADSConnected
                    SendConnectMsg("Connected at " + Me.ADSAdress.ToString + ":" + Me.ADSPort.ToString)
                    SyncLock Me.lock
                        If Me.ADSConnectState = BECKADS2.ADSConnectState.ADSConnected Then
                            Try
                                If Me.ADSClient.ReadState().AdsState <> TwinCAT.Ads.AdsState.Run Then
                                    Me.ADSConnectState = BECKADS2.ADSConnectState.ADSWaitOnRun
                                    Me.DropPLCVars()
                                End If
                            Catch ex As TwinCAT.Ads.AdsException
                                Me.ADSConnectState = BECKADS2.ADSConnectState.ADSCleanUp
                            End Try
                        End If
                        If (Not RunThreads) Then
                            Me.ADSConnectState = BECKADS2.ADSConnectState.ADSExit
                        End If
                    End SyncLock

                Case BECKADS2.ADSConnectState.ADSCleanUp
                    SendConnectMsg("Clean up " + Me.ADSAdress.ToString + ":" + Me.ADSPort.ToString)
                    Me.ADSCleanUp()
                    Me.ADSConnectState = BECKADS2.ADSConnectState.ADSTryConnectToPLC

                Case BECKADS2.ADSConnectState.ADSExit
                    SendConnectMsg("Closed " + Me.ADSAdress.ToString + ":" + Me.ADSPort.ToString)
                    Me.ADSCleanUp()
                    Exit While
            End Select
            Thread.Sleep(timePLC)
        End While
    End Sub
    Private Sub thread_a()
        While RunThreads
            If Me.ADSConnectState = BECKADS2.ADSConnectState.ADSConnected Then
                Me.PLCVarsRead(PLCTimeClass.A)
            End If
            Thread.Sleep(timeA)
        End While
    End Sub

    Private Sub thread_b()
        While RunThreads
            If Me.ADSConnectState = BECKADS2.ADSConnectState.ADSConnected Then
                Me.PLCVarsRead(PLCTimeClass.B)
            End If
            Thread.Sleep(timeB)
        End While
    End Sub

    Private Sub thread_c()
        While RunThreads
            If Me.ADSConnectState = BECKADS2.ADSConnectState.ADSConnected Then
                Me.PLCVarsRead(PLCTimeClass.C)
            End If
            Thread.Sleep(timeC)
        End While
    End Sub

    Public Sub AdsStateChangedEventHandler(ByVal sender As Object, ByVal e As TwinCAT.Ads.AdsStateChangedEventArgs)
        Me.ADSState = e.State.AdsState
        Select Case Me.ADSState
            Case ADSState.Config
            Case ADSState.Error
            Case ADSState.Init
            Case ADSState.Invalid
            Case ADSState.LoadConfig
            Case ADSState.PowerFailure
            Case ADSState.PowerGood
            Case ADSState.Reconfig
            Case ADSState.Reset
            Case ADSState.Resume
            Case ADSState.Run
            Case ADSState.SaveConfig
            Case ADSState.Shutdown
            Case ADSState.Start
            Case ADSState.Stop
            Case ADSState.Suspend
        End Select
    End Sub

    Public Sub StartThreads()
        RunThreads = True
        Me.PLCThread = New Thread(AddressOf ConnectStateMachine)
        Me.PLCThread.Priority = ThreadPriority.Normal
        Me.PLCThread.IsBackground = True
        Me.PLCThread.Start()

        Me.prioA_thread = New Thread(AddressOf thread_a)
        Me.prioA_thread.Priority = ThreadPriority.BelowNormal
        Me.prioA_thread.IsBackground = True
        Me.prioA_thread.Start()

        Me.prioB_thread = New Thread(AddressOf thread_b)
        Me.prioB_thread.Priority = ThreadPriority.Lowest
        Me.prioB_thread.IsBackground = True
        Me.prioB_thread.Start()

        Me.prioC_thread = New Thread(AddressOf thread_c)
        Me.prioC_thread.Priority = ThreadPriority.Lowest
        Me.prioC_thread.IsBackground = True
        Me.prioC_thread.Start()

    End Sub

    Public Sub StopThreads()
        RunThreads = False
        Me.prioA_thread.Join()
        Me.prioB_thread.Join()
        Me.prioC_thread.Join()
        Me.PLCThread.Join()
    End Sub


    Public Sub SetTimes(ByVal timeA As Integer, ByVal timeB As Integer, ByVal timeC As Integer, ByVal timePLC As Integer)
        Me.timeA = timeA
        Me.timeB = timeB
        Me.timeC = timeC
        Me.timePLC = timePLC
    End Sub

#Region "Properties"
    Public Property Adress() As String
        Get
            Return ADSAdress
        End Get
        Set(ByVal Value As String)
            ADSAdress = Value
        End Set
    End Property

    Public Property Port() As Integer
        Get
            Return ADSPort
        End Get
        Set(ByVal Value As Integer)
            ADSPort = Value
        End Set
    End Property

    Public ReadOnly Property ADSClient() As TcAdsClient
        Get
            Return Me.tcADS
        End Get
    End Property

    Public Property Timeout() As Integer
        Get
            Return ADSTimeout
        End Get
        Set(ByVal Value As Integer)
            ADSTimeout = Value
        End Set
    End Property

    Public ReadOnly Property ConnectState() As ADSConnectState
        Get
            Return Me.ADSConnectState
        End Get
    End Property

    Public ReadOnly Property PLCVar(ByVal name As String) As PLCVariable
        Get
            Return Me.VarDic.Item(name).PLCVariable
        End Get
    End Property

    Private ReadOnly Property PoolElements() As System.Collections.Generic.Dictionary(Of String, PLCVarPoolElement)
        Get
            Return Me.VarDic
        End Get
    End Property

    Public ReadOnly Property IsRunning() As Boolean
        Get
            Return Me.RunThreads
        End Get
    End Property

#End Region

End Class
```


----------



## drfunfrock (9 April 2008)

*Teil3*

_*Basisklasse zu den Variablen*_


```
Public Class PLCVariable
    Implements IDisposable
    Private mConnect As Boolean = False
    Protected VarPath As String
    Protected hVar As Integer = 0
    Protected adsStream As AdsStream
    Protected adsClient As TcAdsClient
    Protected VarSize As Integer
    Protected VarTimeClass As PLCTimeClass


    Public Sub New(ByRef connect As PLCBase, ByVal VarPath As String, ByVal Size As Integer, Optional ByVal timeclass As PLCTimeClass = KitronADS2.PLCTimeClass.X)
        MyBase.New()

        Me.adsClient = connect.ADSClient
        Me.Path = VarPath
        Me.VarSize = Size
        Me.TimeClass = timeclass

        Try
            Me.adsStream = New AdsStream(VarSize)
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

        Me.Connect()
    End Sub

    Public Sub Connect()
        Try
            adsClient.ReadState()
            Me.hVar = adsClient.CreateVariableHandle(VarPath)
            Me.mConnect = True
        Catch ex As Exception
            Me.mConnect = False
        End Try
    End Sub

    Public Overridable Sub Read()
        If (Not Me.Connected) Then
            Throw New PLCException("Connection to " + Me.VarPath + " broken")
        End If
    End Sub

    Public Overridable Sub Write()
    End Sub

    Public Overridable Function Changed() As Boolean
        Return True
    End Function

    Public Overloads Sub Dispose() Implements IDisposable.Dispose
        Me.adsStream.Close()
        Me.adsStream.Dispose()
        Me.adsStream = Nothing
        adsClient.DeleteVariableHandle(Me.hVar)
        ' Take yourself off of the finalization queue
        ' to prevent finalization code for this object
        ' from executing a second time.
        GC.SuppressFinalize(Me)
    End Sub


    Public Property Path() As String
        Get
            Return Me.VarPath
        End Get
        Set(ByVal value As String)
            Me.VarPath = value
        End Set
    End Property

    Public ReadOnly Property Handle() As Integer
        Get
            Return hVar
        End Get
    End Property

    Public ReadOnly Property Stream() As AdsStream
        Get
            Return adsStream
        End Get
    End Property

    Public ReadOnly Property Size() As Integer
        Get
            Return VarSize
        End Get
    End Property

    Public ReadOnly Property Connected() As Boolean
        Get
            Dim succ As Boolean = True
            Try
                Me.adsClient.ReadState()
            Catch ex As Exception
                succ = False
            End Try
            Return succ And Me.mConnect
        End Get
    End Property

    Public Property TimeClass()
        Get
            Return Me.VarTimeClass
        End Get
        Set(ByVal value)
            Me.VarTimeClass = value
        End Set
    End Property

End Class
```

*Konkrete Variablenklasse*


```
Public Class PLCVarInteger
    Inherits PLCVariable
    Private value As Int16
    Private oldvalue As Int16

    Public Sub New(ByRef connect As PLCBase, ByVal Path As String, Optional ByVal timeclass As PLCTimeClass = PLCTimeClass.X)
        MyBase.New(connect, Path, 2, timeclass)
    End Sub


    Public Overrides Sub Read()
        Dim reader As AdsBinaryReader
        MyBase.Read()

        reader = New AdsBinaryReader(Me.Stream)
        Me.adsClient.Read(Me.hVar, Me.adsStream)
        Me.adsStream.Position = 0
        oldvalue = value
        Me.value = reader.ReadInt16()
        reader = Nothing
    End Sub

    Public Overrides Sub Write()
        Dim writer As AdsBinaryWriter
        MyBase.Write()
        writer = New AdsBinaryWriter(Me.adsStream)
        Me.adsStream.Position = 0
        writer.Write(CType(Me.value, Int16))
        Me.adsClient.Write(Me.hVar, Me.adsStream)
        writer = Nothing
    End Sub

    Public Overrides Function Changed() As Boolean
        Return (oldvalue <> value)
    End Function

    Public Property val() As Int16
        Get
            Return Me.value
        End Get
        Set(ByVal Value As Int16)
            Me.value = Value
        End Set
    End Property

End Class
```



```
Public Delegate Sub PLCDelegateStringCallback(ByVal [text] As String)
Public Delegate Sub PLCDelegateIntegerCallback(ByVal [integer] As Integer)
Public Delegate Sub PLCDelegateUIntegerCallback(ByVal [uint] As UInteger)
Public Delegate Sub PLCDelegateBooleanCallback(ByVal [boolean] As Boolean)
```


----------



## drfunfrock (9 April 2008)

*Teil4*

Das ganze ist vor 2 Jahren entstanden und ich bin nicht wirklich zufrieden, weil  die Klasse von aufgerufnene Delegates mit .Net2 nicht herausbekomme. Somit muss ich im Programm immer noch folgende Konstruktion haben: 



```
Public Sub VariableChanged(ByVal sender As Object, ByVal e As PLCVariableChangedEventArg)
        For Each field As PLCVarPoolElement In e.fields
            Select Case field.PLCVarName
                Case "version"
                    Dim d As New BECKADS2.PLCDelegateStringCallback(AddressOf PLC_DispatchVersion)
                    Me.Invoke(d, New Object() {CType(field.PLCVariable, PLCVarString).val})
                Case "st01_carisin"
                    Dim d As New BECKADS2.PLCDelegateBooleanCallback(AddressOf PLC_DispatchCarIsIn)
                    Me.Invoke(d, New Object() {CType(field.PLCVariable, PLCVarBoolean).val})
                Case "st01_carinit"
                    Dim d As New BECKADS2.PLCDelegateBooleanCallback(AddressOf PLC_DispatchCarInit)
                    Me.Invoke(d, New Object() {CType(field.PLCVariable, PLCVarBoolean).val})
                Case "st01_carstatus"
                    Dim d As New BECKADS2.PLCDelegateIntegerCallback(AddressOf PLC_DispatchCarStatus)
                    Me.Invoke(d, New Object() {CType(field.PLCVariable, PLCVarInteger).val})
                Case "output"
                    Dim d As New BECKADS2.PLCDelegateIntegerCallback(AddressOf PLC_DispatchOutput)
                    Me.Invoke(d, New Object() {CType(field.PLCVariable, PLCVarInteger).val})
                Case "input"
                    Dim d As New BECKADS2.PLCDelegateIntegerCallback(AddressOf PLC_DispatchInput)
                    Me.Invoke(d, New Object() {CType(field.PLCVariable, PLCVarInteger).val})
                Case "st01_yield"
                    Dim d As New BECKADS2.PLCDelegateIntegerCallback(AddressOf PLC_DispatchST01Yield)
                    Me.Invoke(d, New Object() {CType(field.PLCVariable, PLCVarDInteger).val})
                Case "st03_yield"
                    Dim d As New BECKADS2.PLCDelegateIntegerCallback(AddressOf PLC_DispatchST03Yield)
                    Me.Invoke(d, New Object() {CType(field.PLCVariable, PLCVarDInteger).val})
                Case "st05_yield"
                    Dim d As New BECKADS2.PLCDelegateIntegerCallback(AddressOf PLC_DispatchST05Yield)
                    Me.Invoke(d, New Object() {CType(field.PLCVariable, PLCVarDInteger).val})
                Case "st07_yield"
                    Dim d As New BECKADS2.PLCDelegateIntegerCallback(AddressOf PLC_DispatchST07Yield)
                    Me.Invoke(d, New Object() {CType(field.PLCVariable, PLCVarDInteger).val})
                Case "st08_yield"
                    Dim d As New BECKADS2.PLCDelegateIntegerCallback(AddressOf PLC_DispatchST08Yield)
                    Me.Invoke(d, New Object() {CType(field.PLCVariable, PLCVarDInteger).val})
                Case "st01_labelcode"
                    Dim d As New BECKADS2.PLCDelegateStringCallback(AddressOf PLC_DispatchST01LabelCode)
                    Me.Invoke(d, New Object() {CType(field.PLCVariable, PLCVarString).val})
                Case "st02_i_dontsolder"
                    Dim d As New BECKADS2.PLCDelegateBooleanCallback(AddressOf PLC_DispatchSoldering)
                    Me.Invoke(d, New Object() {CType(field.PLCVariable, PLCVarBoolean).val})

                Case Else
                    Me.StatusStrip.Items("errormsg").Text = "unknown PLC variable:" + field.PLCVarName
            End Select
        Next
    End Sub
```
 Dazu habe ich Beckhoff misstraut und selbst Events bei Änderungen implementiert und das ist Müll. 


Nun ja, die Initialisierung ist einfach: 


```
Private Sub PLC_Init()
        Try
            Me.PLC_base = New BECKADS2.PLCBase(My.Settings.ADSNetID, My.Settings.ADSNetPort)
            AddHandler Me.PLC_base.OnPLCVarChange, AddressOf Me.VariableChanged
            AddHandler Me.PLC_base.OnPLCConnectMsg, AddressOf Me.StatusChanged
            AddFields()
            PLC_base.StartThreads()
        Catch ex As Exception
            MsgBox(ex.Message.ToString, MsgBoxStyle.Critical, "Critical failure in PLC_init!")
            PLC_base = Nothing
        End Try
    End Sub


    Private Sub PLC_Destroy()
        If Not (Me.PLC_base Is Nothing) Then
            PLC_base.StopThreads()
            PLC_base = Nothing
        End If
    End Sub

    Private Sub AddFields()
        PLC_base.AddPLCVar("version", ".Version", PLCType.PLCString, PLCTimeClass.C, 50)
        PLC_base.AddPLCVar("Var01", ".ST1.var01", PLCType.PLCBoolean, PLCTimeClass.A)
    End Sub
```


----------



## drfunfrock (9 April 2008)

Ach ja, die Bibliothe ist nicht vollständig, so wie ich die gepostet habe. Es ist nur als Implementierungsbeispiel gedacht.


----------



## Parallax (10 April 2008)

ähm.... ja

danke für die viele mühe nur die sache ist das ich seit ungefähr 2 monaten mit VB 2005 arbeite... daher hab ich von dem ganzen klassenzeugs und so keine ahnung... also das was mein stand ist, ist dass ich ein Steuerelement platziere, meine adresse eingeb und dann unter Form_Load einfach und bescheiden 

Call AdsOcx1.AdsReadIntegerConnect(Gruppe,Offset,Länge,Art,Time, "Var") 

schreib und dann meinen Wert hab....

so wie deine beispiele aussehen scheint das so als kann ich diese easy und ständig funtionale methode vergessen und darf mich nun durch kiloweise klassen und dämliches VB 2005 kämpfen...

ich frag mich warum man net einfach alles so lassen kann wie es gut war sondern nun son gewirr einführen muss....

aber scheinbar gehts ja wohl net anders

aber danke für die vielen beispiele die ich irgendwann 2010 mal alle verstehen werd...

mfg
Parallax


----------



## drfunfrock (10 April 2008)

Wenn du das nicht objektorientiert implementierst, dann bekommst du Probleme bei Verbindungsabrüchen und zwar ganz massive. Du musst nach einem Verbindungsabbruch, also einem Fehler in der Kommunikation ALLE Ressourcen wieder freigeben, sonst blockiert der PC sehr schnell und du darfst rebooten. Die Arbeit lohnt sich in jedem Falle. 

Meine Idee dahinter war, dass ich eine Verbindung aufbaue und alle Variablen, die ich connecte, in einer Liste sammle, damit ich bei einem Fehler alles elegant und schnell freigeben kann. So ein Fehler kann überall auftreten. Ohne Exceptions wird das zum Alptraum eines Programmierers.


----------



## Parallax (11 April 2008)

hallo

ich muss mich normal bei dir melden weil ich mit dem Zeug überhaupt net zurecht komm. Evt. sollte ich erwähnen das ich kein Programmierer bin sondern nur ein paar einfache Oberflächen mit ein paar simplen Bedingungen und Berechnungen in VB6 gecodet hab. Dazu zählen zum Beispiel ein Programm zum Auswerten eines Tischtennis oder Schafkopfturniers (^^) und ein paar Oberflächen für Maschinen wie zum Beispiel eine Statusanzeige für Schwerlastzylinder und ähnliches. Dabei hab ich halt immer meine Variablen dimensioniert und dann halt a weng was zam rechnen lassen, teilen, wurzeln, differenzieren und so weiter und dann halt irgedwo anzeigen lassen.

So meine Oberfläche und meine Maschinensteuerung funktionieren mittlerweile auch unter VB.Net oder 2005 und wie das jetzt heißt.

Das einzige was ich noch brauche ist die Kommunikation mit TwinCat.

Ich kann dir ja mal erklären was ich bisher gemacht hab.

Also ich habe mit des neue OCX dings geholt und dann mit Verweis hinzufügen in mein Projekt eingebunden.

Als nächstes hab ich im Code (ganz oben, also im allgemeinen Bereich)

Imports TwinCAT.Ads 

reingeschrieben. Das scheint dafür da zu sein um dieses OCX dings irgendwie zu implementieren

Als nächstes habe ich unter der Class des Forms 

Private tcClient As TcAdsClient

eingefügt.

Bis jetzt hab ich immer noch keine ahnung was diese Anweisung bedeuet aber scheint irgend eine Dimensionierung zu sein. Ich hab die nur reingeschrieben weil mir jemand gesagt hat ich solls reinschreiben....

So nun müsste ich ja irgendwie den Port und die NetId angeben damit das ding kommunizieren kann.

Unter Form Load steht bis jetzt

 tcClient = New TcAdsClient()

was das nun wieder genau bedeutet..: keine Ahnung

so aber nun müsste ich ja eine Var mit irgend etwas beschreiben

Also mit Dim varTest as Integer mal ne Testvar erstellt und dann hab ich gelesen brauch ich

varTest = tcClient.AddDeviceNotification(Gruppe,Offset,dataStream??,Länge,AdsTransMode.OnChange,Cycle,Delay,userData as Object???)

so das meiste is mir klar aber was ist ein dataStream oder was erwartet der da von mir und was is Userdata as Object. In VB6 kommt ja da der Name für die var rein die mit dem Wert beschrieben werden soll....


Nun ja etz weißt du auf was für einen Stand ich bin und was mir fehlt. Ich hab mir schon mehrere Codes angeschaut werd aber aus dem Objekt zeug net schlau... Also mir war die Art von VB6 wesentlich lieber... das hat man noch verstanden ohne Informatik gelernt zu haben.

MfG
Andre Wagner


----------



## drfunfrock (11 April 2008)

Streams sind die Datenströme in .Net. Dabei ist es nicht wichtig, ob etwas aus einer Datei, dem Speicher oder einer SPS kommt oder geschrieben wird, so die Theorie. Die verschiedenen Streams sind verschieden mächtig.

Du eröffnest einen Stream weil du Daten aus der SPS holen willst. Genauso gut kannst du einen Stream eröffnen, um eine Datei zu lesen.


----------



## Parallax (11 April 2008)

aja und wie eröffne ich einen solchen stream und welche "mächtigkeit" brauch ich dafür...

gibt es irgendwo deutschsprachige erklärungen zu den entsprechenden methoden und ähnliches....

wie gesagt ich benutzt vb.net erst seid 2 monaten und war die meiste zeit damit beschäftigt die oberfläche zu erstellen und mich da etwas reinzudenken...

und warum ich am anfang das 

   Private tcClient As TcAdsClient

schreibe weiß ich immer noch net^^....

ich hab mir auch ein paar bücher angeschaut aber da steht nur sowas drin wie eine klasse ist ein blablabla das nix davon wie ich das hinschreib und was das alles zu bedeuten hat..

für vb6 war wenigstens in der beckhoff doku explizit gestanden was man tun muss und was was in der anweisung heißt und so konnte ich das auch nachvollziehen aber hier stehen nur tausend fachbegriffe und ich hab keine ahnung mehr

mfg
andre wagner


----------



## drfunfrock (11 April 2008)

Du hast ein Problem mit der objektorientierten Programmierung. Lese das Buch zum herunterladen und lerne VB programmieren. 

http://download.galileo-press.de/openbook/visual_basic/galileocomputing_visual_basic.zip


Mit ein bisschen Suchen hättest du diverse Hilfen für VB.net gefunden.


----------



## Parallax (15 April 2008)

Hallo,

ich danke für die umfassenden antworten und Unterlagen die ich von dir bekommen hab. Allerdings habe ich dadurch aus festgestellt das ich ein schweres Problem habe.

Ich habe bis ende der Woche eine Frist für diese Anlage und das ist ein sehr großes Problem.

Kurzer Überblick zur erklärung:

Ich programmiere seit einigen Jahren SPS in einem kleineren Betrieb, was ich mir in größtenteils selbst oder über Bücher beigebracht habe.
Dazu gehört die Logo von Siemens, alle arten von Möller und ein paar wenige andere. Meist wurden damit nur kleine Maschinen mit maximal 40 Ein- und Ausgängen angesteuert.

Seid einiger Zeit mache ich das auch mit Beckhoff  da ich dort VB6 über Busskoppler verwenden kann. VB6 habe ich mir auch über die Jahre selbst beigebracht und konnte damit einiges bewerkstelligen. 
Nun habe ich eine neue Maschine und eine neue Steuerung, nämlich eine CX1010-xxxx und die Aus und Eingänge sind etwas mehr geworden. Die komplexität ist nicht das Problem das das Hauptprogramm mehr oder weniger komplett vorliegt und die Aufgaben erfüllt. 

Das Problem ist wie geschrieben die Kommunikation.
Ich ging beim erwerb dieser Steuerung von der einfachheit von VB6 aus und lies mich dazu überreden VS2005 zu verwenden da dies (so wurde mir gesagt) sich von den Anweisungen nicht stark von VB6 unterscheidet.

Nachdem sich Windows CE als ungenügend herausstellte habe ich auf einen Win XP rechner gewechselt, die Programmierung unter VS2005 is zwar wesentlich einfacher geworden und meine Oberfläche und Programmablauf sind größtenteils fertig aber das Problem an Kunden ist das sie diesen Aufwand nicht sehen sondern immer drehende Teile zu ihrer zufriedenheit verlangen. 
Wie ich ja nun auf grund deiner Unterlagen nachlesen konnte is das mehr als komplex und ich werde das bis Freitag nicht komplett schaffen.

Nun 2 Fragen die mehr oder weniger über leben und tot entscheiden^^:

gibt es von Beckhoff oder irgendwem anders eine dll oder sonst irgendetwas die einem den ganzen Müll von Klassen und sonst allem abnimmt so das man wieder auf seine ausreichend Primitive Call adsocx1.AdsReadIntegerConnect ( ... und so weiter kommt...??


2. Wenn es sowas nicht gibt, gibt es irgendwo eine stelle oder Hotline oder am besten aussendienst oder kurs oder was weiß ich auch immer der in ungeahnter geschwindigkeit (das heißt bis Freitag) das einem zeigt und erklärt.

Das Problem is nicht das ich etwas nicht verstehe wenn man mir sagt wozu diese anweisung da ist was sie tut was sie verlangt und so weiter...

Nur wenn ich ein Buch vor mir habe der mich mit Begriffen überschüttet und ich immern noch net so viel mehr von Streams weiß dann is das bis Freitag unmachbar....

Mfg
Parallax

PS: Ich kann in diesem Projekt leider nicht mehr auf VB6 wechseln da die anschaffungskosten für VS2005 mit in das Projekt mit einfließen und der kunde dann natürlich auch in dieser Version ein Programm haben willl


----------



## drfunfrock (15 April 2008)

Uppss, da bist du wirklich in einer schwierigen Situtation. Nein, es gibt ausser der ADS-Bibliothek keine weiteren Hilfen und das ist wirklich Mist. 

Ich empfehle: 

1) Werfe alles über Bord, was ich über das Freigeben von Ressourcen schrieb und mache es Straightforward. Das führt später zu kleineren Problemen, die aber als Bug verkauft werden können. 

2) Dann brauchts du sowieso eine Bibliothek, die eine Architektur gemäss meinen Angaben verlangt und schreibst das Programm mit Hilfe der Bibliothek neu. (dauert max 1Tag)


----------



## Parallax (15 April 2008)

hm ich hab ja über wochenende schon verschiedene bücher durchgelesen aber so schnell lernt man das leider nicht...

jetzt hab ich beckhoff am sonntag ne email geschrieben in der hoffnung das mir einer ihrer entwickler erklärt an einem auskommentierten beispielprogramm wie ich von anfang an nachdem ich das adsocx.dll eingebunden habe die verbindung aufbau und dann einen wert auslesen...

bekommt heute nachmittag antwort.. ich hoffe das dass was wird....

ich habe mir gestern noch gedacht naja kann ja net so schwer sein einfach ne ne verbindung herzustellen und dann einen wert zu lesen... nur wenns schon mal an dem stream scheitert weiß ich auch net...

mein chef hat schon angeboten er zahlt was wenn mir das jemand erklärt aber du wirst auch net aus der nähe von Hersbruck/Nürnberg kommen^^??

mfg
parallax


----------



## drfunfrock (15 April 2008)

Nee, ich komm nicht aus der Nähe  Ich bräuchte so mit dem Flugzeug (inkl. aller Wartezeiten grrr) so 1 Tag Anreisezeit und 1000Eu für einen Flug. Wenn ich nicht demnächst meinen Job wechseln sollte, können wir die Lib auf Sourceforge zusammen designen. Ich brauche sowieso eine verbesserte Version. Einen grossen Teil der Tipperei habe ich ja schon.


----------



## Parallax (15 April 2008)

naja ich hab mich für den nächsten kurs eingetragen allerdings hilft der mir für das projekt auch nix mehr....

hm... aber mal im ernst...

in vb6 brauchte ich zum connecten auf eine variable ca 3 minuten und dann gings...

des kann doch net denen ihr aller ernst sein das man nun mehr als ne stunde und n diplom in vb.net braucht um mich mit einer variable zu verbinden... 

also entweder bin ich in dem fall schwer von begriff oder ich übersehe einfach irgendwas....

wenn ich schon mal ne auflistung von den befehlen methoden und sonst was hab was mit des ADS teil bringt wäre ich ja schon mal sehr glücklich nur leider finde ich in dem Infosys von beckhoff nur zeug für vb.net... irgendwas will mich bei dem projekt tierisch verarschen...

mfg
parallax


----------



## drfunfrock (15 April 2008)

Nein, du hast recht, es ist einfach. Aber, die praktischen Probleme gibt es hinterher, denn wenn z.B. der HMI-PC heruntergefahren wird, ohne dass das Programm alle seine Variablen zur SPS freigegeben hat. Die wird dann irgendwann immer mehr CPU verbrauchen. Das kann man hervorragend sichtbar machen, wenn den FB aus der Systembibliothek nutzt und sich die CPU-Belastung anzeigen lässt. Die steigt dann nämlich. Ausserdem hatten wir Probleme mit dem Netzwerk und dann passiert ähnliches.  Meine einzigste Abwehr war, alles sehr geordnet  hoch und herunterzufahren. 

Damit ich dass _einfach_ machen konnte, habe ich alle Variablenverbindungen in eine Liste eines Objektes gelegt, und beim Beenden  des Programmes brauche ich nur noch zu schreiben: PLS.close, weil ich einfach mit einer Schleife alle Verbindungen durchgehen kann, anstatt 80 oder mehr Variablen freizugeben. So viel hatte ich nämlich in einem Programm und mir wurde das alles zu unübersichtlich. 

Hier bietet die Objektorientierung einfach das bessere Mittel, auch wenn es mehr Tippserei ist. 


Die Organisation ist so:

Hauptklasse ist 

"PLC"

- Legt die Verbindung zur SPS an und überwacht diese st¨ndig. Bei einem Timeout, werden alle Variablen freigeben und die Verbindung neu aufgebaut.
- Verwaltet alle Variablen 

Dann kommt 
"PLCVariable"

- Diese Klasse ist Wurzelklasse für alle Variablentypen wie z.B. PLCInteger
- Weil alle Valriablenklassen von "PLCVariable" abstammen, kann ich die in die Liste packen, ohne dass es Typkonflikte gibt. 


Um in eine Var vom Typ Int zu schreiben mache ich das einfach so: 

dim  t as PLCInteger = new PLCInteger('.X_Value')
t.val = 2
t.write
t.dispose

Das wars. Das ist auch der Sinn dieser Lib. EInmal geschrieben, nimmt die einem viel Arbeit ab und verhindert mögliche Fehler.


----------



## drfunfrock (15 April 2008)

Auf der Webseite unter Dokumentation->TwinCat 

findet man die ADS-Dokus. 

ftp://ftp.beckhoff.com/Software/TwinCAT/Infosystem/1033/chm/TcAdsNet.chm
ftp://ftp.beckhoff.com/Software/TwinCAT/Infosystem/1033/chm/TcAdsNetRef.chm
ftp://ftp.beckhoff.com/Software/TwinCAT/Infosystem/1031/chm/TcAdsCommon.chm

Zusatz zu meinem letzten Posting


----------



## Parallax (15 April 2008)

using System.IO, *TwinCAT.Ads

*das habe ich schon mal probiert wird aber von VB.net nicht anerkannt...

die lösung habe ich durch probieren gefunden in dem ich anstelle von using Imports verwendet habe...

kann es sein das sich von den beispielen einiges zu meiner version unterscheidet...

auch weisen die ; am ende der befehlszeilen auf C++ Code hin....

Ich hab mir das schonmal angeschaut allerdings sind die letzten beiden Files neu... entweder bin ich echt zu doof dieses system zu durchkämmen oder mein rechner will einfach net das ich finde wonach ich suche...

mfg
parallax


----------



## drfunfrock (15 April 2008)

Die Beispiele sind meistens in C# geschrieben. Da ich aber mind. schon 15Programmiersprachen hinter mir habe, war das für mich kein Problem. 

Ich rate dir, wenn du damit durch bist, dass Buch durchzulesen und VB langsam zu lernen. Die Hilfe in VB ist auch nicht so schlecht. Aber wenn man das noch nie gemacht hatr, rechne ich mit 3 Wochen Lehrzeit.


----------



## Parallax (15 April 2008)

using System.IO, *TwinCAT.Ads*;

This enables access to the types defined in TwinCAT.Ads without including  the name of the namespace. The class TcAdsClient is the core of the TwinCAT.Ads  class library and enables the user to communicate with an ads device. To begin  with an instance of the class must be created. Then a connection to the ADS  device is established by means of the Connect method.
*Establish a connection to an ADS device:*
TcAdsClient tcAds = new TcAdsClient(); 
tcAds.Connect("172.16.3.217.1.1",801);

hier fangen meine probleme schon mal an... 

ok von meinem C++ Wissen her muss ich am anfang erst mal das was ich brauche einbinden

laut dieser Anleitung geht das mit 
using System.IO, *TwinCAT.Ads*; 
allerdings ist das schon das erste was bei mir nicht funktioniert

using wird unterringelt also verwende ich Imports...
das wird angenommen und läuft

dann als nächstes 

TcAdsClient tcAds = new TcAdsClient(); 

ich verstehe nicht wozu diese befehl dient, soweit ich nun gelernt hab wird ein neues objekt mit dem namen
tcAds erstellt... allerdings wenn ich diesen befehl kopiere und einfüge wird schon der nächste fehler ausgegeben
nämlich das irgendetwas mit TcAdsClient nicht stimmt...

und somit stecke ich schon hier fest...

mfg
Parallax


----------



## Parallax (15 April 2008)

hm ok hab zu früh geantwortet.. wenn ich das mit dem Connect hinbekommen würde wäre ich ja schon viel weiter...

wie lauten den die anweisungen für VB.net

oder sind die wie ich es mir schon letzte woche gedacht habe auf VB.net nicht  verfügbar

mfg
parallax


----------



## Parallax (15 April 2008)

Sorry das ich dich jetzt damit belästigen muss aber das is im Moment wohl das einzige was ich machen kann....

ich habe ein neues Projekt erstellt und zeig dir mal den Quellcode bis jetzt:

Imports system.io, TwinCat.Ads 'Einbinden des TwinCad.Ads.dll verweises

Public Class frmTest

Dim tcAds as New TcAdsClient 'Objektvar mit dem Komischen TcAdsdings

Private Sub frmTest_Load(bla bla bla)

tcAds.Connect("127.255.255.1.1.1",301) 'verbinden mit lokalen Rechner und port der zusätzlichen Task (301)

End Sub
End Class

leider kann ich dir den Code nicht so Posten da ich am Inet PC kein VB hab und am VB rechner kein Inet

so das ganze schaut für mich etz mal logisch aus... habe ich bis hier schon mal nen fehler gemacht??

mfg
Parallax

PS: mei chef meint wenn des klappt wirst du mal zum Kaffetrinken eingeladen^^


----------



## drfunfrock (15 April 2008)

So das reicht, um einen Connect hinzubekommen: 


```
Imports TwinCAT.Ads

Dim tcADS As TcAdsClient
tcADS = New TcAdsClient()
tcADS.Synchronize = True
tcADS.Timeout = 1000
tcADS.Connect(ADSAdress, ADSPort)
```
Anschliessend kannst du eine Var so connecten:


```
handle = tcADS.CreateVariableHandle(VarPath)
```
VarPath hat immer einen Punkt voraus. Z.B. ".GlobalerZaehler"

Daher alle globalen Var müssen einem Punkt vorraus bekommen.


Den Code packst du in die Eventroutine zu einem Button.


----------



## drfunfrock (15 April 2008)

Freigeben einer Variablen: 

```
tcADS.DeleteVariableHandle(handle)
```
DAS IST EXTREM WICHTIG!


----------



## drfunfrock (15 April 2008)

Evtl. musst du unter Referenzen im "Solution Explorer" noch die .Net-Libs reinpacken


----------



## Parallax (15 April 2008)

hey du bist mein persönlicher messias...

also das mit dem Objekt versteh ich mittlerweile...

frage 1: für was is genau das syncro gut bzw was tut es...

timeout erklärt sich von selbst... denk ich zumindest 
naja connect is klar

so das mit dem CreateVariableHandle is doch sowas wie das auslesen per symbolic beim alten Call ads. bla prinzip...

gibt es auch eine möglichkeit per Group Offset u.ä. darauf zuzugreifen da doch bei der art und weise der Variablen name in TwinCat net verändert werden darf....

außerdem weiß ich nimmer wie man darauf zugegriffen hat....
war des net mit Task1.Ausgänge.Var1 oder so ähnlich??

warum ist das disconnecten so wichtig... also am besten ich packs bei Form unload ein weil dann werden ja alle verbindungen getrennt oder irre ich mich da irgendwie??

übrigens kaffeewasser kocht schon...


----------



## drfunfrock (15 April 2008)

War gut geholfen zu haben. Diese Forum ist eben auch für mich Gold wert. Die Hilfen sind hier unschätzbar. 

Zu Frage 1) Ich weiss nicht mehr wozu das gut ist. -> Les die Doku Heute Abend im Bett. 

Zu Frage 2) Ja die Möglichkeit gibt, siehe Bsp. in der Beckhoff-Doku. Ich ziehe das hier vor, weil wir keine statischen Anlagen haben und Änderungen einfach für mich zu machen sind. Unsere grosse Anlage fährt am Anschlag des Machbaren und jeder Start vom TwinCat-SystemManager kostet mich 5min, um den Offset herauszubekommen.  Dh. ich ziehe diese Methode vor.

Zu Frage 3) Die habe ich nicht verstanden

Zu Frage 4) Probier mal und connecte/disconnecte dich vielfach zur SpS mit mehreren Var auf die SPS und das ohne den Disconnect für die Vars. Wenn du dann den SystemManager startest und auf die RealTime-Settings schaust, bekommst du die CPU-Belastung heraus. Die steigt dann nämlich kontinuierlich.


----------



## Parallax (15 April 2008)

```
Imports system.io, TwinCat.Ads




Public Class frmTest
    Dim tcAds As New TcAdsClient()

    Dim varTest As Integer



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

        tcAds.Synchronize = True
        tcAds.Timeout = 1000
        tcAds.Connect("127.255.255.1.1.1", 301)


        varTest = tcAds.CreateVariableHandle("Task1.Eingänge.Test")







    End Sub

    Private Sub cmdArgh_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdArgh.Click

        Me.txtVar1.Text = varTest


    End Sub
End Class
```


so etz hab ich den Code mal daraufhin erweitert... 
nun sagt er mir bei dem punkte timeout "port not opend"

hm.... mein twincat system läuft... kann ich die fehlernummer 0x748 irgendwo bei beckhoff nachlesen??


----------



## drfunfrock (15 April 2008)

Siehe 

Beckhoff-Download-Dokumentation-Twincat->ADS...

ftp://ftp.beckhoff.com/Software/TwinCAT/Infosystem/1031/chm/TcAdsCommon.chm

Der Fehlercode besagt, ADS-Port ist nicht offen. Ich vermute, du solltest Port 801 benutzen, anstatt 301. Hast du das ADS-Routing eingestellt (inkl. Rebooten aller PCs) wenn dein Programm auf einem anderen PC läuft?


----------



## Parallax (15 April 2008)

hm

also das ganze ist etwas mystheriös.... 

das programm is bis zum tcAds.connect schon mal gelaufen... 

und nun sagt er mir der Port sei nicht geöffnet

Das TwinCat und mein Programm laufen am selben Rechner...

Die NetId ist also die Lokale....

Es wurden in einer Testconfig nur eine Task und eine Variable angelegt...

über ScopeView kann ich diese ja auslesen....

nur des VB bringt mir den Fehler bei .Timeout = 1000 Port is not open

ich verstehs net...
wenn ich mit der geschwindigkeit weiterarbeite bin ich am ende der Woche den auftrag los... langsam bin ich dabei zu überlegen das ganze einfach in VB6 zu schreiben weil da weiß ich das es geht...

mfg
Parallax


----------



## Ralle (15 April 2008)

Nicht das ich davon soviel Ahnung hab, aber vielleicht wurde der Port nicht korrekt geschlossen und ist damit belegt, bzw. wird als nicht offen bezeichnet?


----------



## drfunfrock (15 April 2008)

Wenn Twincat auf dem lokalen PC läuft, dann schalte mit dem Systemmanager Twincat in den Runmodus. Lade das Programm und starte es (2 verschiedene Vorgänge). Dann gebe keine Adresse an dh. nur "" und gebe Port 801 an. 

Das sollte klappen.


----------



## Majestic_1987 (6 April 2009)

Ich roll das hier mal auf.

Nachdem ich mich jetzt vergeblich an der OCX versucht habe, dachte ich, ich bau einfach die .Net in mein VB2008 ein.

Bekomme jetzt den selben Fehler wie Parallax.

Wenn ich über die OCX connecte auf port 801 läuft das Ding, mit der .Net nicht. Hat jemand dafür mittlerweile eine Lösung?

EDIT:
System = RUN
PLC = RUN


----------

