samedi, décembre 21, 2024
Banner Top

Mise en place d’une communication MODBUS RTU entre un automate Arduino et un IHM Iview

Prérequis

Lien des produits

Logiciels :

Installation physique

Les produits utilisés pour cet articles sont les suivants :

  • Automate ARD_10I08R
  • IHM IV207M-SEAP

Sur certains produits des mêmes gammes, la programmation et le fonctionnement pourront potentiellement être différents.

Configuration des switches

La première chose à faire est de définir les positions dans lesquelles placer les switches rouges présents sur l’automate.

Dans notre cas, la communication que nous allons mettre en place utilise un protocole RS485 en Halfduplex.

Pour cela, il faut configurer les switches comme suit :

Câblage

En Halfduplex, les informations transitent par un couple de fils. Chaque appareil prend tour à tour la fonction d’émetteur puis de transmetteur. Pour limiter les pertes, il vaut mieux utiliser une paire torsadée dans une gaine isolée (comme dans un câble Ethernet classique).

Configuration logicielle

Ouverture de la communication côté IHM

Sur le logiciel de programmation Iview,  la communication doit être configurée comme suit :

Les valeurs « Baudrate », « Data Bits », « Parity » et « Stop Bits » peuvent être configurées différemment que ci-dessus. Il est cependant nécessaire qu’elles soient identiques à celles configurées dans l’automate.

Ouverture de la configuration côté automate

La première chose à faire et d’appeler dans le programme les différentes bibliothèques dont nous auront besoin.

#include <ModbusRTUMaster.h>

#include <RS485.h>

MODBUS RTU étant un protocole de communication logiciel, il faut ensuite déclarer le support physique sur lequel transiterons les données, RS485 dans notre cas.

//Définition de l’objet ModbusRTUMaster

ModbusRTUMaster master(RS485);

Cette ligne déclare un objet ModbusRTUMaster sur support physique RS485 que l’on nomme « master »

 

Enfin, pour finaliser l’ouverture de la connexion côté automate, il faut la lancer dans la fonction « setup » du programme.

void setup() { 

                 // Lancement de la connexion RS485

                 RS485.begin(38400, HALFDUPLEX, SERIAL_8N1);//(8N1 = 8bits, parity = None, bits de stop = 1)

               // Lancement de l’objet ModbusRTUMaster

               master.begin(38400);

}

Une fois toutes ces étapes effectuées, la communication est lancée.

Lecture et écriture des données

MODBUS fonctionne avec des fonctions qui permettent de définir l’action à réaliser, que ce soit de la lecture ou de l’écriture et que la cible soit des bits ou des registres.

Traditionnellement, on retrouve 8 fonctions principales :

  • Read Coils
  • Read Discrete Inputs
  • Read Holding Registers
  • Read Input Registers
  • Write Single Coil
  • Write Single Register
  • Write Multiple Coils
  • Write Multiple Registers

Dans notre cas, la surcouche logicielle industrialShiel qui permet l’utilisation des automates ARDBOX nous limite à l’utilisation de deux codes fonctions :

  • Read Coils
  • Write Multiple Registers

 

Lors de l’appel de ces fonction, nous devons définir des paramètres :

ReadCoils() :

//Cette fonction va lire les 3 bits suivants le bit d’adresse 1 de l’esclave n°1

//(numéro d’esclave, adresse, quantité) ;

master.readCoils(1, 1, 3); //(Numéro d’esclave, adresse, quantité)

Une fois cette fonction lancée, il est possible d’enregistrer les bits lus dans un tableau pour les traiter, par exemple :

//définition de la réponse modbus qui suit la requête ReadCoils()

ModbusResponse response = master.available();

//lecture des bits de la réponse (ici le premier bit lu est celui qui possède l’adresse 3 dans  //l’esclave. Il sera enregistré dans Coils[0])

for (int i = 0 ; i < 3 ; i++) {

                               bool coil = response.isCoilSet(i);

                               Coils[i] = coil;

                }

//Activation des sorties relais R4 et R6 en fonction des bits d’adresse 3 et 4 sur l’esclave

               digitalWrite(R4, Coils[0]);

               digitalWrite(R6, Coils[1]);

 

Au niveau de la programmation de l’IHM, il faudra alors faire correspondre le bit activé par un bouton avec celui défini dans la fonction readCoils()

WriteMultipleRegisters() :

//Lecture des entrées digitales de l’automate et enregistrement dans un tableau

               DigitalIn[0] = digitalRead(I0_1);

               DigitalIn[1] = digitalRead(I0_2);

               DigitalIn[2] = digitalRead(I0_3);

 

   

               //Définition d’un registre résumant les entrées digitales

                int Reg_DigitalIn = 0;

               for (int i = 0; i < 3; i++) {

               Reg_DigitalIn = (Reg_DigitalIn + (DigitalIn[i] * (pow(2, i))));

                }

 

                //remplissage du tableau contenant les registres à écrire

               Reg[0] = Reg_DigitalIn;

               Reg[1] = analogRead(I0_6);

 

   //Envoi du tableau

//(Adresse de l’esclave,adresse d’écriture, Valeurs, Nombre de registres)

master.writeMultipleRegisters(1, 1, Reg, 2);

 

Pour afficher les états des entrées digitales sur l’IHM, il faut créer des voyants et les programmer comme suit :

Pour visualiser l’état d’une entrée analogique, on peut créer par exemple un « Bargraph » et le programmer comme suit :

Exemple :

#include <ModbusRTUMaster.h>

#include <RS485.h>

/* PAramétrage Iview207M :

    Modicon 984 Master(RTU) sublink

    38400, 8N1, Panel Address : 1; PLC adress : 1; autre : 0

*/

 

// Define the ModbusRTUMaster object, using the RS-485

ModbusRTUMaster master(RS485);

const uint32_t baudrate = 38400UL;

bool DigitalIn[3];

int Reg[3];

int graph = 0;

bool Coils[5];

 

 

 

////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {

  Serial.begin(9600UL);

  // définition de la connexion MODBUS

    RS485.begin(baudrate, HALFDUPLEX, SERIAL_8N1);//(8E1 = 8bits, parity = Even, bits de stop = 1)

  // Start the modbus master object.

  // It is possible to define the port rate (default: 19200)

  master.begin(baudrate);

}

 

 

////////////////////////////////////////////////////////////////////////////////////////////////////

 

void loop() {

  switch (graph) {

   

    case 0 :

      //Lecture des entrées digitales en enregistrement dans un tableau

      DigitalIn[0] = digitalRead(I0_1);

      DigitalIn[1] = digitalRead(I0_2);

      DigitalIn[2] = digitalRead(I0_3);

      graph = 1;

 

    case 1 :

      //Définition d’un registre contenant les valeurs des entrées analogiques

      int Reg_DigitalIn = 0;

      for (int i = 0; i < 3; i++) {

        Reg_DigitalIn = (Reg_DigitalIn + (DigitalIn[i] * (pow(2, i))));

      }

      //remplissage du tableau contenant les registres à écrire

      Reg[0] = Reg_DigitalIn;

      Reg[1] = analogRead(I0_6);

      graph = 2;

 

 

    case 2 :

      delay(5);

      master.readCoils(1, 1, 100);

      ModbusResponse response = master.available();

      if (response.getFC() != 0) {

        graph = 3;

      }

 

    case 3 :

      if (response) {

        if (response.hasError()) {

          Serial.println(“error”);

          // Response failure treatment. You can use response.getErrorCode()

          // to get the error code.

        } else {

          // Get the coil value from the response

          for (int i = 0 ; i < 5 ; i++) {

            bool coil = response.isCoilSet(i);

            Coils[i] = coil;

          }

          digitalWrite(R4, Coils[0]);

          digitalWrite(R6, Coils[1]);

        }

        graph = 4;

      }

     

    case 4 :

      delay(5);

      master.writeMultipleRegisters(1, 1, Reg, 5); //(Adresse de l’esclave,adresse d’écriture, Valeurs, Nombre de registres)

      ModbusResponse response1 = master.available();

      if (response1.getFC() != 0) {

        graph = 0;

      }    

  }  //fin switch

//fin loop

Visuel automatisation technic-achat
0 Commentaires

Laisser un commentaire