Cómo conectar los PLCs basados en Arduino usando Modbus TCP/IP

Configuración Maestro/Esclavo con Modbus TCP/IP
18 de marzo de 2019 por
Cómo conectar los PLCs basados en Arduino usando Modbus TCP/IP
Bernat Garcia

Introduction

Modbus es un estándar muy útil que nos permite comunicar varios dispositivos de diferentes fabricantes en la misma red. Además Modbus TCP/IP se transfiere a través de Ethernet que es uno de los protocolos más fiables del mercado.

En este caso, mostraremos cómo configurar dos PLCs industriales basados en ArduinoM-Duino, uno utilizado como amo y el otro como esclavo. 

Control Industrial

Requirements for the connection between and Arduino industrial programmable logic controller with Modbus TCP/IP

Controlador industrial basado en Arduino Modbus TCPs TCP/IP Master/Slave ejemplos:

Sigue el post anterior para ver el código Slave que hemos utilizado en este ejemplo:

  • Cómo usar la biblioteca Modbus TCP Slave con un controlador PLC Arduino      Read the post >>>

También, echa un vistazo a la publicación del Maestro para ver cómo usar la Biblioteca Modbus, pero para el Maestro hemos cambiado un poco el código para hacerlo más interactivo con el usuario:

Application Architecture of the connection between an Arduino PLC and Modbus TCP/IP

M-Duino Master tiene un menú serie interactivo que permite al usuario controlar la aplicación. El menú tiene 6 opciones. Las primeras cuatro opciones son controlar dos salidas del Slave, la quinta opción es obtener las entradas Analógicas o registros del Slave y la última opción, es obtener las entradas Digitales o entradas discretas del Slave.

Usamos las funciones use writeSingleCoil(), readInputRegisters() y readDiscreteInputs() para comunicarnos con el Slave. A continuación, simplemente ejecutando un corto loop dependiendo del mensaje que hayamos enviado, leemos los valores usando response.getRegister() o response.isDiscreteInputSet().

El resto del código es solo configuraciones Ethernet y comandos Serial para depurar y hacer que la aplicación sea más interactiva.

Software

/*
   Copyright © 2018 Boot&Work Corp., S.L. All rights reserved
   This program is free software: you can redistribute it and/or modify
   it is under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.
   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <ModbusTCPMaster.h>
#include <Ethernet.h>
 
// Ethernet configuration values
uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(10, 10, 10, 3);
IPAddress slaveIp(10, 10, 10, 4);
uint16_t slavePort = 502;
// Define the ModbusTCPMaster object
ModbusTCPMaster modbus;
//
bool registerSet = 0;
bool discreteSet = 0;
// Ethernet client object used to connect to the slave
EthernetClient slave;
uint32_t lastSentTime = 0UL;
uint32_t lastSentTimeReadInputs = 0UL;
////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
  Serial.begin(9600UL);
  // Begin Ethernet
  Ethernet.begin(mac, ip);
  Serial.println(Ethernet.localIP());
  // NOTE: it is not necessary to start the modbus master object
  mainUI();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
  // Connect to slave if not connected
  // The ethernet connection is managed by the application, not by the library
  // In this case the connection is opened once
  if (!slave.connected()) {
    Serial.println("Slave not connected");
    slave.stop();
    slave.connect(slaveIp, slavePort);
    if (slave.connected()) {
      Serial.println("Reconnected");
    }
  }
  // Send a request every 1000ms if connected to slave
  if (slave.connected()) {
    //Serial.println("Slave connected");
  if (Serial.available()) {
      byte chosenOption= Serial.read();
  bool value;
  byte address;
  switch(chosenOption){
      case '1': //set Q0_0 to high
          value = 1;
          address = 0;
          if (!(modbus.writeSingleCoil(slave, 0, address, value))) {
            // Failure treatment
            Serial.println("Request fail");
          }
          Serial.println("Q0_0 set to HIGH");
          break; 
      case '2': //set Q0_0 to low
          value = 0;
          address = 0;
          if (!(modbus.writeSingleCoil(slave, 0, address, value))) {
            // Failure treatment
            Serial.println("Request fail");
          }
          Serial.println("Q0_0 set to LOW");
          break;
      case '3': //set Q0_1 to high
          value = 1;
          address = 1;
          if (!(modbus.writeSingleCoil(slave, 0, address, value))) {
            // Failure treatment
            Serial.println("Request fail");
          }
          Serial.println("Q0_1 set to HIGH");
          break;
      case '4':
          value = 0;
          address= 1;
          if (!(modbus.writeSingleCoil(slave, 0, address, value))) {
            // Failure treatment
            Serial.println("Request fail");
          }
          Serial.println("Q0_1 set to LOW");
          break;
      case '5':
          if (!modbus.readInputRegisters(slave, 0, 0, 6)) {
            // Failure treatment
            Serial.println("Error requesting registers");
          }else{registerSet = true;}
          break;
      case '6':
          if (!modbus.readDiscreteInputs(slave, 0, 0, 7)) {
          // Failure treatment
          Serial.println("Error requesting discrete input");
          }else{discreteSet = true;} 
          break;
  }
  mainUI();
    }
    if (modbus.isWaitingResponse()) {
      ModbusResponse response = modbus.available();
      if (response) {
        if (response.hasError()) {
          // Response failure treatment. You can use response.getErrorCode()
          // to get the error code.
        }else if (registerSet){
          // Get the input registers values from the response
          Serial.print("Input registers values: ");
          for (int i = 0; i < 6; ++i) {
            Serial.print(response.getRegister(i));
            Serial.print(',');
          }
          registerSet = false; 
        } else if(discreteSet) {
          // Get the input registers values from the response
          Serial.print("Input discrete values: [");
          for (int i = 0; i < 7; ++i) {
            Serial.print(response.isDiscreteInputSet(i));
            Serial.print(',');
          }
          Serial.println(']');
          discreteSet = false;
        }
      }
    }
  }
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void mainUI(){
    Serial.println("********************Modbus Test*********************");
    Serial.println("Chose an option:");
    Serial.println("1. Set Q0_0 to HIGH");
    Serial.println("2. Set Q0_0 to LOW");
    Serial.println("3. Set Q0_1 to HIGH");
    Serial.println("4. Set Q0_1 to LOW");
    Serial.println("5. Print slave input analog values");
    Serial.println("6. Print slave input digital values");
    Serial.println("****************************************************");

 
 
 
 


* IMPORTANTE: al conectar los PLC, se debe utilizar un cable Ethernet cruzado


¿Buscas algunos ejemplos de automatización industrial?

Consulta nuestros casos de estudio sobre la automatización, el control y la supervisión con Arduino. 


Buscar en nuestro blog

Cómo conectar los PLCs basados en Arduino usando Modbus TCP/IP
Bernat Garcia 18 de marzo de 2019
Compartir

¿Estás buscando tu Controlador Lógico Programable ideal?

Echa un vistazo a esta comparativa de producto de varios controladores industriales basados en Arduino.

Comparamos entradas, salidas, comunicaciones y otras especificaciones con las de los equipos de otras marcas destacadas.


Industrial PLC comparison >>>