TwinCat Load Symbol Data @camper



  • Achso. Wieder was gelernt. 🙂

    Tu mir ehrlich gesagt noch schwer den ganzen Code zu verstehen.

    Auch mein Resharper hat noch Schwierigkeiten mit dem Code 😃
    Der zeigt mir noch ziemlich viele Fehler an.

    Aber kompilieren tut es jetzt.

    Zum Speicherverbrauch kann ich noch nichts sagen. Aber der Code ist nun um einiges komplexer geworden.

    Oftopic: Gibts eigentlich gute Schulungen die einem c++ und im speziellen die Neuerungen von c++ 11 bis c++17 vorstellen.



  • Nochmals zur Ordnerstruktur von ADS. Hierzu habe ich mit Beckhoff Rücksprache gehalten.

    Hier wurde mitgeteit das die Dateien im Verzeichnis:

    C:\TwinCAT\3.1\sdk\Include
    

    nur für interne Zwecke vorgesehen sind.

    Bitte nehmen Sie nur die Dateien aus den AdsApi Ordner!

    Also diesem hier.

    C:\TwinCAT\AdsApi\TcAdsDll\Include
    

    Ich weiß jetzt nicht inwiefern das sich nun mit deinem Code verträgt. Ich sollte es aber tunlichst vermeiden irgendwas zu verwenden das von unserem SPS lieferanten nicht unterstützt wird.


  • Mod

    booster schrieb:

    Zum Speicherverbrauch kann ich noch nichts sagen.

    Sicher etwas größer als in meinem ursprünglichen Code, weil die Daten nicht mehr in der kompakten Form gehalten werden, in der sie vom Netzwerk kommen. Andererseits werden keine Duplikate erstellt, so dass der Speicherverbrauch der gesamten Datenstruktur nur linear von der Größe der Netzwerkdaten abhängt. Ein davongallopieren des Verbrauchs wie zuvor ist ausgeschlossen.

    booster schrieb:

    Aber der Code ist nun um einiges komplexer geworden.

    Dafür kann er auch mehr 🙂

    Irgendetwas habe ich beim Experimentieren kaputtgemacht. Egal wie mein POU aussieht, ich erhalte keine Daten mehr darüber, bloss die paar Systemvariablen, die immer da sind. Irgendeine Idee dazu?

    booster schrieb:

    Oftopic: Gibts eigentlich gute Schulungen die einem c++ und im speziellen die Neuerungen von c++ 11 bis c++17 vorstellen.

    Wenn du jetzt noch nach C++11 fragen musst, wären eher ein paar Bücher angesagt. Die Antwort dazu überlasse ich mal Anderen, die einen besseren Überblick über die aktuelle Literatur haben.


  • Mod

    booster schrieb:

    Hier wurde mitgeteit das die Dateien im Verzeichnis:

    C:\TwinCAT\3.1\sdk\Include
    

    nur für interne Zwecke vorgesehen sind.

    Bitte nehmen Sie nur die Dateien aus den AdsApi Ordner!

    C:\TwinCAT\AdsApi\TcAdsDll\Include
    

    Wenn diese Dateien gepflegt und intern konsistent wären, wäre das ja auch kein Problem.

    Beispiel:

    TcAdsDef.h schrieb:

    typedef struct
    {
    	ADS_UINT32		entryLength;	// length of complete datatype entry
    ...
    	// GUID			typeGuid;		// typeGuid of this type if ADSDATATYPEFLAG_TYPEGUID is set
    	// ADS_UINT8	copyMask[];		// "size" bytes containing 0xff or 0x00 - 0x00 means ignore byte (ADSIGRP_SYM_VALBYHND_WITHMASK)
    } AdsDatatypeEntry, *PAdsDatatypeEntry, **PPAdsDatatypeEntry;
    

    Schön und gut. Nur dass ADSDATATYPEFLAG_TYPEGUID eben nirgends definiert ist, wie auch ADSIGRP_SYM_VALBYHND_WITHMASK.

    Die Sachen in <ads.h> an denen wir interessiert sind, sind ausschliesslich diese Stukturdefinitionen und die zugehörigen Konstanten.



  • Wenn du jetzt noch nach C++11 fragen musst,
    

    Wie meinst das?

    Denke die meisten Änderungen sind eher bei c++ 17 angesiedelt. Oder?
    Desweiteren bewege ich mich die meiste Zeit in c#. Und darf gerade halt de alten c++ code auf vorderman bringen.

    Weiß jetzt nicht ob die ganze komplexität des Programmes hier wegen des Technologiesprungs zu c++17 zu finden ist. Es ist halt eine ganz andere vorgehensweise die ich sonst kenne.

    Egal wie mein POU aussieht, ich erhalte keine Daten mehr darüber, bloss die paar Systemvariablen, die immer da sind. Irgendeine Idee dazu?

    Wo erhälst du keine Informationen mehr darüber? Aus deiner Schnittstelle.

    Teste mal vieleicht das Beispielprogramm von Beckhoff in .Net. Das listet einem die Informationen der Symbole auch auf.

    https://infosys.beckhoff.com/content/1031/tcsample_net/html/twincat.ads.sample06.htm?id=7147847683939335804



  • Die Sachen in <ads.h> an denen wir interessiert sind, sind ausschliesslich diese Stukturdefinitionen und die zugehörigen Konstanten.

    Die Frage ist warum sind "wir" daran interessiert. Ich hatte ja bisher die benötigten Informationen auch erhalten die ich benötigt hatte.

    Kann jetzt nicht sagen für was du ADSDATATYPEFLAG_TYPEGUID oder ADSIGRP_SYM_VALBYHND_WITHMASK benötigst. Oder auch die ganzen anderen Dinge.

    Ich glaube dir das dein Code viel mehr kann. Nur die Frage ist ob ich das benötige. Und bin ich kompatibel zu TwinCat2 und den zukünftig folgenden Versionen.

    Ich muss den Code hier nachher selber warten, und wenn ich nun meine eigene Wege ohne Beckhoff gehe bekomme ich von denen auch keinen Support mehr.


  • Mod

    booster schrieb:

    Die Sachen in <ads.h> an denen wir interessiert sind, sind ausschliesslich diese Stukturdefinitionen und die zugehörigen Konstanten.

    Die Frage ist warum sind "wir" daran interessiert. Ich hatte ja bisher die benötigten Informationen auch erhalten die ich benötigt hatte.

    Und woher weisst du dass du die richtigen Informationen (und nicht nur irgendwelche zufälligen Daten) erhalten hast? Das geht nur auf einem Weg: indem die Implemention mit der Spezifikation abgleichst (d.h. dass was im Header oder irgendeiner anderen Dokumentation dazu gelieferten wird) abgeglichen wird.

    Aber diese Spezifikation, wie sie geliefert wird, ist eben offenbar fehlerhaft.

    booster schrieb:

    Und bin ich kompatibel zu TwinCat2 und den zukünftig folgenden Versionen.

    Das hängt eben auch nur davon ab, ob das, was du geliefert bekommst, inkompatible Änderungen enthält. In dem Fall hast du verloren, egal was du machst: wenn du solchen Änderungen nicht folgst, funktioniert das Programm mit neuen Versionen nicht mehr, wenn du ihnen folgst, läuft es eben nicht mehr mit alten Versionen.

    Betrachte zum Beispiel das hier:

    #define	ADSDATATYPEFLAG_BITVALUES		0x00000020	// size and offs are in bits instead of bytes AND iGroup of main symbol incremented by 1!
    

    Das ist eine inkompatible Änderung des Protokolls, weil hier die Interpretation von Datenfeldern, die bereits eine wohldefinierte Bedeutung haben, geändert werden muss. Gleichzeitig wurde darauf verzichtet, diese Änderung in irgendeiner Form (wozu gibt es schließlich das version-Feld) kenntlich zu machen. Ein Programm, dass dieses Flag nicht kennt, wird mit Daten, die in dieser Form geliefert werden, Unfug anstellen.
    Umgekehrt hat ein Programm, dass dieses Flag kennt, kein Problem mit Daten, die dieses nicht enthalten, bleibt also zu alten Versionen kompatibel.
    Wenn ich mich also auf TcAdsDef.h - wie sie jetzt ist - beschränke, dann ist die Frage, ob der Code mit der aktuellen TwinCAT-Version kompatibel ist, ein einfaches nein. Es ist schlicht unmöglich, kompatibel zu programmieren, ohne diese Änderungen zu kennen.


  • Mod

    booster schrieb:

    Wo erhälst du keine Informationen mehr darüber? Aus deiner Schnittstelle.

    Nein, es werden schlicht keine Information dazu geliefert.
    Mit deinem kleinen

    PROGRAM MAIN
    VAR
        myInt:INT:=10;
    END_VAR
    

    gibt es kein Main.myInt mehr in den Daten (und ich kriege immer noch ganz normal Daten, mit all dem vordefinierten Zeug, dass immer da ist), die ich über das Netzwerk erhalte. Ich werde aber umgekehrt jedesmal beim Login gefragt, ob ich hochladen will, an fehlender Synchronisation kann es also nicht liegen.



  • Nein, es werden schlicht keine Information dazu geliefert.

    Das ist ja genau die Frage. Wo werden keine Informationen mehr geliefert.
    Über die Ads c++ Schnittstelle?
    Darum die Frage was liefert die .Net Schnittstelle?

    Und woher weisst du dass du die richtigen Informationen (und nicht nur irgendwelche zufälligen Daten) erhalten hast?

    Na weil ich mir ja anschauen und vergleichem kann was in TwinCat definiert ist und das nachher über die Schnittstelle geliefert wird. Und das hat bisher gepasst.

    Und wenn es nicht passt. Rufe ich Beckhoff an und sage da passt was nicht 😃

    Das geht nur auf einem Weg: indem die Implemention mit der Spezifikation abgleichst
    

    Welche Implementation. Die von Beckhoff?

    Das ist eine inkompatible Änderung des Protokolls, weil hier die Interpretation von Datenfeldern, die bereits eine wohldefinierte Bedeutung haben, geändert werden muss.

    Ich versteh nur Bahnhoff.

    ref_property<datatype_entry_prop::hasBitValues, flag< AdsDatatypeEntry, datatype_entry_prop::flags, ADSDATATYPEFLAG_BITVALUES>>,

    Das ist die einzige Stelle bei der du das Symbol verwendest. Und ehrlich gesagt habe ich Null Ahnung was du da überhaupt machst.



  • Also in der Mail von Beckhoff wird erklärt dass die Kommunikation intern zwischen den verschiedenen Modulen innerhalb von TwinCat auch auf die AdsKommunikation setzen. Hier bei kann es allerdings vorkommen dass die einzelnen Module verschiedene Versionen der AdsSchnittstelle benötigen. Darum kann es vorkommen das in den verschiedenen Headern Symbole mehrfach vorkommen aber anders definiert sind.

    Die AdsSchnittstelle für externe Anwendungen basiert aber auf der im AdsApi Ordner und diese Schnittstelle ist für TwinCat2 so wie TwinCat3 gleich.

    Heißt für mich ich muss diese auf jeden Fall einsetzen dass ich kompatibel zu beiden Systemen bin und weiterhin Support erhalte.


  • Mod

    booster schrieb:

    Nein, es werden schlicht keine Information dazu geliefert.

    Das ist ja genau die Frage. Wo werden keine Informationen mehr geliefert.
    Über die Ads c++ Schnittstelle?
    Darum die Frage was liefert die .Net Schnittstelle?

    Ah, jetzt verstehe ich die Frage. Sorry, war etwas verwirrt.
    ...
    testing
    ...
    Nope, die gesuchte Variable ist wirklich nicht da 😞

    booster schrieb:

    Und woher weisst du dass du die richtigen Informationen (und nicht nur irgendwelche zufälligen Daten) erhalten hast?

    Na weil ich mir ja anschauen und vergleichem kann was in TwinCat definiert ist und das nachher über die Schnittstelle geliefert wird. Und das hat bisher gepasst.

    Aha. Und du bist natürlich in der Lage, jeden möglichen Fall vorher zu testen und nicht verantwortlich, wenn später etwas schief geht, weil du etwas nicht bedacht hast. Weil nicht sein kann, was nicht sein darf 😉 Womit ich nicht sagen will, dass man Fehler komplett ausschliessen kann. Andereseits ersetzt aber Testen nicht eigenes Denken.

    booster schrieb:

    Das geht nur auf einem Weg: indem die Implemention mit der Spezifikation abgleichst
    

    Welche Implementation. Die von Beckhoff?[/code]

    Nein. Der Code deines Programmes. Was antwortest du, wenn dein Chef fragt, ob der Code funktioniert?

    Das ist eine inkompatible Änderung des Protokolls, weil hier die Interpretation von Datenfeldern, die bereits eine wohldefinierte Bedeutung haben, geändert werden muss.

    booster schrieb:

    Ich versteh nur Bahnhoff.

    ref_property<datatype_entry_prop::hasBitValues, flag< AdsDatatypeEntry, datatype_entry_prop::flags, ADSDATATYPEFLAG_BITVALUES>>,

    Das ist die einzige Stelle bei der du das Symbol verwendest. Und ehrlich gesagt habe ich Null Ahnung was du da überhaupt machst.

    Das ist deshalb die einzige Stelle, weil ich das Flag noch nicht benutze und also dessen Folgen noch nicht berücksichtigt werden. Bin ja erst 90% fertig.

    Der Code selbst ist rein deklarativ:
    die Zeile ist ja Teil einer Argumentliste und fügt die Spezialisierung von ref_property dieser Liste hinzu.
    ref_property ist ein paar aus einem int und einem Typ. Der Typ (flag<...>) enthält all den Code, der benötigt wird, um auf dieses Flag innerhalb der binären Daten zuzugreifen. structured_type ist nichts weiter als eine Aufzählung dieser int-Type-Paare und stellt praktisch eine map dar, die zur Compilezeit eine Zuordnung des ints zu diesem Typ ermöglicht (in properties_of<T>::get_accessor).

    Wozu das Ganze? Ich wollte eben nicht 1000 mal den gleichen Code schreiben. Denn wie auf einzelne Felder der Binärstruktur zuzugreifen ist, sieht ja immer mehr oder weniger gleich aus. Gerade wenn subtile Unterschiede bestehen, übersieht man diese aber leicht.
    Was ich also mache, ist erst mal abstrakt zu beschreiben, welche Art von Datenfeldern existieren, und wie auf diese zuzugreifen ist; das sind die verschiedenen Formen von Accessoren. Und im Anschluss wird in den Spezialisierungen von properties_of Zeile für Zeile, jedes einzelne Datenfeld aufgezählt und der dafür passende Accessor spezifiziert.
    Diese Zuordnung funktioniert nahezu 1:1, so dass man eben die Übereinstimmung mit der Spezifikation leicht überprüfen kann, sofern man sich außerdem überzeugt hat, dass
    1. die Accessoren das tun, was sie sollen, und
    2. auch der richtige Accessor ausgewählt wird.

    Die konkrete Zeile besagt letzlich, dass dem int Wert des enums dataype_entry_prop::hasBitValues der ein flag-Accessor zugeordnet ist, dieser Accessor hängt selbst von einer anderen Property (auf die per datatype_entry_prop::flags verwiesen wird) ab, verknüpft diesen Wert binär mit der angegebenen Maske (der 3.Templateparameter) und vergleicht das Ergebnis mit der Maske.

    Ohne diese Strukturen, hätte ich dem Template ref (oder alternativ entsprechend vielen normalen Klassen) entsprechend viele Zugriffsfunktionen spendieren müssen, gleichzeitig würde der Code zwischen diesen Funktionen zum Teil subtil varrieren, weil semantisch gleichartige Felder nicht immer denselben Namen haben oder an der gleichen Stelle in der Struktur gefunden werden. Das kannst du im Ansatz bereits in den adsDT und adsSym-Klassen sehen in dem Code, den ich ganz am Anfang gebracht hatte. Mit jedem weiteren Datenstruktur, die das Programm kennen soll, verschlimmert sich die Situation.
    Es ist wahrscheinlich auch nicht so, dass all die extra Information die du jetzt bekommen kannst, für dich nutzlos ist.
    Structured Text erlaubt ja beispielsweise wertbeschränkte Variablen:

    VAR
        myInt: INT (1..10);
    END_VAR
    

    Unabhängig davon, was dein Programm macht, ob bloß Überwachung oder auch Änderungen von Speicher, wirst du wahrscheinlich diese Beschränkungen beachten wollen. Die Information über diese Wertgrenzen wird aber durch Attribute gesendet, mit dem einfachen Beispielcode bekommst du sie nie zu sehen.


  • Mod

    Wenn ich im Menü auf TwinCat/Activate Configuration gehe, kommt die Meldung

    Device 'Gerät 1 (EtherCAT)' needs sync master (at least one variable linked to a task variable).

    Das war vorher nicht der Fall und ist evtl. die Ursache für mein Problem. Wie behebe ich das?



  • Die Meldung kenne ich wenn statt einem TwinCAT XAE Project (XML format) nur ein TwinCAT PLC Projekt angelegt wurde.

    Aber das hast du ja nicht wie du schon gesagt hast.
    Ich bin nicht der PLC Programmierer und unser Experte hier ist unterwegs.
    Drum kann ich nicht viel dazu sagen. Vieleicht einfach nochmals ein neues Projekt anlegen


  • Mod

    Neue VM aufgesetzt und geht wieder. Snapshot gemacht 😃


  • Mod

    Anleitung zum Dev-Maschine kaputtmachen:

    PROGRAM MAIN
    VAR
    	myInt : INT := 10;
    	aufzaehlung : (eins, zwei, drei);
    END_VAR
    

    Das ist absolut gültiger Code. Der Compiler ist damit glücklich und min Programm kann die Aufzählung super auslesen. Aber: sei nicht eingelogt, und wechsle zu tabular view: erfreue dich an einer sehr sehr langen Fehlermeldung in einer Messagebox und einem Absturz+Neustartaufforderung von Visual Studio.

    2. Variante: (die ich bisher nur durch zurückgehen auf einen früheren Snapshot lösen konnte, du bist gewarnt!)

    TYPE
    
    END_TYPE
    PROGRAM MAIN
    VAR
    	myInt : INT := 10;
    END_VAR
    

    Das ist nat. kein legaler Code, der Compiler stört sich daran aber nicht und erzeugt gerne ein Programm, in dem main fehlt (wie zuvor beschrieben). Die Situation bleibt so, selbst wenn der fehlerhafte type-Block entfernt wird. Windowsneustart, Anlegen eines neuen Projektes etc. helfen nicht.
    Ist das wirklich Software, die im Produktiveinsatz ist und mit Geld verdient wird? Wobei ich verstehen kann, dass der Support Geld einbringt...



  • Variante 1 ist kein legaler code. Keine Typdefinition in einem POU. Dafür gibt es die DUTs. Dass die Variante kompiliert wußte ich allerdings nicht. Da hätte ich auch einen Fehler erwartet.

    Aber Variante ist bis auf den genannten fehlerhaften Type-block eigentlich gültiger Code. Main darf leer sein.

    Ist das wirklich Software, die im Produktiveinsatz ist und mit Geld verdient wird?

    Ja 🙂

    TwinCat basiert auf codesys -> https://www.codesys.com/

    Was da Beckhoff noch alles dazu erfunden hat weiß ich nicht.
    Wobei der Support von Beckhoff kostenlos ist wenn man Kunde dort ist (Hardware)



  • Jetzt nicht den Überblick verlieren.

    Das geht nur auf einem Weg: indem die Implemention mit der Spezifikation abgleichst

    Ich hatte den Satz nicht richtig verstanden.
    Mann muss die seine Implementation mit der Spezifikation (von Beckhoff) abstimmen?
    Na klar. Ich programmiere ja nach der Spezifikation.
    Aber woher weißt du dass die Spezifikation im Ordner 3.1\sdk gilt.
    Wie gesagt laut Beckhoff gilt für jedes Modul eine andere Spezifikation.

    2. Es ist interessant welche Informationen du daraus rausziehen kannst. Auch wenn ich den Code nicht wirkliche verstehe. Aber ich benötige die Menge der Informationen auch gar nicht. Mir ist egal ob ein enum ein flag-Accessor zugeordnet ist oder nicht.
    Ich beobachte den Speicher auch nicht oder verändere ihn.
    Was ich benötige ist die Informationen der Variablen:

    Name
    IndexGroup
    IndexOffset
    Datatype
    Size

    mehr nicht

    damit ich mit AdsSyncReadWriteReq geziehlt die Variable beschreiben kann.

    Es ist toll und beeindruckend wie du dich in c++ auskennst aber aktuell komme ich damit meiner Lösung nicht näher.

    3. Ich habe deinen Code jetzt nochmals kopiert und in ein neues Visual Studio Projekt (VS 2017) eingefügt. Da ich es in meinem Projekt nicht zum laufen bekomme, da ich dort an verschiedenen Stellen die TcAdsDef.h und TcAdsAPI.h eingebunden habe.

    In dem neuen Projekt habe ich den Code erst mal komplett unverändert (bis auf #include "stdafx.h" -> Code um 1 Zeile verschoben) versucht zu kompilieren. Erhalte hier aber noch 4 Fehler:

    Error C3861 'exists': identifier not found adsdata.cpp 323
    Error C3861 'value': identifier not found adsdata.cpp 323
    Error C2664 'void std::vector<adsData::attributeInfo,std::allocator<_Ty>>::reserve(const unsigned int)': cannot convert argument 1 from 'void' to 'const unsigned int' adsdata.cpp 993
    Error C2664 'void std::vector<adsData::enumInfo,std::allocator<_Ty>>::reserve(const unsigned int)': cannot convert argument 1 from 'void' to 'const unsigned int' adsdata.cpp 999


  • Mod

    booster schrieb:

    Erhalte hier aber noch 4 Fehler:

    Error C3861 'exists': identifier not found adsdata.cpp 323
    Error C3861 'value': identifier not found adsdata.cpp 323
    Error C2664 'void std::vector<adsData::attributeInfo,std::allocator<_Ty>>::reserve(const unsigned int)': cannot convert argument 1 from 'void' to 'const unsigned int' adsdata.cpp 993
    Error C2664 'void std::vector<adsData::enumInfo,std::allocator<_Ty>>::reserve(const unsigned int)': cannot convert argument 1 from 'void' to 'const unsigned int' adsdata.cpp 999

    Stimmt. Komisch dass das bisher kompiliert hat.
    Die Zeile muss

    return optional<T, flag, Access>::exists(p, q) ? optional<T, flag, Access>::value(p, q) : default_value;
    

    lauten.



  • dann kommen die nächsten zwei Fehler

    Error	C3861	'get': identifier not found	AdsSymbolLoader	adsdata.cpp	259	
    Error	C2228	left of '.find' must have class/struct/union	adsdata.cpp	259
    

  • Mod

    Selbes Prinzip:

    ASSERT_THROW((var_data<T, data, length>::get(p, q).find('\0') == std::string_view::npos)); // no embedded \0
    

    ausserdem Zeile 196

    ASSERT_THROW((next_data<T, before, align>::get(p, q) == properties_of<T>::template get<expected>(p, q)));
    

    Richtiges 2-Phasen-Lookup ist bei Visual C++ leider seit Jahren immer noch WIP, da hängt es von der Mondphase ab, ob der Fehler gefunden wird.

    Ich habe noch ein paar andere Bugs gefixed, ausserdem adsData Konstruktoren spendiert wie besprochen.
    adsdata.h
    adsdata.cpp


Anmelden zum Antworten