A4A : Conteneur Docker

Bonjour,

Docker

J’indiquais dans l’article précédent que, sur les solutions netIOT Edge de Hilscher, Docker permet d’intégrer toutes sortes d’applications pour traiter les données acquises depuis le terrain ou le process avant de fournir celles-ci digérées aux applications hébergées dans le fameux nuage d’où doit pleuvoir la manne.

C’est aussi valable pour le netPI comme pour le Raspberry Pi sur lequel il est tout à fait possible d’installer Docker.

Il est bien sûr indispensable de se familiariser avec Docker puis de consulter la documentation pour comprendre les concepts.

Avec Docker, une application est empaquetée avec l’environnement nécessaire à son exécution dans une image que l’on va pouvoir instancier en conteneur(s) que Docker va exécuter.

On peut voir cela comme une approche composant où l’on isole chaque application et son environnement.

Pour le netPI, Hilscher offre nombre d’images prêtes à l’emploi sur le Hub communautaire où figurent également la plupart des projets  open source.

Ces images sont construites à partir de recettes, les docker files, et tous les fichiers pour les images fournies sont disponibles sur GitHub.

Dockerfile

Afin de me former sur ces technologies bien attirantes il m’est apparu que j’avais un projet candidat à la conteneurisation, Ada for Automation bien sûr !

J’ai donc installé Docker sur mon Raspberry Pi et, en m’inspirant des Dockerfiles de mes collègues, j’en ai écrit un basique que je vous présente ci-dessous.

#use latest armv7hf compatible raspbian OS version from group balena as base image
FROM balenalib/armv7hf-debian:stretch

#enable building ARM container on x86 machinery on the web (comment out next line if built on Raspberry)
#RUN [ "cross-build-start" ]

#labeling
LABEL maintainer="slos@hilscher.com" \
      version="V0.0.1" \
      description="Debian(stretch) / Ada for Automation Development"

#version
ENV ADA_FOR_AUTOMATION_BASIS_DEV_VERSION 0.0.1

#install ssh, gcc, create user "pi" and make him sudo
RUN apt-get update  \
    && apt-get install -y openssh-server build-essential \
    && mkdir /var/run/sshd \
    && useradd --create-home --shell /bin/bash pi \
    && echo 'pi:raspberry' | chpasswd \
    && adduser pi sudo
   
#install git, gnat and gprbuild
RUN apt-get update  \
    && apt-get install git gnat gprbuild

#install libmodbus
RUN apt-get update  \
    && apt-get install libmodbus5 libmodbus-dev

#install Ada for Automation and build some demo applications
RUN mkdir --parents /home/pi/Ada \
    && cd /home/pi/Ada \
    && git clone https://gitlab.com/ada-for-automation/ada-for-automation.git A4A \
    && cd "/home/pi/Ada/A4A/demo/000 a4a-k0-cli" && make

#SSH port
EXPOSE 22

#the entrypoint shall start ssh
ENTRYPOINT ["/usr/sbin/sshd", "-D"]

#set STOPSGINAL
STOPSIGNAL SIGTERM

#stop processing ARM emulation (comment out next line if built on Raspberry)
#RUN [ "cross-build-end" ]

Celui-ci, à partir d’une debian stretch, installe SSH, GCC, Git, les outils pour Ada GNAT, GPRBuild, et la librairie libmodbus.

Pour finir, il tire « Ada for Automation » depuis gitlab et compile la plus simple des applications qui implémente un serveur Modbus TCP et recopie quelques registres en entrée sur quelques registres en sortie.

Image

Construire l’image est trivial. Depuis le répertoire contenant le Dockerfile, il suffit de saisir la commande :

docker build --tag=rpi-a4a-basis-dev:latest .

Cette commande construit donc une image ayant pour nom « rpi-a4a-basis-dev » et taguée « latest » depuis le répertoire courant.

La commande suivante permet de lister les images produites :

docker image ls -a

Conteneur

On peut bien sûr créer aussitôt un conteneur à partir de cette image avec la commande suivante :

docker container create --publish 22:22 -p 1503:1503 --privileged rpi-a4a-basis-dev:latest

On publie le port 22 pour SSH et le port 1503 pour Modbus TCP Serveur et on octroie le privilège de pouvoir tourner avec une priorité temps réel si nécessaire.

Notre conteneur est créé comme nous pouvons le constater avec la commande qui nous donne le nom qui lui a été affecté automatiquement :

docker container ls -a

Et on peut s’en servir dès à présent :

docker container start <nom_du_conteneur>

Un ssh en local ou distant permet de se connecter à notre conteneur, de naviguer en ligne de commande dans l’arborescence et de démarrer l’application de démonstration.

Empiler

Notre conteneur basique permet de réaliser des applications avec une interface en ligne de commande, sans interface graphique basée sur GtkAda ou Gnoga.

Avec Docker, il est facile d’empiler une nouvelle couche pour étendre la fonctionnalité.

Ainsi, le dockerfile suivant ajoute à l’image de base Gnoga et ses dépendances, SimpleComponents et Zanyblue, et compile l’application A4A_Piano qui dispose d’une interface web.

#use latest Ada for Automation Basis Development as base image
FROM rpi-a4a-basis-dev:latest

#enable building ARM container on x86 machinery on the web (comment out next line if built on Raspberry)
#RUN [ "cross-build-start" ]

#labeling
LABEL maintainer="slos@hilscher.com" \
      version="V0.0.1" \
      description="Debian(stretch) / Ada for Automation Web Development"

#version
ENV ADA_FOR_AUTOMATION_WEB_DEV_VERSION 0.0.1

#install Gnoga and dependencies (Simple Components, ZanyBlue)
RUN mkdir --parents /home/pi/Ada/Gnoga \
    && cd /home/pi/Ada/Gnoga \
    && git clone https://git.code.sf.net/p/gnoga/code gnoga \
    && cd /home/pi/Ada/Gnoga/gnoga \
    && make release \
    && make install

#build some Ada for Automation Web demo applications
RUN cd "/home/pi/Ada/A4A/demo/010 a4a_piano" && make

#SSH port
EXPOSE 22

#the entrypoint shall start ssh
ENTRYPOINT ["/usr/sbin/sshd", "-D"]

#set STOPSGINAL
STOPSIGNAL SIGTERM

#stop processing ARM emulation (comment out next line if built on Raspberry)
#RUN [ "cross-build-end" ]

On construit l’image de la même façon que la précédente :

docker build --tag=rpi-a4a-web-dev:latest .

Puis on crée le conteneur avec un port supplémentaire pour le serveur web intégré :

docker container create --publish 22:22 -p 1504:1504 -p 8081:8081 --privileged rpi-a4a-web-dev:latest

On démarre le conteneur :

docker container start <nom_du_conteneur>

Un ssh en local ou distant permet de se connecter à notre conteneur, de naviguer en ligne de commande dans l’arborescence et de démarrer l’application de démonstration.

Et en pointant un navigateur sur l’adresse du site on trouve les pages attendues !

Tandis qu’on peut jouer avec :

Il ne me reste plus qu’à y envoyer dans mon espace du Hub Docker.

Taguons nos images :

docker tag rpi-a4a-basis-dev soloist/rpi-a4a-basis-dev:latest
docker tag rpi-a4a-web-dev soloist/rpi-a4a-web-dev:latest

Connectons nous :

docker login

Et poussons :

docker push soloist/rpi-a4a-basis-dev
docker push soloist/rpi-a4a-web-dev

C’est prêt pour une utilisation avec votre Raspberry Pi ou le netPI !

Cordialement,
Stéphane

Node-RED, InfluxDB, Grafana, Docker

Bonjour,

Nous avons pu voir dans les articles précédents quelques tableaux de bord réalisés avec des composants issus de la bibliothèque suivante :
https://github.com/node-red/node-red-dashboard

Ce n’est certes pas la seule solution et le couple InfluxDB / Grafana est souvent cité pour réaliser des projets IoT avec le Raspberry Pi.

InfluxDB permet de stocker des données horodatées dans une base de données que Grafana va interroger pour les afficher sous forme de diagrammes, de graphiques, ou sous forme tabulaire.

Ce sont des projets « open source » et il est possible de les installer sur toutes sortes de machines dont le Raspberry Pi.

Il se trouve qu’il y a un nœud Node-RED qui permet d’insérer depuis un flow des données dans une base InfluxDB, ce qui rend l’opération triviale :
https://flows.nodered.org/node/node-red-contrib-influxdb

Voilà, voilà…

Les données du « flow » présenté ici parviennent via le lien (link) au nœud qui les envoie à la base de données InfluxDB.

Et Grafana peut piocher dans les données pour les afficher comme vous le souhaitez :

En ce qui concerne la mise en œuvre d’une telle solution sur votre Raspberry Pi les articles et la documentation ne manquent pas.

Sur les solutions durcies netIOT Edge de Hilscher le système d’exploitation sécurisé ne permet pas d’installer quoi que ce soit non signé par Hilscher et il faut utiliser Docker via l’interface d’administration Portainer, ce qui est chose relativement aisée.

En fait, des conteneurs officiels sont disponibles sur le Hub Docker tant pour InfluxDB que pour Grafana.

Et Portainer permet de télécharger les images et de configurer les conteneurs correspondants.

Bien sûr, InfluxDB comme Grafana ont beaucoup plus à offrir, ce que je vous laisse le soin d’approfondir.

Comme l’interface applicative est basée sur le protocole HTTP, toutes sortes d’architectures sont envisageables.

Cordialement,
Stéphane

A4A : Pilotage d’un variateur en EtherCAT

Bonjour,

J’espérais à voix haute pouvoir réaliser des manipulations avec un variateur communiquant en CANopen ou EtherCAT et mon souhait a été exaucé par un ami travaillant chez INFRANOR à Lourdes qui a bien voulu mettre à ma disposition un banc de test composé d’un variateur et d’un ensemble moteur / codeur… Miracle !

Je l’en remercie très chaleureusement !

Le banc est équipé d’un variateur XtrapulsPac et l’on peut depuis le site télécharger bien sûr la documentation, le logiciel de configuration Gem Drive Studio, le fichier ESI EtherCAT, en bref tout le nécessaire pour la manipulation.

Je n’ai pas rencontré de problème particulier avec Gem Drive Studio et j’ai pu configurer, régler le variateur et me familiariser avec son fonctionnement via la liaison série.

Pour ma démonstration, le PC de test étant un peu ancien, j’ai utilisé une carte Hilscher cifX au format PCI.

On peut télécharger une archive du DVD contenant la documentation, les outils de configuration et les firmwares ici.

Cependant, je préfère me fournir dans la base de connaissance qui dispose des dernières versions…

Ainsi, il est possible de se procurer la dernière version de l’outil de configuration SYCON.net.

Il est aussi possible de récupérer le dernier firmware EtherCAT Master .

On a donc importé dans SYCON.net le fichier ESI du variateur, menu « Network > Import Device Descriptions… », ne pas oublier de sélectionner le type de fichier « EtherCAT DDF », inséré l’esclave EtherCAT sur le réseau de la cifX configurée en EtherCAT Maitre et sélectionné les PDO en entrée et sortie pour un fonctionnement en boucle de vitesse.

Côté EtherCAT Maitre, dans la mémoire process de la carte Hilscher cifX donc, on retrouve les données d’entrée et sortie correspondantes :

Gem Drive Studio comme SYCON.net fonctionnent sous Microsoft Windows(R).

Cependant notre application va s’exécuter sous Linux avec les modifications PREEMPT_RT permettant d’obtenir un comportement temps réel.
Nous récupérerons donc les fichiers de firmware et de configuration pour les disposer dans l’arborescence du pilote cifX pour Linux.

Je travaille principalement sur des systèmes Debian et sur cet OS il existe un noyau Linux déjà compilé avec les patches PREEMPT_RT qui n’est donc qu’à une portée de clics ou d’une ligne de commande.
Cherchez « linux-image-rt » dans votre outil habituel et tant que vous y êtes installez également les en-têtes correspondants qui seront nécessaires pour la compilation du pilote Hilscher cifX qui n’est fourni que sous forme de code source.

Une fois installé, il suffit de redémarrer la machine en sélectionnant ce noyau.

Compilez ensuite le pilote comme expliqué dans la documentation relative. Ce pilote est en deux parties, l’une en espace noyau, uio_netx, qu’il vous faudra recompiler à chaque mise à jour du noyau, l’autre en espace utilisateur, la libcifx, qui est l’API pour votre application.

Voyez également la documentation pour l’utilisation du module si vous voulez vous passer de l’incantation en « root » :

modprobe -v uio_netx

Si tout ce passe bien, l’incantation fournit un résultat tel que :

On a disposé firmware et configuration dans le dossier idoine, par exemple :

Vous avez bien sûr installé « Ada for Automation », les dépendances et les outils pour le développement et vous avez navigué vers le répertoire contenant la démonstration « 122 ap7-wui ».
Un simple « make » doit vous permettre de générer l’application dont il est question dans cet article.

Cette application nécessite des droits spécifiques pour tourner avec des priorités temps réel.
Aussi il faut faire partie du groupe dédié ou être « root » pour pouvoir l’exécuter.

Cela démarre sur les chapeaux de roues en laissant une trace de ce style dans la console :

root@hf-test-2:/home/slos/Ada/A4A/demo/122 app7-wui# ./bin/App7_WUI_cifX
error
Log_Level = LEVEL_ERROR
2018-12-17 14:43:29.94 => A4A.Kernel.Sig_Handler : Waiting Signal Interrupt... Use Ctrl+C to exit
2018-12-17 14:43:29.94 => A4A.Kernel.Main_Task : Main_Task's ID is the_main_task_00005579443C2E50
Started at 2018-12-17 14:43:29.94
2018-12-17 14:43:29.94 => A4A.Generic_Periodic_Task : started !
2018-12-17 14:43:29.94 => A4A.Kernel.Main_Task : Initialising cifX Driver...
2018-12-17 14:43:31.61 => A4A.Kernel.Main_Task : Opening cifX Driver...
2018-12-17 14:43:31.61 => A4A.Kernel.Main_Task : Starting cifX TCP Server...
2018-12-17 14:43:31.61 => A4A.Kernel.Main_Task :
***********************************************
          Driver Information
Version     : cifX Toolkit 1.2.0.0
Board Count :  1
***********************************************

2018-12-17 14:43:31.61 => A4A.Kernel.Main_Task : Waiting for the firmware to start...
2018-12-17 14:43:36.61 => A4A.Kernel.Main_Task : Opening cifX Channel...
2018-12-17 14:43:36.61 => A4A.Kernel.Main_Task :
***********************************************
          Channel Information
Board_Name    : cifX0
Board Alias   : ECM
Device Number :  1250100
Serial Number :  20952

Firmware : EtherCAT Master
Version  :  4. 4. 9(Build  0)
Date     :  2018- 10- 10
***********************************************

2018-12-17 14:43:36.61 => A4A.Kernel.Main_Task : Setting Flag Host Ready...
2018-12-17 14:43:36.61 => A4A.Kernel.Main_Task : Setting Flag Bus On...
2018-12-17 14:43:38.61 => A4A.Kernel.Main_Task : (16#800C0021#)COM-flag not set
2018-12-17 14:43:38.61 => A4A.Kernel.Main_Task : Initialising Channel Messaging...
2018-12-17 14:43:38.61 => A4A.Kernel.Main_Task : Getting DPM IO Info...
2018-12-17 14:43:39.11 => A4A.Kernel.Main_Task :
***********************************************
          DPM IO_Info

Number of IO Block Info    :  2

Input Area :
Type of sub block    :  2
Flags                :  17
Offset               :  0
Length               :  10

Output Area :
Type of sub block    :  2
Flags                :  18
Offset               :  0
Length               :  6
***********************************************

2018-12-17 14:43:39.11 => A4A.Kernel.Main_Task : Calling Cold_Start...
2018-12-17 14:43:39.11 => A4A.Kernel.Main_Task : (16#800C0021#)COM-flag not set
Gnoga            :1.2b
Application root :/home/slos/Ada/A4A/demo/122 app7-wui/
Executable at    :/home/slos/Ada/A4A/demo/122 app7-wui/bin/
HTML root        :/home/slos/Ada/A4A/demo/122 app7-wui/html/
Upload directory :/home/slos/Ada/A4A/demo/122 app7-wui/html/
Templates root   :/home/slos/Ada/A4A/demo/122 app7-wui/
/js  at          :/home/slos/Ada/A4A/demo/122 app7-wui/js/
/css at          :/home/slos/Ada/A4A/demo/122 app7-wui/css/
/img at          :/home/slos/Ada/A4A/demo/122 app7-wui/img/
Boot file        :000-boot.html
HTTP listen on   ::8091
Press Ctrl-C to close server.
2018-12-17 14:43:39.96 : HTTP Server Started

Si je pointe mon navigateur sur l’adresse locale et le port choisi (:8091 cf. la trace), je peux piloter le variateur depuis le mot de contrôle et observer un signal en dent de scie sur la consigne et la mesure…

… tandis que je mate une vidéo de lapin…

… ce qui charge ma vieille CPU comme une bête …

Dans cette vue de « htop » on voit bien les priorités des processes de l’application temps réel, notamment les deux avec la priorité -89 sont les tâches « main » et « periodic », une priorité normale en FIFO étant à -50, -89 est une priorité plutôt haute donc.

C’est ce qui permet à ces tâches de se comporter honnêtement :

Ainsi, la tâche « main », cadencée à 1 ms, subit une fois sur mille un dépassement de son heure d’activation.

La vue d’état de la cifX montre des informations classiques…


… que je peux vérifier également depuis SYCON.net sur un autre poste :

Car « Ada for Automation » implémente « netX Diagnostic and Remote Access » comme déjà évoqué.

J’espère bien trouver un peu de temps pour mener d’autres expérimentations comme implémenter quelques fonctions de Motion Control

Cordialement,
Stéphane

Raspberry Pi : Une passerelle Modbus – Communication S7

Bonjour,

Suivant le fil de nos expériences sur Raspberry Pi / Node-RED / netPi, netIOT… il est donc possible de communiquer en Modbus d’une part et en communication S7 sur Iso on TCP / RFC 1006 d’autre part.

Bien que cela ne soit pas une demande très fréquente il m’a été demandé quelques fois une passerelle permettant de connecter un automate communiquant selon le protocole Modbus, généralement il faut bien le dire un automate de la gamme SCHNEIDER ELECTRIC, avec un automate de la gamme SIEMENS S7.

S’il est possible bien sûr, et c’est souvent ainsi que la connexion est réalisée, d’utiliser une passerelle de la gamme Hilscher comme les netTAP 50 / 100 / 151 pour des conversions Modbus ou Ethernet/IP vers PROFIBUS ou PROFINET, il est nécessaire dans ce cas de modifier la configuration du réseau et de l’automate SIEMENS S7 pour y ajouter la passerelle en tant qu’esclave et programmer les échanges.

Cela demande de toute évidence de disposer des outils, des compétences, du programme et de l’autorisation de le modifier.

Dans certains cas, on souhaite seulement accéder aux données de l’automate qui sont déjà disponibles, par exemple dans un bloc de données mises à disposition pour un SCADA, et c’est ce que permet la communication S7.

Ainsi, le « flow » suivant réalise une communication entre un automate SCHNEIDER ELECTRIC M340, dans ce cas serveur Modbus TCP, et un automate SIEMENS S7-1500.

La passerelle équipée de Node-RED est dans ce cas le client Modbus TCP et lit et écrit les données dans le M340 d’une part.
D’autre part, elle lit et écrit les données dans le S7-1500.

Avec la version JSON pour l’import :
Node-RED-Modbus-S7-GW-00

On a donc un potentiomètre qui permet de régler le %MW10 en l’écrivant dans le S-1500 et une relecture de ce même mot.
Le résultat de la lecture est affiché d’une part dans une jauge et d’autre part écrit dans le %MW205 du M340.
Finalement, on lit ce %MW205 dans le M340 et on affiche sa valeur dans une jauge.

Un autre cas de figure est traité en partie basse du « flow », le cas où la passerelle est serveur Modbus TCP.

On a donc un nœud Modbus Serveur qui va être interrogé par un client Modbus TCP quelconque, en l’occurrence pour ma démonstration Modbus Poll.

Pour tester le nœud Modbus Serveur, un potentiomètre permet d’écrire une valeur dans le %MW0.
Le %MW10 remontant du S7-1500 est lui écrit en %MW1 (en même temps qu’il est écrit dans le M340).

On lit dans le nœud Modbus Serveur les données (et on y écrit) avec les mêmes nœuds que pour le M340 bien sûr sauf que cela se passe sur l’hôte local (localhost : 127.0.0.1).

On obtient le tableau de bord suivant :

Et Modbus Poll affiche bien les données attendues !

Cordialement,
Stéphane

Raspberry Pi : un tableau de bord pour votre automate Siemens S7

Bonjour,

Si votre installation comporte des automates Siemens S7, vous êtes bien en peine de discuter selon le protocole Modbus bien que cela soit possible. Et vous vous demandez comment réaliser vous aussi un superbe tableau de bord pour votre automate comme celui exposé ici.

C’est très possible et nous allons pouvoir avec Node-RED mettre en œuvre de nouveaux nœuds permettant la communication S7 via ISO on TCP / RFC 1006 :
https://flows.nodered.org/node/node-red-contrib-s7comm

Ces nœuds ont été développés par Hilscher :
https://github.com/Hilscher/node-red-contrib-s7comm

sur la base de l’excellent travail de ce projet :
https://github.com/plcpeople/nodeS7

Vous voudrez bien consulter la littérature fournie par ces projets pour plus d’information.

Disposant d’une CPU Siemens S7-1500 PN j’ai donc pu tester ces blocs et j’ai créé ce « flow » que je partage :

Le « flow » exporté est ici :
Node-RED-S7-1500-RFC1006-0

Il réalise la lecture du %MW0, sa mise en forme et l’affichage dans une jauge.
L’état de la communication est également affiché.
Un potentiomètre permet de régler une valeur écrite dans ce même %MW0, ce qui suffit à ma démonstration.

Le code de la fonction est très simple. On récupère sur une sortie la valeur qui nous intéresse et l’on teste l’état de la communication que l’on retourne sur la seconde sortie.

var msg_out = {payload:msg.payload.value[0]};
var msg_com = {payload:(msg.payload.error === 0)};
return [msg_out, msg_com];

Les nœuds peuvent accéder en lecture et écriture aux différentes zones mémoire de l’automate (entrée, sortie, mémento, blocs de données, tempo et compteurs) et tous les types de données élémentaires, aussi les chaines de caractères S7, sont supportés.

Ainsi le « flow » montre l’exemple du réel %MD2. La valeur est aussi envoyée vers un autre « flow » connecté à une base de données « InfluxDB » mais c’est une autre histoire que je vous raconterai ce tantôt.

Et voici un beau tableau de bord pour votre S7-1500 :

Si votre CPU ne possède pas de connexion TCP/IP, rien n’est perdu !

En effet, vous pouvez lui adjoindre un NL 50-MPI (ou un NT 50-MPI) connecté sur le port MPI ou PROFIBUS.

Ces passerelles ont déjà fait l’objet de plusieurs articles.

Ainsi je peux faire la même chose avec ma CPU Siemens S7 315-2DP :

Les nœuds Node-RED S7-Comm sont installés par défaut dans toutes les passerelles de la gamme netIOT Edge.

Ces équipements industriels iront très bien à côté de votre CPU Siemens ! 😉

Cordialement,
Stéphane