Archives par mot-clé : Node-RED

Raspberry pi : CODESYS & Al.

Bonjour,

Introduction

J’ai préparé une super démo que je devais présenter à des collègues et partenaires mais nous voici confinés et mes présentations devront attendre… Quoique… Quid d’un article ?

Les derniers articles traitaient de Raspberry Pi, de netPI Core / RTE et netIOT Edge « Connect », plateformes matérielles pour le marché industriel développées par Hilscher et basées sur le Raspberry Pi, de Docker, Node-RED, InfluxDB, Grafana et j’avais donc prévu de tester les SoftPLC (automates logiciels) CODESYS ou STRATON.

J’ai ainsi concocté une mixture de tout ceci, avec CODESYS cette fois car ma manipulation inclut le variateur INFRANOR qui se pilote via EtherCAT et que j’ai déjà évoqué ici.

Il se trouve que l’application de contrôle pour le Raspberry Pi dispose de EtherCAT Maitre, entre autres.

On montrera donc :

  • un automate CODESYS pilotant via EtherCAT un variateur INFRANOR,
  • un flow Node-RED avec un tableau de bord qui permet d’interagir avec le variateur via le serveur OPC de CODESYS,
  • ce flow renseigne également une base de données temporelles InfluxDB,
  • et une instance Grafana vient lire les données et les affiche.

Il est tout à fait possible de faire la même chose avec un Rasberry Pi mais par convenance je ferai ma démonstration avec un netPI RTE puisque c’est celui que j’ai sous la main.
Une version netPI Core suffit amplement à ma démo mais bien sûr j’aurais pu utiliser une version netPI Core / RTE ou netIOT Edge « Connect », cette dernière proposant une intégration native de Node-RED avec utilisation du protocole sécurisé HTTPS.

Le plan

Voici donc le plan d’ensemble, the big picture, de la solution envisagée :

CODESYS

J’ai donc suivi pas à pas les instructions pour la création du conteneur CODESYS et installé l’environnement de développement sur mon poste et les paquets runtime et gateway comme demandé.

J’utilise pour ma part l’interface WIFI (wlan0) pour accéder depuis mon PC de développement à la cible CODESYS.

Il est nécessaire d’importer le fichier ESI du variateur dans l’IDE CODESYS et l’on peut alors créer une configuration avec l’EtherCAT Master sur le port LAN (eth0).

On peut configurer les données échangées cycliquement entre l’automate et le variateur :

Mon programme en Structured Text ressemble à de l’Ada, c’est normal. 😉

J’ai défini quelques variables mappées côté EtherCAT :

Et d’autres remontant à l’IHM via le serveur OPC :

Jusque là, ça va :

Docker

Comme je veux que mon conteneur InfluxDB reste isolé du monde extérieur, je crée un réseau « myNet1 » auquel je vais connecter les conteneurs InfluxDB donc, le conteneur Node-RED qui va alimenter la base et le conteneur Grafana qui va y piocher :

J’ai donc créé mes conteneurs en suivant les instructions pour Node-RED, InfluxDB et Grafana en connectant les conteneurs sur mon réseau privé « myNet1 » :

Node-RED

Dans Node-RED, auquel on accède via le port 1880, j’ai ajouté quelques nœuds à ma palette comme node-red-dashboard, node-red-contrib-opcua, node-red-contrib-influxdb :

Puis j’ai développé ce flow qui d’une part communique avec CODESYS en OPC UA et d’autre part avec les composants du tableau de bord.
Il injecte également dans la base InfluxDB les échantillons de la vitesse.

On obtient un magnifique tableau de bord pour piloter le variateur INFRANOR :

On y voit le mode d’opération (3 : boucle de vitesse), la vitesse actuelle sous forme de jauge ou de diagramme, un curseur permettant de modifier la consigne, le mot d’état et pour finir le mot de contrôle.

0, 6, 7, 15… ça tourne ! 128 pour acquitter les défauts.

Et le menu hamburger permet d’accéder directement à la visualisation Grafana qui nous attend sur le port 3000 :

Le flow est disponible ici.

Puisque nous voilà confinés pour un moment, n’est-ce pas l’occasion rêvée de se mettre à l’autoformation ? 😉

Bien sûr, si vous ne disposez pas d’un variateur, tout autre esclave fera l’affaire étant donné que CODESYS supporte plusieurs technologies de bus de terrain sur Ethernet, CAN et liaison série.

Vous pourriez utiliser aussi le netHAT sur le Raspberry Pi, ou le netPI RTE / netIOT Edge « Connect », qui embarque un netX 51 permettant de gérer tous les protocoles sur Ethernet Temps Réel, ce qui autorise plein d’expériences amusantes.

Have fun comme disent nos collègues anglophones.

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

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

Raspberry Pi : un tableau de bord pour votre automate Modbus

Bonjour,

L’article précédent montrait la réalisation d’un tableau de bord pour un serveur Modbus TCP un peu particulier avec Node-RED.

Il est bien sûr possible d’appliquer ces mêmes technologies pour créer un tableau de bord quel que soit le serveur Modbus TCP ou l’esclave Modbus RTU.

En l’occurrence, j’ai à ma disposition un automate M340 de SCHNEIDER ELECTRIC, muni d’un coupleur NOC04101, et qui possède, entre autres, la fonctionnalité serveur Modbus TCP et le « flow » ci-après réalise les opérations suivantes :

D’une part, on lit et on affiche dans une jauge la valeur du %MW200.
On trouve donc les nœuds suivants :

  • un nœud qui effectue la lecture du %MW200, fonction FC3, lecture de registres internes,
  • un autre, l’extraction et la mise en forme de la donnée pour la jauge,
  • et la jauge elle-même.

D’autre part, un potentiomètre permet de régler la valeur du %MW210.
Il y a ainsi :

  • le nœud du potentiomètre,
  • et celui réalise l’écriture du %MW210, FC6, écriture d’un registre interne.

Le code de la fonction d’extraction est très simple, la requête FC3 remonte un tableau de données et l’on ne s’intéresse qu’à la première :

var msg_out = {payload:msg.payload[0]};
return msg_out;

Le programme automate se contente de recopier la valeur du %MW210 dans le %MW200 pour les besoins de ma démonstration.

[
    {
        "id": "43e491b2.0b35a8",
        "type": "tab",
        "label": "Modbus",
        "disabled": false,
        "info": ""
    },
    {
        "id": "6ca8bbe5.c10cfc",
        "type": "modbus-read",
        "z": "43e491b2.0b35a8",
        "name": "",
        "topic": "",
        "showStatusActivities": false,
        "showErrors": false,
        "unitid": "",
        "dataType": "HoldingRegister",
        "adr": "200",
        "quantity": "1",
        "rate": "1",
        "rateUnit": "s",
        "delayOnStart": false,
        "startDelayTime": "",
        "server": "43c0221.3e519dc",
        "x": 150,
        "y": 100,
        "wires": [
            [
                "d1453b66.31e57",
                "74b2d916.437c08"
            ],
            []
        ]
    },
    {
        "id": "d1453b66.31e57",
        "type": "debug",
        "z": "43e491b2.0b35a8",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 350,
        "y": 100,
        "wires": []
    },
    {
        "id": "35d64d2a.3a0dfa",
        "type": "ui_gauge",
        "z": "43e491b2.0b35a8",
        "name": "Modbus Gauge",
        "group": "338d75bf.8d7ca2",
        "order": 1,
        "width": 0,
        "height": 0,
        "gtype": "gage",
        "title": "MW200 Gauge",
        "label": "units",
        "format": "{{value}}",
        "min": 0,
        "max": "65535",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "x": 500,
        "y": 180,
        "wires": []
    },
    {
        "id": "74b2d916.437c08",
        "type": "function",
        "z": "43e491b2.0b35a8",
        "name": "",
        "func": "var msg_out = {payload:msg.payload[0]};\nreturn msg_out;",
        "outputs": 1,
        "noerr": 0,
        "x": 330,
        "y": 140,
        "wires": [
            [
                "35d64d2a.3a0dfa",
                "de0996f0.d1aef"
            ]
        ]
    },
    {
        "id": "de0996f0.d1aef",
        "type": "debug",
        "z": "43e491b2.0b35a8",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 490,
        "y": 140,
        "wires": []
    },
    {
        "id": "82cf117c.244d88",
        "type": "modbus-write",
        "z": "43e491b2.0b35a8",
        "name": "",
        "showStatusActivities": false,
        "showErrors": false,
        "unitid": "",
        "dataType": "HoldingRegister",
        "adr": "210",
        "quantity": "1",
        "server": "43c0221.3e519dc",
        "x": 500,
        "y": 320,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "7fad2d38.5ba184",
        "type": "ui_slider",
        "z": "43e491b2.0b35a8",
        "name": "Modbus MW210 Slider",
        "label": "MW210 Slider",
        "group": "338d75bf.8d7ca2",
        "order": 0,
        "width": 0,
        "height": 0,
        "passthru": true,
        "topic": "",
        "min": 0,
        "max": "65535",
        "step": 1,
        "x": 160,
        "y": 320,
        "wires": [
            [
                "82cf117c.244d88"
            ]
        ]
    },
    {
        "id": "43c0221.3e519dc",
        "type": "modbus-client",
        "z": "43e491b2.0b35a8",
        "name": "M340",
        "clienttype": "tcp",
        "bufferCommands": true,
        "stateLogEnabled": false,
        "tcpHost": "192.168.1.100",
        "tcpPort": "502",
        "tcpType": "DEFAULT",
        "serialPort": "/dev/ttyUSB",
        "serialType": "RTU-BUFFERD",
        "serialBaudrate": "9600",
        "serialDatabits": "8",
        "serialStopbits": "1",
        "serialParity": "none",
        "serialConnectionDelay": "100",
        "unit_id": 1,
        "commandDelay": 1,
        "clientTimeout": 1000,
        "reconnectTimeout": 2000
    },
    {
        "id": "338d75bf.8d7ca2",
        "type": "ui_group",
        "z": "43e491b2.0b35a8",
        "name": "Modbus",
        "tab": "52e4f040.d2daf",
        "order": 1,
        "disp": true,
        "width": "6"
    },
    {
        "id": "52e4f040.d2daf",
        "type": "ui_tab",
        "z": "43e491b2.0b35a8",
        "name": "Modbus",
        "icon": "dashboard",
        "order": 3
    }
]

Le code du flow est disponible ici :
Node-RED-M340-OMB0

Et le tableau de bord résultant ressemble à ceci :

Je suis certain que vous voyez déjà toutes les opportunités qui s’offrent à vous pour un investissement somme toute modique.

Avec un œil sur votre automate depuis n’importe quel navigateur, de votre bureau ou sur votre mobile, vous pourrez vous consacrer à d’autres tâches comme apprendre Ada 😉 :
https://learn.adacore.com/index.html#

Bien sûr, lorsque vous vous serez fait la main sur votre Raspberry Pi, vous pourrez compter sur une version industrialisée de celui ci comme le netPI CORE 3 :
https://www.hilscher.com/products/product-groups/industrial-internet-industry-40/netiot-edge/niot-e-npi3-en/

Cordialement,
Stéphane