Temps de lecture : 8 minutes
Dans cet article de blog, trois différentes piles logicielles EtherCAT Master seront examinées. Pour chaque option et approche, seront présentés les avantages, les inconvénients, les principales différences entre ces 3 piles, ainsi que les coûts réels associés.
Cette comparaison présentera la solution EC-Master d'acontis Technologies ainsi que deux implémentations Open Source : IgH EtherCAT- Master® dans le cadre de l' EtherLab® distribué par IgH et la Simple Open EtherCAT Master ( SOEM ) principalement maintenu par rt-labs .
Ces trois piles EtherCAT sont disponibles sous forme de code source et peuvent être compilées pour différents systèmes d'exploitation et architectures de processeurs. Certaines nécessitant plus d'efforts que d'autres. Mais voyons le résultat de cette comparaison…
Historique/Contexte
La meilleure spécification d’une pile logicielle EtherCAT Maitre dans les années 2004 / 2005, était celle de EtherCAT Master Sample Code ( MSC ), car la version 1.0 de la spécification de communication EtherCAT n’indiquait pas de spécifications précises et détaillées pour la partie MAITRE (Master). Encore aujourd'hui, la spécification ETG.1000 EtherCAT et d'autres documents ne donnent toujours pas de définitions précises sur les spécifications d’une pile Maitre EtherCAT. Pour comprendre le fonctionnement d’une pile Maitre Ethercat presque tout le monde souhaitant concevoir une pile Maitre Ethercat doit en quelque sorte repenser le MSC pour comprendre les machines d'état, les algorithmes et les protocoles nécessaires au fonctionnement d'un réseau EtherCAT.
La pile EtherCAT : acontis EC-Master
acontis technologies GmbH a été fondée en 2001 et est une des premiers membres de l'EtherCAT Technology Group ( ETG ) depuis 2004. acontis a commencé le développement de sa propre pile logicielle EtherCAT Master (appelé par la suite EC-Master ) sur la base du MSC de Beckhoff, qui n'était et qui reste disponible uniquement que pour le système d'exploitation Windows (OS). Dans sa pile EC-Master, acontis a rajouté bon nombre de fonctions de gestion des erreurs car cela était manquant dans le code MSC . Le MSC n'avait pas non plus pour objectif de capturer tous les cas d'erreur. Au fil du temps, des fonctionnalités supplémentaires telles que la redondance des câbles, la connexion à chaud et la redondance du Maitre EtherCAT ainsi que de nombreuses autres fonctionnalités utiles ont également été ajoutées.
Après 20 ans de développement, EC-Master a été porté sur de nombreux systèmes d'exploitation, architectures de processeurs et contrôleurs Ethernet. Au fil du temps, acontis a acquis une expertise approfondie de la technologie EtherCAT et des applications temps réel. Les utilisateurs d' EC-Master apprécient notamment la réactivité et les connaissances de l'équipe d'acontis en matière d’assistance technique et de recherche de nouvelles solutions aux problèmes rencontrés.
Après 20 ans de développement, EC-Master a été porté sur de nombreux systèmes d'exploitation, architectures de processeurs et contrôleurs Ethernet. Au fil du temps, acontis a acquis une expertise approfondie de la technologie EtherCAT et des applications temps réel. Les utilisateurs d' EC-Master apprécient notamment la réactivité et les connaissances de l'équipe d'acontis en matière d’assistance technique et de recherche de nouvelles solutions aux problèmes rencontrés.
acontis EC-Master : architecture
EC-Master est principalement écrit en C++, mais des APIs pour C/C++, C# et Python sont également disponibles. Cette pile ne dépend pratiquement d'aucune bibliothèque tierce et n'a que deux interfaces avec le système d'exploitation et le contrôleur Ethernet. Cette abstraction vis-à-vis du matériel et de l'OS facilite la prise en charge de nouveaux systèmes d'exploitation, d’architectures processeurs ou adaptateurs réseau.
Figure 1 Architecture EC-Master
acontis EC-Master : Qui maintient le logiciel ?
Le produit est principalement maintenu par l'équipe technique acontis, mais les plus de 500 clients dans le monde contribuent à l'amélioration et l’evolution la pile EC-Master que ce soit en signalant des problèmes ou en proposant des évolutions.
acontis EC-Master : Types et Modèles de licence
Il existe 2 modèles de licences différents : Le logiciel est disponible soit sous forme de code objet (librairie) bibliothèque soit de code source. La licence est liée à un projet, à un système d'exploitation et une architecture de processeur spécifique. Des kits d'évaluation sont également disponibles permettant d’évaluer totalement la pile EC-Master avant d’acquérir le kit de développement logiciel (SDK). La pile EC-Master est soumise à des licences runtime lors que le produit développé passe en production. Le support technique et la maintenance logicielle de la pile sont assurés via un abonnement de maintenance facultatif
La pile EtherCAT : IgH EtherCAT Master® (EtherLab®)
Fondée en 1995, la société IgH Gesellschaft für Ingenieurleistungen mbH est spécialisée historiquement dans l’hydraulique. Au fil des ans, ils sont intervenus dans de nombreux projets spéciaux mécaniques et électromécaniques. En outre, l'IgH est devenu membre ETG (EtherCAT Technology Group) en mars 2004. La première version de l'IgH EtherCAT Master® dans le cadre du package EtherLab® remonte à août 2006 et traitait déjà de l’application du protocole CAN sur les services EtherCAT (CoE ) et d’Ethernet tunnellisé sur les services EtherCAT (EoE) à l'aide du principe de boîtes aux lettres. La dernière release qui a été éditée est la 1.5.2 datant de 2013, depuis cette pile n'a pas fait l’objet d’évolution continue.
IgH EtherCAT Master® : architecture
Heureusement, il existe une documentation pour l'IgH EtherCAT Master® qui donne une description détaillée de l'architecture. L'IgH EtherCAT Master® est implémenté en tant que module Linux Kernel Space et prend en charge les extensions Linux temps réel telle que Preempt RT. Les cartes réseau sont abstraites par modules de périphérique. La pile IgH EtherCAT Master® est dépendante du système d'exploitation Linux et est écrite en C.
Figure 2 Architecture IgH EtherCAT Master®
Un comportement singulier de cette pile maître EtherCAT que nous avons rencontré est que les données acycliques sont regroupées dans des trames cycliques. Cela a un certain effet sur le temps de cycle rencontré par certains équipements esclaves, en particulier lorsque le temps est pris à la réception complète de la trame.
IgH EtherCAT Master® : Qui maintient le logiciel ?
Florian Pose de l'IgH est responsable de presque tous les changements (>90%) de cette pile depuis sa première sortie. L'effort de travail et la persévérance de Florian sont admirables, sans pour autant nuire aux engagements des autres contributeurs.
IgH EtherCAT Master® : Termes de la licence
L'intégralité du code source disponible auprès d'IgH est sous licence GNU General Public License version 2 (GPLv2). Il faut donc tenir compte de cela lorsqu’on souhaite concevoir un produit basé sur cette pile EtherCAT car les codes sources dérivés devront éventuellement partagées avec la communauté.
Simple Open EtherCAT Master (SOEM)
Le Flanders Mechatronics Technology Center (FMTC) a décidé de rendre son implémentation maître EtherCAT (anciennement connue sous le nom de EtherCAT Master Library (EML)) accessible au public en 2006 . Selon certaines sources sur Internet, SOEM serait basée sur cette bibliothèque maître EtherCAT de FMTC. La pile EtherCAT SOEM a été développée et validée pour le système d'exploitation eCos. Certains des fichiers source nomment également Arthur Ketels de la Special Machinefabriek Ketels vof comme auteur. En outre, la TU/e Technische Universiteit Eindhoven est indiquée dans le fichier de licence.
Simple Open EtherCAT Master (SOEM) : architecture
La pile EtherCAT SOEM est écrite en C, et prête à l'emploi. elle s'exécute comme une application dans l’espace utilisateur du Kernel. Deux interfaces (API) assurent l’abstraction des drivers OS et Ethernet. Ces interfaces dépendent du système d'exploitation ainsi que de l'interface de la carte réseau et peuvent être implémentées avec environ 700 à 1 000 lignes de code. Il existe des portages pour une large gamme de systèmes d'exploitation et d'adaptateurs réseau différents (voir Supported Operating Systems, CPU architectures and Ethernet interfaces).
Figure 3 Architecture SOEM
Simple Open EtherCAT Master (SOEM) : Qui maintient le logiciel ?
Cette implémentation semble être soutenue et maintenue principalement par les employés de rt-labs et Arthur Ketels. La dernière version officielle remonte à juillet 2019 (v1.4.0).
Simple Open EtherCAT Master (SOEM) : Termes de la licence
À l'instar du IgH EtherCAT Master®, La pile SOEM est également sous licence GPLv2, mais avec une exception spéciale , il est autorisé de la compiler avec un code applicatif additionnel sans être obligé de partager ce code dérivé avec la communauté open source. rt-labs propose également une licence commerciale payante par produit/projet. La différence entre la version disponible gratuitement et la version commerciale n'est pas claire, bien qu'il semble qu'une partie de l'assistance et de la maintenance soit incluse dans la licence commerciale payante.
Systèmes d'exploitation, architectures CPU et interfaces Ethernet supportés
Dans le tableau suivant, nous comparons les combinaisons de système d'exploitation, d'architecture CPU et d'interface Ethernet prises en charge par ces piles logicielles EtherCAT. Parmi les systèmes d'exploitation, il existe des systèmes d'exploitation en temps réel (RTOS) et non temps réel (OS). Les architectures de processeur incluent 32 et 64 bits, ainsi que big et little-endian.
Comme les trois piles sont disponibles sous forme de code source, il est en principe possible de les porter sur chaque système d'exploitation, architecture et interface réseau existantes avec plus ou moins d'efforts. Par conséquent, nous nous concentrerons uniquement sur ce qui est actuellement disponible. Étant donné qu'acontis propose déjà ces informations et que nous effectuons cette comparaison pour nos clients et clients potentiels, nous ne pouvons garantir l’exactitude de ces informations que pour la pile l'EC-Master. De plus, comme nous n'avons pas été en mesure de compiler chaque pile pour chaque système d'exploitation, architecture et adaptateur réseau, nous nous appuyons sur ce qui est indiqué dans la documentation et sur ce que nous voyons dans le code source.
Comme les trois piles sont disponibles sous forme de code source, il est en principe possible de les porter sur chaque système d'exploitation, architecture et interface réseau existantes avec plus ou moins d'efforts. Par conséquent, nous nous concentrerons uniquement sur ce qui est actuellement disponible. Étant donné qu'acontis propose déjà ces informations et que nous effectuons cette comparaison pour nos clients et clients potentiels, nous ne pouvons garantir l’exactitude de ces informations que pour la pile l'EC-Master. De plus, comme nous n'avons pas été en mesure de compiler chaque pile pour chaque système d'exploitation, architecture et adaptateur réseau, nous nous appuyons sur ce qui est indiqué dans la documentation et sur ce que nous voyons dans le code source.
x support complet
x 1 quelqu'un l'a utilisé ou a essayé de l'utiliser dans un projet/quelques projets
x 2 en tant qu'application 32 bits sur Windows 64 bits
x 3 il existe du code
x 1 quelqu'un l'a utilisé ou a essayé de l'utiliser dans un projet/quelques projets
x 2 en tant qu'application 32 bits sur Windows 64 bits
x 3 il existe du code
Tableau 1 Systèmes d'exploitation, architectures de CPU et adaptateurs supportés
EC-Master prend en charge plus de 147 combinaisons différentes d'architectures de processeur, de systèmes d'exploitation et d'adaptateurs réseau. IgH EtherCAT Master® 21 et SOEM 7. 34 solutions pour Linux existent (26 par l'EC-Master et 8 Open Source). Il est important de noter le nombre de combinaisons disponibles pour EC-Master et la liste est encore incomplète. Une liste complète peut être trouvée sur la page des manuels de la pile. Il convient également de noter que SOEM est la seule pile qui prend en charge Erika Enterprise RTOS , un RTOS certifié OSEK/VDX pour l’automobile sans royalty.
Fonctionnalités maître EtherCAT prises en charge
Comme nous avons mis en évidence le système d'exploitation, les architectures et les adaptateurs Ethernet pris en charge, examinons également les fonctionnalités prises en charge selon le document EtherCAT Master Classes ETG.1500 pour une Master Class A. Les fonctionnalités importantes incluent la possibilité d'importer des fichiers d'informations réseau EtherCAT (ENI) (EtherCAT XML Master Configuration), documentation, gestion des erreurs et support.
Tableau 2 Caractéristiques des classes EtherCAT Master (ETG.1500)
Remplir le tableau ci-dessus était un défi pour les solutions open source car nous devions rechercher presque toutes les informations dans le code source lui-même. En effet, la documentation sur les fonctionnalités prises en charge n'est généralement pas disponible. La documentation IgH est plus complète que SOEM, cependant, la documentation acontis s'est avérée être la meilleure.
Si le champ IRQ des datagrammes EtherCAT n'est pas vérifié, les changements de topologie et d'état de l'esclave ne sont pas détectés immédiatement. Si votre application contient, par exemple, des modifications d'outils, cela peut vous inquiéter.
De nombreux fabricants d'esclaves définissent des commandes d'initialisation CoE obligatoires ("InitCmds") dans le fichier EtherCAT Slave Information (ESI) (EtherCAT Devices Description). Ces informations ne sont disponibles que dans le fichier ESI et ne peuvent pas être lues à partir de l'EEPROM de l'esclave car l'EEPROM ne contient généralement que des valeurs par défaut. Si les fichiers ESI ne peuvent pas être traités dans une ENI et lus par la pile, ces InitCmds doivent être implémentés manuellement pour que ces esclaves atteignent l'état opérationnel (OP) → pour chaque changement d'état pour chaque révision de ces esclaves. Cela peut être fastidieux. Veuillez-vous référer à l' annexe pour plus de détails.
Pour autant que nous puissions en juger, les deux piles open source n'ont pas de capacité d'importation ENI ni d'installations de communication esclave à esclave, par conséquent, elles ne prennent pas non plus en charge Safety over EtherCAT (FSoE = FailSafe over EtherCAT). S'il s'agit d'exigences actuelles ou futures pour votre projet, vous devez reconsidérer l'utilisation des piles open source.
Tableau 3 Traitement des erreurs
Un rapport détaillé sur tous ces cas de test et leurs résultats peut être obtenu sur demande. Comme le montre le tableau, la gestion des erreurs dans IgH est légèrement meilleure que dans SOEM. Le plus grand domaine où les piles open source manquent de gestion des erreurs est lors du démarrage du réseau.
Conclusion
En fonction de votre plate-forme (processeur, système d'exploitation, carte réseau, etc.) et d'autres exigences, de nombreuses bonnes solutions sont disponibles. Si vous avez un réseau très statique, petit et trivial, les implémentations open source peuvent être un bon choix. Toutefois, si la configuration de votre réseau EtherCAT est susceptible de changer et/ou est très complexe (par exemple, contient des lecteurs, des profils d'appareils modulaires (MDP)) ou des esclaves avec ou sans différentes révisions matérielles/logicielles, vous devez ajuster la configuration par défaut (par exemple, PDO mappage, commandes Init) alors vous devez sélectionner une pile qui peut importer des fichiers ENI comme acontis EC-Master.
Annexe : extraits de code pour initialiser un variateur Yaskawa Sigma
Open source
Vous trouverez ci-dessous un code de test SOEM pour initialiser la configuration PDO d'un variateur Yaskawa Sigma. Dans ce cas, il est écrit sur le changement d'état de PreOp à SafeOP. L'écriture d'une telle configuration PDO sur l'esclave est similaire à la solution IgH. Tous les index, sous-index et valeurs doivent être évalués, copiés et/ou calculés et codés en dur. Les méta-informations comme un commentaire pour le seul InitCmds sont manquantes. Comprendre ce qui se passe, en particulier dans le cas d'une mauvaise configuration ou d'une erreur, est beaucoup plus difficile. Travailler avec les fichiers ESI et ENI est évidemment plus pratique. C'est ce que nous disent les clients EC-Master. Voir aussi sous la liste suivante.
static int YaskawaSigmaDrivePDOConfiguration (uint16 slave)
{
int retval = 0;
uint8 ui8Val = 0;
uint16 ui16Val = 0;
uint32 ui32Val = 0;
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1c12, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
retval += ec_SDOwrite(slave, 0x1c13, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1a00, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 0x60410010;
retval += ec_SDOwrite(slave, 0x1a00, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1617166368;
retval += ec_SDOwrite(slave, 0x1a00, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618411536;
retval += ec_SDOwrite(slave, 0x1a00, 0x3, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1626603552;
retval += ec_SDOwrite(slave, 0x1a00, 0x4, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1616969736;
retval += ec_SDOwrite(slave, 0x1a00, 0x5, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 8;
retval += ec_SDOwrite(slave, 0x1a00, 0x6, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1622736312;
retval += ec_SDOwrite(slave, 0x1a00, 0x7, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1622802464;
retval += ec_SDOwrite(slave, 0x1a00, 0x8, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 8;
retval += ec_SDOwrite(slave, 0x1a00, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1a01, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614872592;
retval += ec_SDOwrite(slave, 0x1a01, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1617166368;
retval += ec_SDOwrite(slave, 0x1a01, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 2;
retval += ec_SDOwrite(slave, 0x1a01, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1a02, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614872592;
retval += ec_SDOwrite(slave, 0x1a02, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1617166368;
retval += ec_SDOwrite(slave, 0x1a02, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 2;
retval += ec_SDOwrite(slave, 0x1a02, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1a03, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614872592;
retval += ec_SDOwrite(slave, 0x1a03, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1617166368;
retval += ec_SDOwrite(slave, 0x1a03, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618411536;
retval += ec_SDOwrite(slave, 0x1a03, 0x3, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 3;
retval += ec_SDOwrite(slave, 0x1a03, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1600, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614804056;
retval += ec_SDOwrite(slave, 0x1600, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618608160;
retval += ec_SDOwrite(slave, 0x1600, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1627324448;
retval += ec_SDOwrite(slave, 0x1600, 0x3, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618018320;
retval += ec_SDOwrite(slave, 0x1600, 0x4, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618083856;
retval += ec_SDOwrite(slave, 0x1600, 0x5, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1616904200;
retval += ec_SDOwrite(slave, 0x1600, 0x6, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 8;
retval += ec_SDOwrite(slave, 0x1600, 0x7, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1622671376;
retval += ec_SDOwrite(slave, 0x1600, 0x8, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 8;
retval += ec_SDOwrite(slave, 0x1600, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1601, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614807056;
retval += ec_SDOwrite(slave, 0x1601, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618608160;
retval += ec_SDOwrite(slave, 0x1601, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 2;
retval += ec_SDOwrite(slave, 0x1601, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1602, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614807056;
retval += ec_SDOwrite(slave, 0x1602, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1627324448;
retval += ec_SDOwrite(slave, 0x1602, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 2;
retval += ec_SDOwrite(slave, 0x1602, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1603, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614807056;
retval += ec_SDOwrite(slave, 0x1603, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618018320;
retval += ec_SDOwrite(slave, 0x1603, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 2;
retval += ec_SDOwrite(slave, 0x1603, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui16Val = 5633;
retval += ec_SDOwrite(slave, 0x1c12, 0x1, FALSE, sizeof(ui16Val), &ui16Val, EC_TIMEOUTSAFE);
ui8Val = 1;
retval += ec_SDOwrite(slave, 0x1c12, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui16Val = 6657;
retval += ec_SDOwrite(slave, 0x1c13, 0x1, FALSE, sizeof(ui16Val), &ui16Val, EC_TIMEOUTSAFE);
ui8Val = 1;
retval += ec_SDOwrite(slave, 0x1c13, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 8;
retval += ec_SDOwrite(slave, 0x6060, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
printf("Servo slave %d set, retval = %d\n", slave, retval);
return 1;
}
{
int retval = 0;
uint8 ui8Val = 0;
uint16 ui16Val = 0;
uint32 ui32Val = 0;
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1c12, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
retval += ec_SDOwrite(slave, 0x1c13, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1a00, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 0x60410010;
retval += ec_SDOwrite(slave, 0x1a00, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1617166368;
retval += ec_SDOwrite(slave, 0x1a00, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618411536;
retval += ec_SDOwrite(slave, 0x1a00, 0x3, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1626603552;
retval += ec_SDOwrite(slave, 0x1a00, 0x4, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1616969736;
retval += ec_SDOwrite(slave, 0x1a00, 0x5, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 8;
retval += ec_SDOwrite(slave, 0x1a00, 0x6, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1622736312;
retval += ec_SDOwrite(slave, 0x1a00, 0x7, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1622802464;
retval += ec_SDOwrite(slave, 0x1a00, 0x8, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 8;
retval += ec_SDOwrite(slave, 0x1a00, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1a01, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614872592;
retval += ec_SDOwrite(slave, 0x1a01, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1617166368;
retval += ec_SDOwrite(slave, 0x1a01, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 2;
retval += ec_SDOwrite(slave, 0x1a01, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1a02, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614872592;
retval += ec_SDOwrite(slave, 0x1a02, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1617166368;
retval += ec_SDOwrite(slave, 0x1a02, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 2;
retval += ec_SDOwrite(slave, 0x1a02, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1a03, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614872592;
retval += ec_SDOwrite(slave, 0x1a03, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1617166368;
retval += ec_SDOwrite(slave, 0x1a03, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618411536;
retval += ec_SDOwrite(slave, 0x1a03, 0x3, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 3;
retval += ec_SDOwrite(slave, 0x1a03, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1600, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614804056;
retval += ec_SDOwrite(slave, 0x1600, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618608160;
retval += ec_SDOwrite(slave, 0x1600, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1627324448;
retval += ec_SDOwrite(slave, 0x1600, 0x3, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618018320;
retval += ec_SDOwrite(slave, 0x1600, 0x4, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618083856;
retval += ec_SDOwrite(slave, 0x1600, 0x5, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1616904200;
retval += ec_SDOwrite(slave, 0x1600, 0x6, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 8;
retval += ec_SDOwrite(slave, 0x1600, 0x7, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1622671376;
retval += ec_SDOwrite(slave, 0x1600, 0x8, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 8;
retval += ec_SDOwrite(slave, 0x1600, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1601, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614807056;
retval += ec_SDOwrite(slave, 0x1601, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618608160;
retval += ec_SDOwrite(slave, 0x1601, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 2;
retval += ec_SDOwrite(slave, 0x1601, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1602, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614807056;
retval += ec_SDOwrite(slave, 0x1602, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1627324448;
retval += ec_SDOwrite(slave, 0x1602, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 2;
retval += ec_SDOwrite(slave, 0x1602, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 0;
retval += ec_SDOwrite(slave, 0x1603, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
ui32Val = 1614807056;
retval += ec_SDOwrite(slave, 0x1603, 0x1, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui32Val = 1618018320;
retval += ec_SDOwrite(slave, 0x1603, 0x2, FALSE, sizeof(ui32Val), &ui32Val, EC_TIMEOUTSAFE);
ui8Val = 2;
retval += ec_SDOwrite(slave, 0x1603, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui16Val = 5633;
retval += ec_SDOwrite(slave, 0x1c12, 0x1, FALSE, sizeof(ui16Val), &ui16Val, EC_TIMEOUTSAFE);
ui8Val = 1;
retval += ec_SDOwrite(slave, 0x1c12, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui16Val = 6657;
retval += ec_SDOwrite(slave, 0x1c13, 0x1, FALSE, sizeof(ui16Val), &ui16Val, EC_TIMEOUTSAFE);
ui8Val = 1;
retval += ec_SDOwrite(slave, 0x1c13, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
ui8Val = 8;
retval += ec_SDOwrite(slave, 0x6060, 0x0, FALSE, sizeof(ui8Val), &ui8Val, EC_TIMEOUTSAFE);
while(EcatError) printf("%s", ec_elist2string());
printf("Servo slave %d set, retval = %d\n", slave, retval);
return 1;
}
EC-Master
Comme décrit précédemment, les fabricants d'esclaves EtherCAT fournissent généralement un fichier ESI avec leur appareil. La collection de tous les fichiers ESI de vos esclaves décrit votre réseau EtherCAT. Cette collection de fichiers est généralement traitée - principalement avec un outil graphique (par exemple EC-Engineer ) - dans une ENI. Cette ENI contient la description complète du réseau. Outre de nombreuses autres informations, également les commandes (InitCmds) à exécuter à chaque changement d'état de chaque esclave dans chaque révision. L' EC-Master lit toutes ces informations. Chaque fois qu'un changement d'état d'esclave est commandé à l' EC-Master et de la pile vers les esclaves, ces commandes InitCmd connectées à changement d'état sont également envoyées/commandées aux esclaves. Imaginez que vous ayez des esclaves dans différentes révisions et que vous deviez modifier une configuration PDO avec différentes séquences d'initialisation avec certains ensembles de règles ou attributs qui y sont attachés. Faire cela sur des coffres-forts de niveau supérieur à un niveau plus élevé, économise du temps et de l'argent. Pour initialiser l' EC-Master, les quatre fonctions en gras énumérées ci-dessous sont principalement nécessaires. L'extrait initialise un EC-Master multi-thread complet et le réseau attaché, y compris la gestion des erreurs, la journalisation et bien plus encore...
/* initialize EtherCAT master */
EC_T_INIT_MASTER_PARMS oInitParms;
OsMemset(&oInitParms, 0, sizeof(EC_T_INIT_MASTER_PARMS));
oInitParms.dwSignature = ATECAT_SIGNATURE;
oInitParms.dwSize = sizeof(EC_T_INIT_MASTER_PARMS);
oInitParms.pLinkParms = pAppParms->apLinkParms[0];
oInitParms.dwBusCycleTimeUsec = pAppParms->dwBusCycleTimeUsec;
oInitParms.dwMaxAcycFramesQueued = MASTER_CFG_MAX_ACYC_FRAMES_QUEUED;
OsMemcpy(&oInitParms.LogParms, &pAppContext->LogParms, sizeof(EC_T_LOG_PARMS));
oInitParms.LogParms.dwLogLevel = pAppParms->dwMasterLogLevel;
CHECK_MASTER_CALL( ecatInitMaster(&oInitParms), "Cannot initialize EC-Master: %s (0x%lx))\n" );
/* create cyclic task to trigger jobs */
CREATE_CYCLIC_TASK_TO_TRIGGER_JOBS
/* configure master */
CHECK_MASTER_CALL( ecatConfigureMaster(pAppParms->eCnfType,
"YaskawaSigmaDrive.xml",
(EC_T_DWORD)OsStrlen("YaskawaSigmaDrive.xml")),
"Cannot configure EC-Master: %s (0x%lx))\n" );
/* register client */
CHECK_MASTER_CALL( ecatRegisterClient(EcMasterNotifyCallback, pAppContext, &RegisterClientResults), "ERROR: Cannot register client: %s (0x%lx))\n" );
pAppContext->pNotificationHandler->SetClientID(RegisterClientResults.dwClntId);
/* state transition to OP */
CHECK_STATE_TRANSITION( ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_INIT), "INIT" );
CHECK_STATE_TRANSITION( ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_PREOP), "PREOP" );
CHECK_STATE_TRANSITION( ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_SAFEOP), "SAFEOP" );
CHECK_STATE_TRANSITION( ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_OP), "OP" );
EC_T_INIT_MASTER_PARMS oInitParms;
OsMemset(&oInitParms, 0, sizeof(EC_T_INIT_MASTER_PARMS));
oInitParms.dwSignature = ATECAT_SIGNATURE;
oInitParms.dwSize = sizeof(EC_T_INIT_MASTER_PARMS);
oInitParms.pLinkParms = pAppParms->apLinkParms[0];
oInitParms.dwBusCycleTimeUsec = pAppParms->dwBusCycleTimeUsec;
oInitParms.dwMaxAcycFramesQueued = MASTER_CFG_MAX_ACYC_FRAMES_QUEUED;
OsMemcpy(&oInitParms.LogParms, &pAppContext->LogParms, sizeof(EC_T_LOG_PARMS));
oInitParms.LogParms.dwLogLevel = pAppParms->dwMasterLogLevel;
CHECK_MASTER_CALL( ecatInitMaster(&oInitParms), "Cannot initialize EC-Master: %s (0x%lx))\n" );
/* create cyclic task to trigger jobs */
CREATE_CYCLIC_TASK_TO_TRIGGER_JOBS
/* configure master */
CHECK_MASTER_CALL( ecatConfigureMaster(pAppParms->eCnfType,
"YaskawaSigmaDrive.xml",
(EC_T_DWORD)OsStrlen("YaskawaSigmaDrive.xml")),
"Cannot configure EC-Master: %s (0x%lx))\n" );
/* register client */
CHECK_MASTER_CALL( ecatRegisterClient(EcMasterNotifyCallback, pAppContext, &RegisterClientResults), "ERROR: Cannot register client: %s (0x%lx))\n" );
pAppContext->pNotificationHandler->SetClientID(RegisterClientResults.dwClntId);
/* state transition to OP */
CHECK_STATE_TRANSITION( ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_INIT), "INIT" );
CHECK_STATE_TRANSITION( ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_PREOP), "PREOP" );
CHECK_STATE_TRANSITION( ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_SAFEOP), "SAFEOP" );
CHECK_STATE_TRANSITION( ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_OP), "OP" );