In compliance with high industry standards

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

How to connect an Arduino industrial PLC using Modbus TCP/IP

Master/Slave configuration with Modbus TCP/IP


Modbus is a very useful standard that allows us to communicate several devices from different manufacturers in the same network. Besides Modbus TCP/IP is transferred through Ethernet that is one of the most reliable protocols of the market.

In this case we will show how to configure two industrial Arduino based PLCs M-Duinos, one used as a Master and the other as a Slave.

Industrial control


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

Industrial PLC Arduino based controller Modbus TCP/IP Master/Slave examples:

Follow the previous post to see the Slave code that we have used in this example:

  • How to use Modbus TCP Slave library with a PLC controller Arduino      Read the post >>

Also take a look at the Master post to see how to use the Modbus Library, but for the Master we have changed the code a little in order to make it more interactive with the user:

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

M-Duino Master has an interactive serial menu that allow the user to control the application. The menu has 6 options. The first four options are to control two outputs of the slave, the fifth option is to get the Analog inputs or registers from the slave and the last option, sixth, is to get the digital inputs or discrete inputs from the slave.

We use writeSingleCoil(), readInputRegisters() and readDiscreteInputs() functions to communicate to the slave. Then just executing a short for loop depending on which message we have sent, we read the values using response.getRegister() or response.isDiscreteInputSet().

The rest of the code is just Ethernet configurations and Serial commands to debug and make the application more interactive

Modbus TCP IP


   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
   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 <>.
#include <ModbusTCPMaster.h>
#if defined(MDUINO_PLUS)
#include <Ethernet2.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() {
  // Begin Ethernet
  Ethernet.begin(mac, ip);
// 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()) {
    Serial.println("Slave not connected");
    slave.connect(slaveIp, slavePort);
    if (slave.connected()) {
  // Send a request every 1000ms if connected to slave
  if (slave.connected()) {
    //Serial.println("Slave connected");
  if (Serial.available()) {
      byte chosenOption=;
  bool value;
  byte address;
      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");
      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");
      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");
      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");
      case '5':
          if (!modbus.readInputRegisters(slave, 0, 0, 6)) {
            // Failure treatment
            Serial.println("Error requesting registers");
          }else{registerSet = true;}
      case '6':
          if (!modbus.readDiscreteInputs(slave, 0, 0, 7)) {
          // Failure treatment
          Serial.println("Error requesting discrete input");
          }else{discreteSet = true;} 
    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) {
          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) {
          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");


* IMPORTANT: when connecting the PLCs, a crossover Ethernet cable must be used

Arduino Modbus TCP

Looking for some examples of industrial automation?

Check our Case Studies about Arduino automation, control and monitoring.

Looking for your ideal PLC?

Take a look at this product comparison with other industrial controllers Arduino.

We are comparing inputs, outputs, communications and other features with the ones of the relevant brands.

Industrial PLC controller comparison >>

Do you want more information?

Just fill the form!

Tell me more!