Browse our Blog. You will find multiple applications, solutions, code examples. Navigate using the tag cloud or search using specific criteris

Modbus TCP Master with Industrial Arduino based PLCs

Introduction

The Modbus protocol was developed in 1979 by Modicon for industrial automation systems and programmable logic controllers with an Ethernet connection. It is used to transfer discrete/analog I/O informations and register data between industrial control and monitoring devices.



Modbus devices communicate using a master-slave (client-server) technique in which only one device (the master/client) can initiate transactions (called queries). The other devices (slaves/servers) respond by supplying the requested data to the master, or by taking the action requested in the query. A slave is any peripheral device (I/O transducer valve, network drive, or other measuring devices) that processes information and sends its output to the master using Modbus. The Acromag I/O Modules form slave/server devices, while a typical master device is a host computer running appropriate application software. Other devices may function as both clients (masters) and servers (slaves). 

Requeriments

In order to work with the Modbus TCP, you will need any of our PLC controllers for industrial automation:

Modbus TCP/IP protocol

Modbus TCP/IP uses TCP/IP and Ethernet to carry the data of the Modbus message structure between compatible devices. That is, Modbus TCP/IP combines a physical network (Ethernet), with a networking standard (TCP/IP), and a standard method of representing data (Modbus as the application protocol). Essentially, the Modbus TCP/IP message is simply a Modbus communication encapsulated in an Ethernet TCP/IP wrapper.

Hardware

  • Configuration of the switches: 

Most of the inputs and the outputs are connected to the internal PLC Arduino, but in few cases, the user can choose between a special peripheral configuration or a GPIO by changing the position of the Dip Switches.

Each switch can select only one of the two possible configurations at the same time, the right position (ON) or the left one (OFF). 

In this case, the position of the switches are not important, because the communication is always available.


Software

  • Modbus TCP Master Library:

This library is only available for Industrial Shields' industrial PLC, but they can be modified by any user, so they can be used in other Arduino devices.

The funcions to read and write slave values are:

readCoils(client, slave_address, address, quantity);
readDiscreteInputs(client, slave_address, address, quantity);
readHoldingRegisters(client, slave_address, address, quantity);
readInputRegisters(client, slave_address, address, quantity);
writeSingleCoil(client, slave_address, address, value);
writeSingleRegister(client, slave_address, address, value);
writeMultipleCoils(client, slave_address, address, values, quantity);
writeMultipleRegisters(client, slave_address, address, values, quantity);

Where

  • client is the EthernetClient connected to the slave.
  • slave_address is the Modbus RTU slave address.
  • address is the coil, digital input, holding register or input register address. Usually this address is the coil, digital input, holding register or input register number minus 1: the holding register number 40009 has the address 8.
  • quantity is the number of coils, digital inputs, holding registers or input registers to read/write.
  • value is the given value of the coil or holding registers on a write operation. Depending on the function the data type changes. A coil is represented by a bool value and a holding register is represented by a uint16_t value.

On a multiple read/write function the address argument is the first element address. On a multiple write function the values argument is an array of values to write.

It is important to notice that these functions are non-blocking, so they do not return the read value. They return true or false depending on the current module state. If there is a pending Modbus request or the client is not connected, they return false.

  • There is the available() function to check for responses from the slave.

  • The ModbusResponse implements some functions to get the response information:

hasError();
getErrorCode();
getSlave();
getFC();
isCoilSet(offset);
isDiscreteInputSet(offset);
isDiscreteSet(offset);
getRegister(offset);


  • Modbus TCP Master Input registers reader code:

/* 
   Copyright (c) 2018 Boot&Work Corp., S.L. All rights reserved

   This program is free software: you can redistribute it and/or modify
   it 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 <Ethernet.h>            // This is the client;
#include <ModbusTCPMaster.h>     // This is the master;

// Ethernet configuration values
uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
uint8_t ip[] = { 10, 10, 10, 3 };
uint8_t slaveIp[] = { 10, 10, 10, 4 };
uint16_t slavePort = 502;

// Define the ModbusTCPMaster object
ModbusTCPMaster master;

// Ethernet client object used to connect to the slave
EthernetClient slave;

uint32_t lastSentTime = 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
}

////////////////////////////////////////////////////////////////////////////////////////////////////
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()) {
    slave.stop();

    slave.connect(slaveIp, slavePort);
  }

  // Send a request every 1000ms if connected to slave
  if (slave.connected()) {
    if (millis() - lastSentTime > 1000) {
      // Send a Read Input Registers request to the slave with address 31
      // It requests for 6 registers starting at address 0
      // IMPORTANT: all read and write functions start a Modbus transmission, but they are not
      // blocking, so you can continue the program while the Modbus functions work. To check for
      // available responses, call master.available() function often.
      if (!master.readInputRegisters(slave, 31, 0, 6)) {
        // Failure treatment
      }

      lastSentTime = millis();
    }

    // Check available responses often
    if (master.isWaitingResponse()) {
      ModbusResponse response = master.available();
      if (response) {
        if (response.hasError()) {
          // Response failure treatment. You can use response.getErrorCode()
          // to get the error code.
        } else {
          // 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(',');
          }
          Serial.println();
        }
      }
    }
  }
}

Other ARDUINO MODBUS

Arduino RS485 working as a Modbus RTU

Modbus is a standard way to connect different devices for Industrial uses. As shown in this post you can connect through Modbus TCP protocol using Arduino Ethernet shields or working with Arduino as a PLC but there are other ways to use the Modbus protocol. You can also use Modbus RTU using the RS485 shield for Arduino. Take into consideration if you need to work using Arduino for Industrial automation or industrial use you can also use the same code used on an Arduino Uno board connected to any MAX485 Arduino shield using an Arduino industrial grade controller made from Industrial Shields. 

Do you want more information?

Open Source technology allows you to develop your installations.

Just fill the form and we will contact you as soon as we can.

Send