Ereignisgesteuertes auslesen von Strukturen

adwaf

Level-1
Beiträge
13
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich will den Restweg einer Achse auslesen, jedoch beinhaltet dieser Indexoffset eine Struktur.
T9X8dNPOzhJZgAAAABJRU5ErkJggg==


handle = tcAds.AddDeviceNotification(0x4101, 0x00000014, ds, 0, 50, AdsTransMode.OnChange, 100, 0, null);
Wenn ich in meinen C# Programm eine DeviceNotification anlegen will bekomme ich jedes mal diesen Fehler
JvuHGNedB2BgbuDgf8DRWGRkpK0vB0AAAAASUVORK5CYII=


TwinCAT.Ads.AdsErrorException: 'Ads-Error 0x705 : Parameter size is incorrect. (Ads-Error 0x705 : Parameter size is incorrect.)'

Deswegen wollte ich Fragen ob jemand weiß, wie man Ereignisgesteuert Strukturen auslesen kann (mit einen anderen Offset kann ich nichts anfangen, da ich andere Strukturen auch auslesen muss)
 
Leider ist es in Beckhoff/TwinCAT nicht möglich Strukturen oder Arrays per Connected zu verbinden, also deren Änderungen zu "Abonnieren".
Dies ist nur bei einfachen Datentypen möglich, wobei ein String auch funktioniert (obwohl er aus bis zu 256 Byte besteht).
Will man eine Struktur oder ein Array nicht dauernd pollen, um Änderungen mitzubekommen, dann muss man jedes einzelne Element per Connected verknüpfen. Klingt zwar aufwendig, lässt sich aber in einer Schleife machen und kann durchaus lohnenswert sein, da man sich danach das stetige Polling spart und die Netzwerkauslastung damit erheblich verbessert wird.
 
Vielleicht wäre das etwas für dich
Observer pattern

Oh man... selbst drauf reingefallen... Der ursprüngliche Beitrag ist 3 Jahre alt. Das Problem sollte dich derweil erledigt haben...
 
Zuletzt bearbeitet:
Diese Stuktur hier funktioniert z.B. tadellos:

C#:
<StructLayout(LayoutKind.Sequential, Pack:=8)>
Public Structure ST_TimeStruct
    Implements IDisposable

    <MarshalAs(UnmanagedType.U2)>
    Public wYear As UInt16                          'Time struct: Year
    <MarshalAs(UnmanagedType.U2)>
    Public wMonth As UInt16                         'Time struct: Month
    <MarshalAs(UnmanagedType.U2)>
    Public wDayOfWeek As UInt16                     'Time struct: Day of week
    <MarshalAs(UnmanagedType.U2)>
    Public wDay As UInt16                           'Time struct: Day
    <MarshalAs(UnmanagedType.U2)>
    Public wHour As UInt16                          'Time struct: Hour
    <MarshalAs(UnmanagedType.U2)>
    Public wMinute As UInt16                        'Time struct: Minute
    <MarshalAs(UnmanagedType.U2)>
    Public wSecond As UInt16                        'Time struct: Second
    <MarshalAs(UnmanagedType.U2)>
    Public wMilliseconds As UInt16                  'Time struct: Milliseconds
    Public Sub Init()

    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        wYear = Nothing
        wMonth = Nothing
        wDayOfWeek = Nothing
        wDay = Nothing
        wHour = Nothing
        wSecond = Nothing
        wMilliseconds = Nothing
    End Sub

    Public Function GetCheckedPlcDate() As ST_TimeStruct
        Dim d As ST_TimeStruct = Me
        If d.wYear < 1900 Or d.wDay < 1 Or d.wDay < 1 Or d.wHour > 23 Or d.wMinute > 59 Or d.wSecond > 59 Then
            d.wYear = 1900
            d.wMonth = 1
            d.wDay = 1
            d.wHour = 0
            d.wMinute = 0
            d.wSecond = 0
        End If

        Return d
    End Function
    Public Function GetDateTime() As DateTime
        Dim d As ST_TimeStruct = GetCheckedPlcDate()
        Dim dt As DateTime
        Try
            dt = New DateTime(d.wYear, d.wMonth, d.wDay, d.wHour, d.wMinute, d.wSecond, d.wMilliseconds)
        Catch ex As Exception

        End Try
        Return dt
    End Function
End Structure
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Als Struktur nimmst Du offenbar keine eigene Struktur, sondern das TimeStruct aus der TwinCAT-Bibliothek - aber ok.
In Deinem Code kann ich nirgends einen TwinCAT-Zugriff sehen.
Kannst Du bitte auch den Teil, der für den TwinCAT-Connected-Zugriff zuständig ist posten?
Da müsste ja mindestens eine Routine sein, die den Connected-Zugriff aufbaut, sowie eine Callback-Routine, die aufgerufen wird, sobald sich ein Wert in der SPS ändert. Und in dieser Callback-Routine müsste über einen Parameter übergeben werden, welche PLC-Variable sich geändert hat.

So in der Art:
Anfordern eines Variablen-Handles vom TwinCAT-Server
Code:
iSuccess := AdsOcx.AdsReadVarConnectEx2(PlcVarName, ADSTRANS_SERVERONCHA, ACycleTime, iNewPlcVarHandle); // iSuccess=0 => kein Fehler

Callback-Routine:
Code:
procedure TTwinCATServerOCX.AdsOcxAdsReadConnectUpdateEx2(Sender: TObject; dateTime: TDateTime; nMs, hConnect: Integer;
    const data, hUser: OleVariant);

Falls Du es wirklich hinbekommen hast, ein struct per Connected zu verbinden und ein Update der Struktur bei jeder Veränderung einer Untervariablen des struct zu erhalten, dann würde mir das sehr weiterhelfen. Bin echt gespannt.
 
Zuletzt bearbeitet:
In Deinem Code kann ich nirgends einen TwinCAT-Zugriff sehen.
Ja sicher, danach hast Du ja auch nicht gefragt.
Zeig mir doch mal den Aufbau einer Struktur, die Du per Connected erfolgreich abonniert hast.
Das habe ich getan.

Wo die Struktur definiert ist, in einer Biblothek oder nicht, dürfte ja wohl kaum einen Unterschied machen.

Eines vorweg. Ich habe einen eigenen hochperformanten ADS-RT-Kernel für meine Visualisierungen selbst geschrieben. Der ist unter anderem multitasking fähig und managt selbstständig das An- und Abmelden der Abonnements beim Öffnen und Schließen der Fenster, kann eine verlorene Verbindung im Lauf wieder herstellen, verwaltet "shared notifications" und so weiter.

In meinem Code kannst Du also nirgends sehen, wie ich eine Struktur abonniere. Aber ich kann Dir sagen, dass ich die TwinCAT.Ads.dll in der Version 4.1.20.0 verwende und dort die Methode AddDeviceNotificationEx aufrufe und dann auf das Ereignis AdsNotificationEx warte.

Ich würde jetzt mal sagen: Zeig mir doch mal eine Struktur, die Du nicht abonnieren kannst.
 
Zurück
Oben