ESP32 Modbus TCP/IP protocol over ethernet

Hi everyone, for my end of degree project i have to use my ESP32 WeMos Board with Modbus over ethernet. I know that ESP32 is usually used with wifi but i made the suitable modifications to adapt ethernet library for ESP32, therefore, currently, it works for sending data through ethernet. Now i want to use ethernet to develop MODBUS TCP over it. I saw that last year our mate WVESP32 made more or less the same but due to that conversation is old i’m going to post this for everybody as well.
What modifications do i have to do to implement that? I append my declaration code and also setup code.
I also add the warnings that i get.
I hope you can help me. Thank you!
Code:

#include <Ethernet.h>
#include <ArduinoModbus.h>
//#include "local_config.h"
#include <ModbusTCPServer.h>


bool _1s;
unsigned long TimeAct, TimePrev, HodingResult, InputResult, HeartBeat, i, StartingAddr;
long Cmd;

EthernetServer EthServer(502);
ModbusTCPServer modbusTCPServer;

void setup() {
  // Ethernet Settings
  /*
  byte mac[] = { 0x4E, 0xA0, 0xBE, 0x3F, 0xFE, 0x0F };  // Define MAc address
  byte ip[] = { 192, 168, 1, 23 };                      // Define IP address
  byte subnet[] = { 255, 255, 255, 0 };                 // Define SubNEt mask
*/
uint8_t eth_MAC[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };


/*
 * Define the static network settings for this gateway's ETHERNET connection
 * on your LAN.  These values must match YOUR SPECIFIC LAN.  The "eth_IP"
 * is the IP address for this gateway's ETHERNET port.
 */
 
IPAddress eth_IP(192, 168, 1, 120);    // *** CHANGE THIS to something relevant for YOUR LAN. ***
IPAddress eth_MASK(255, 255, 255, 0);   // Subnet mask.
IPAddress eth_DNS(192, 168, 1, 2);    // *** CHANGE THIS to match YOUR DNS server.           ***
IPAddress eth_GW(192, 168, 1, 0);   // *** CHANGE THIS to match YOUR Gateway (router).     ***


  // initialize the ethernet device
  Ethernet.begin(eth_MAC, eth_IP, eth_MASK);                      // Assign MAC, IP, and subnet mask
  Serial.begin(9600);
  EthServer.begin();          // start listening for clients
  modbusTCPServer.begin();    // start listening for clients

  // Define Holding register:
  HodingResult = modbusTCPServer.configureHoldingRegisters(0, 100);
  InputResult = modbusTCPServer.configureInputRegisters(0, 100);

  Serial.print("Holding Reg init result =");
  Serial.print(HodingResult);
  Serial.print("\n");

  Serial.print("Input Reg init result =");
  Serial.print(InputResult);
  Serial.print("\n");

  Serial.print("Modbus server address=");
  Serial.println(Ethernet.localIP());
  Serial.print("\n");
}

Warnings:

1 Like

Hi Mr. Berguinsson,

this is my ModBusInit-Code-Snip. Hope it helps.

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Include-Files vom Compiler
#include <Arduino.h>
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "driver/pcnt.h"
#include <ETH.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// eigene Include-Files
#include "main.h"							// => top of !
#include "modbus_ke.h"
#include "mqtt_ke.h"
#include "ModbusTCPServer.h"        // autom: #include "ModbusServer.h"
#include "wifi_ke.h"
....

void Modbus_Initialisierung ()
{
	int iStatusModbusTCPServer = 0;
	int iStatusRegisterInit = FALSE;

	Serial.println ("Modbus.Init");

	...
	// 2. Modbus starten
	iStatusModbusTCPServer = modbusTCPServer.begin();
	Serial.print (" -> ModbusTcpServer.begin=");
	Serial.println (iStatusModbusTCPServer);

	// OK? 
	// => wir konfigurieren ein paar Register
	if ( iStatusModbusTCPServer == TRUE )
	{
	// HINWEIS: wir reservieren uns mal 65 RegisterSpeicher.
	iStatusRegisterInit =
	  modbusTCPServer.configureInputRegisters ( 30001, 65);
	Serial.print (" -> ModbusTcpServer.configInput.65  S=");
	Serial.println (iStatusRegisterInit);
	}  

	Serial.print (" -> Messkampagne1.Step3 RegInit=");
	Serial.println (iStatusRegisterInit);
	delay(100);

Hey Mr. WVESP32, thanks for your help,
With this code, can you use MODBUS only over wifi or also over ethernet?
It is strange that you don’t need <ethernet.h> library.

Hey Mr. Berguinsson,

yes of cource. Modbus works with both interfaces.
Connected LAN, so over LAN, disconnect LAN, then over WiFi.
Tip: Wifi is the base for communication, LAN participates from Wifi.
The project is more than 1 year ago, and i rememer there was a problem which lib if have included.
With many it doesn’t work, with the last constellation it works (_IDxxxx !!).
See my libs, hope it helps
grafik

1 Like

Hello dear WVESP32,
Thanks a lot for your info, i’m working with these libraries.
My question is, in ArduinoModbus library i had a modbusTCPServer (as you can see in the image which i appended) which is the object that did so many tasks : start listening for clients, configure registers…, and also, is the object which i have to mention to write in the registers ( e.g modbusTCPServer.holdingRegisterWrite(Direction, Value). Not using ArduinoModbus, thus, without using ModbusTCPServer.h, what object do you use or how do you do to carry out those tasks that in ArduinoModbus performanced ModbusTCPServer?
I’m looking forward to hearing from you.

Hi again WVESP32,
I realise that in your one year ago post, finally your code works using ModbusTCPServer and ModbusServer (i add the photo that you appended one year ago). How did you manage to use these library without using ArduinoModbus library, in my case, if i include these two libraries, then they call other ArduinoModbus libraries and i get the same errors of the pic that i uploaded two days ago.

Sorry for writing that in a different post, but i realised that after have written the first one.

Thank you.

Hello everyone,
Thanks to WVESP32, with your indications and some modifications more i solved the problem.
I’m posting what i did because it could help somebody in the future.
In ArduinoModbus, delete modbus-rtu.cpp of libmodbus folder.
I had a folder called “ArduinoRS485”, i saw that it is not necessary, thus, also delete this one.
In modbus-tcp.cpp of libmodbus folder, comment or delete line: "#define printf(…) {}.
This is what i had to do.
By the moment it works without any problem.
Have a nice weekend.

1 Like

Continuing the discussion from ESP32 Modbus TCP/IP protocol over ethernet:

if you want to using library ArduinoModbus.h and ArduinoRS485.h with Ethernet.h . you must try this

  1. Search file library RS485.h
    search code →
           #if __AVR__         
            #define RS485_DEFAULT_DE_PIN 2         
            #define RS485_DEFAULT_RE_PIN -1
         #else
            #define RS485_DEFAULT_DE_PIN A6        
            #define RS485_DEFAULT_RE_PIN A5
         #endif

Change Code to →

         #ifdef __AVR__
           #define RS485_DEFAULT_DE_PIN 2
           #define RS485_DEFAULT_RE_PIN -1
         #elif ESP8266
           #define RS485_DEFAULT_DE_PIN 5    //D1      
           #define RS485_DEFAULT_RE_PIN 4    //D2
         #elif ESP32
           #define RS485_DEFAULT_DE_PIN 34    //D34
           #define RS485_DEFAULT_RE_PIN 35    //D35
         #endif
  1. Search file library RS485.cpp
    search method => void RS485Class::begin(unsigned long baudrate, uint16_t config, int predelay, int postdelay)
    search code → _serial->begin(baudrate, config);
    change code to →
           #ifdef __AVR__
              _serial->begin(baudrate, config);
           #else
              _serial->begin(baudrate);
           #endif
 search method => void RS485Class::sendBreak(unsigned int duration)
 search code ->  _serial->begin(_baudrate, config);
 change code to ->
          #ifdef __AVR__
            _serial->begin(_baudrate, config);
          #else
            _serial->begin(_baudrate);
          #endif      
 Search method => void RS485Class::sendBreakMicroseconds(unsigned int duration)
 Search code => _serial->begin(_baudrate, config);
 change code to => 
          #ifdef __AVR__
            _serial->begin(_baudrate, config);
          #else
            _serial->begin(_baudrate);
          #endif

maybe this help

Can you propose these changes in the library you’re refering to so that they get fixed there?