Library Download Modbus

Hi guys,
i’m new in PlatformIO forum.
My order was: “ESP32: include a Modbus TCP server application”

My Platform for Arduino “ESP32-EVB” is: PlatFormIO ( newest: Home 2.0.0 ), and VisualStudioCode
platform.io:
[env:xxxxxxx]
platform = espressif32
board = esp32-evb
framework = arduino
board_build.partitions = default.csv

What i’m doing (after reading some examples) inside PlatFormIO:

  1. append the new library “ArduinoModbus”
    … compiling: he said missing “ArduinoRS485” …

  2. so i append the new library “ArduinoRS485”

  3. i’m appending “lib_ldf_mode = deep+” in my platform.io, because installed libs are in:
    “….platformio\lib\ArduinoModbus_ID5816”
    “….platformio\lib\ArduinoRS485_ID5814”

My source modification is only 2 includes:

#include <ArduinoRS485.h> // ArduinoModbus depends on the ArduinoRS485 library
#include <ArduinoModbus.h>

then the compiler said:

D:\orcad\spb_data.platformio\lib\ArduinoRS485_ID5814\src\RS485.cpp: In member function ‘virtual void RS485Class::begin(long unsigned int)’:
D:\orcad\spb_data.platformio\lib\ArduinoRS485_ID5814\src\RS485.cpp:33:29: warning: large integer implicitly truncated to unsigned type [-Woverflow]
begin(baudrate, SERIAL_8N1);
^
D:\orcad\spb_data.platformio\lib\ArduinoRS485_ID5814\src\RS485.cpp: At global scope:
D:\orcad\spb_data.platformio\lib\ArduinoRS485_ID5814\src\RS485.cpp:169:18: error: ‘SERIAL_PORT_HARDWARE’ was not declared in this scope
RS485Class RS485(SERIAL_PORT_HARDWARE, RS485_DEFAULT_TX_PIN, RS845_DEFAULT_DE_PIN, RS845_DEFAULT_RE_PIN);
^
In file included from D:\orcad\spb_data.platformio\lib\ArduinoRS485_ID5814\src\RS485.cpp:20:0:
D:\orcad\spb_data.platformio\lib\ArduinoRS485_ID5814\src\RS485.h:35:30: error: ‘A6’ was not declared in this scope
#define RS845_DEFAULT_DE_PIN A6
^
D:\orcad\spb_data.platformio\lib\ArduinoRS485_ID5814\src\RS485.cpp:169:62: note: in expansion of macro ‘RS845_DEFAULT_DE_PIN’
RS485Class RS485(SERIAL_PORT_HARDWARE, RS485_DEFAULT_TX_PIN, RS845_DEFAULT_DE_PIN, RS845_DEFAULT_RE_PIN);
^
D:\orcad\spb_data.platformio\lib\ArduinoRS485_ID5814\src\RS485.h:36:30: error: ‘A5’ was not declared in this scope
#define RS845_DEFAULT_RE_PIN A5
^
D:\orcad\spb_data.platformio\lib\ArduinoRS485_ID5814\src\RS485.cpp:169:84: note: in expansion of macro ‘RS845_DEFAULT_RE_PIN’
RS485Class RS485(SERIAL_PORT_HARDWARE, RS485_DEFAULT_TX_PIN, RS845_DEFAULT_DE_PIN, RS845_DEFAULT_RE_PIN);
^
SOME .h FILES ARE MISSING !!!

Searching google for ‘SERIAL_PORT_HARDWARE’, found a: #define SERIAL_PORT_HARDWARE Serial1
but that makes no sense !!

Is there any way to solve this ???
Please help

Yes it does, it’s the HardwareSerial object to which your RS485 transceiver is connected to. Check the pin mapping of your ESP32 board to see which pins are correct for you. (e.g. here)

These pin definitions seem to be for a Arduino Uno/Mega type where it’s Analog Pin 5. Change that to the pin where you have the receiver enable / transmitter enable etc.

Can e.g. be done by defining the macro via build_flags = -D RS845_DEFAULT_DE_PIN=12 or whatever in the platformio.ini.

Hallo Max,

thanks for your quick reply…

It seems there is a small misunderstanding !!

  1. I NEVER NEED the RS485 for my project
    the missing definitions f.e. ‘SERIAL_PORT_HARDWARE’ and ‘A6’ …
    are coming out after the automatic installation of the two libs inside PlatformIO:
    “\ArduinoModbus_ID5816”
    “\ArduinoRS485_ID5814”

  2. it seems i need another lib for the default RS485 parts ??
    I think: “…take original Arduino libs, they must still be compatibel …” or ?

  3. i think:
    #include <ArduinoRS485.h>
    is not enough. There must be a deeper includ before ?

Greetings Wolfgang

Oh okay you’re trying to do Modbus via TCP/IP not via an actual RS485 transceiver. Seems you have the wrong library for that? Does the ArduinoModbus library say it can do TCP/IP Modbus?

Hallo Max,

no problem.

  1. YES they do:
    scr are always with xx.cpp and xxx.h
    ModbusClient ModbusRTUClient ModbusRTUServer ModbusTCPClient ModbusTCPServer

  2. but they discribe the pysical layer is always RS485 based.
    Thatsway we need RS485 ?!?!?

  3. maybe you have another solution, with other PlatformIO libraries ?

Greetings Wolfgang

Uh seems like you want PlatformIO Registry or PlatformIO Registry? Found via PlatformIO Registry. First one only implements a client.

1 Like

Hallo Max,
OK i see it also before installing my libs …
But “sunnyboy” example looks not so good like “ArduinoModbus” examples…

But i will try it tomorrow, and let you know wkat happens.

Thanks
Greetings Wolfgang

Hi Max,

i am a little bit confiused …

everytime i’m installing another lib inside platformio
i will get different errors.
I think there are some libs missmatched in the deep ?

First try: i always append only the include files to see what happens.
// TEST2
#include <SPI.h>
#include <Ethernet.h>
#include <Modbus.h>
#include <ModbusIP.h>

So after i included again a “Ethernet LIB” Ethernet by Paul Stoffregen
i have only one compile error:
In file included from src\Modbus_KE.cpp:58:0:
…/.platformio/lib/ModbusIP_ID1725/ModbusIP.h:20:24: error: cannot declare field ‘ModbusIP::_server’ to be of abstract type ‘EthernetServer’
EthernetServer _server;
^

This libs i have installed from PIO Home → libraries
grafik

Greetings Wolfgang

Hi Max,

Test3: i install your example: “5902/esp32ModbusTCP”
and again, only including the 3 #include files out of the example in my “Modbus_KE.cpp”:
#include <Arduino.h>
#include <WiFi.h>
#include <ModbusTCP.h>
=> error “ModbusTCP.h” not found ( and really it is NOT on my PC ! )

by the way:
I need a ModbusServer example that uses also Ethernet and WiFi on a ESP32-EVB board
( hardware: ESP32-WROOM-32 ).
It reads inside ESP32 board 10 Hz CAN-values and transmit it over Ethernet and/or Wifi to
an external PC.

Greetings Wolfgang

This one would probably never work, as it clearly states on the Library Registry it is for the Teensy platform, not the ESP32! :open_mouth:

For the esp32ModbusTCP library (id:5902), it looks like the author of that library has been making changes to the library and neglected to update the the example. Change the include and the object initialisation to the following (i.e esp32ModbusTCP instead of ModbusTCP).

#include <esp32ModbusTCP.h>
 
esp32ModbusTCP sunnyboy(3, {192, 168, 123, 123}, 502);

It’ll then start to compile, but then hit an 'esp32ModbusInternals' has not been declared error. I’m not sure why that is happening, as it appears esp32ModbusInternals is declared in Helper.h which is included by esp32ModbusTCP.cpp . Anyway, this is my platformio.ini and compile output.

platformio.ini

[env:esp32-evb]
platform = espressif32
board = esp32-evb
framework = arduino
lib_deps = 
   5902

Code:

#include <Arduino.h>
#include <WiFi.h>
#include <esp32ModbusTCP.h>

const char* ssid = "xxxx";
const char* pass = "xxxx";
bool WiFiConnected = false;

esp32ModbusTCP sunnyboy(3, {192, 168, 123, 123}, 502);

void setup() {
    Serial.begin(115200);

    WiFi.disconnect(true);  // delete old config
    WiFi.setAutoConnect(false);
    WiFi.setAutoReconnect(false);

    sunnyboy.onAnswer([](bool succes, MB_ADU mb_adu) {
      Serial.print("Received:\n");
      if (succes) {
        uint32_t deviceType = 0;
        uint8_t* value = mb_adu.value;
        deviceType = value[0];
        deviceType = deviceType << 8 | value[1];
        deviceType = deviceType << 8 | value[2];
        deviceType = deviceType << 8 | value[3];
        Serial.printf("Sunny Boy device type: %i\n", deviceType);
      } else {
        Serial.println("modbus error");
      }
    });

    delay(1000);

    WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t info) {
      Serial.print("WiFi connected. IP: ");
      Serial.println(IPAddress(info.got_ip.ip_info.ip.addr));
      WiFiConnected = true;
    }, WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP);
    WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t info){
        Serial.print("WiFi lost connection. Reason: ");
        Serial.println(info.disconnected.reason);
        WiFi.disconnect();
        WiFiConnected = false;
    }, WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);

    WiFi.begin(ssid, pass);

    Serial.println();
    Serial.println("Connecting to WiFi... ");
}

void loop() {
  static uint32_t lastMillis = 0;
  if ((millis() - lastMillis > 60000 &&
      WiFiConnected) ||
      lastMillis == 0) {
    lastMillis = millis();
    if (sunnyboy.request(READ_HOLD_REGISTER, 30053, 2)) {
      Serial.print("Requesting data\n");
    } else {
      Serial.print("Request not succeeded\n");
    }
  }
}

Compile log:

Processing esp32-evb (platform: espressif32; board: esp32-evb; framework: arduino)
---------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32-evb.html
PLATFORM: Espressif 32 > OLIMEX ESP32-EVB
HARDWARE: ESP32 240MHz 320KB RAM (4MB Flash)
DEBUG: CURRENT(esp-prog) EXTERNAL(esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF MODES: FINDER(chain) COMPATIBILITY(soft)
Collected 28 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <esp32ModbusTCP> 0.0.1
|   |-- <AsyncTCP> 1.0.3
|   |-- <ESP32 BLE Arduino> 1.0.1
|-- <WiFi> 1.0
Compiling .pioenvs/esp32-evb/src/main.cpp.o
Generating partitions .pioenvs/esp32-evb/partitions.bin
Compiling .pioenvs/esp32-evb/lib288/AsyncTCP_ID1826/AsyncTCP.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLE2902.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLE2904.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEAddress.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEAdvertisedDevice.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEAdvertising.cpp.o
Archiving .pioenvs/esp32-evb/lib288/libAsyncTCP_ID1826.a
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEBeacon.cpp.o
Indexing .pioenvs/esp32-evb/lib288/libAsyncTCP_ID1826.a
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLECharacteristic.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLECharacteristicMap.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEClient.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEDescriptor.cpp.o
/home/pfeerick/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src/BLECharacteristic.cpp: In member function 'void BLECharacteristic::setValue(float&)':
/home/pfeerick/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src/BLECharacteristic.cpp:680:16: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
*((float*)temp) = data32;
^
/home/pfeerick/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src/BLECharacteristic.cpp: In member function 'void BLECharacteristic::setValue(double&)':
/home/pfeerick/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src/BLECharacteristic.cpp:686:17: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
*((double*)temp) = data64;
^
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEDescriptorMap.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEDevice.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEEddystoneTLM.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEEddystoneURL.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEExceptions.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEHIDDevice.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLERemoteCharacteristic.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLERemoteDescriptor.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLERemoteService.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEScan.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLESecurity.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEServer.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEService.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEServiceMap.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEUUID.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEUtils.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/BLEValue.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/FreeRTOS.cpp.o
Compiling .pioenvs/esp32-evb/libbc4/BLE/GeneralUtils.cpp.o
Compiling .pioenvs/esp32-evb/lib27d/esp32ModbusTCP_ID5902/esp32ModbusTCP.cpp.o
Compiling .pioenvs/esp32-evb/lib114/WiFi/ETH.cpp.o
.piolibdeps/esp32ModbusTCP_ID5902/src/esp32ModbusTCP.cpp: In member function 'void esp32ModbusTCP::_send()':
.piolibdeps/esp32ModbusTCP_ID5902/src/esp32ModbusTCP.cpp:138:25: error: 'esp32ModbusInternals' has not been declared
memset(&_TXBuff[0], esp32ModbusInternals::high(mb_adu.id), 1);
^
.piolibdeps/esp32ModbusTCP_ID5902/src/esp32ModbusTCP.cpp:139:25: error: 'esp32ModbusInternals' has not been declared
memset(&_TXBuff[1], esp32ModbusInternals::low(mb_adu.id), 1);
^
Compiling .pioenvs/esp32-evb/lib114/WiFi/WiFi.cpp.o
/home/pfeerick/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src/GeneralUtils.cpp: In static member function 'static void GeneralUtils::dumpInfo()':
/home/pfeerick/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src/GeneralUtils.cpp:115:9: warning: unused variable 'freeHeap' [-Wunused-variable]
size_t freeHeap = heap_caps_get_free_size(MALLOC_CAP_8BIT);
^
*** [.pioenvs/esp32-evb/lib27d/esp32ModbusTCP_ID5902/esp32ModbusTCP.cpp.o] Error 1
=========================================================== [ERROR] Took 11.65 seconds ===========================================================

Hi, sorry for the long delay.

I give the ModbusTCP a chance, and actual it works for me.
Why: Because the examples are working and i need a Server/Slave mode.
My hardware is SLAVE: modbusTCPServer.begin() and PC is Master/Client
I’m filtering out all files i need, and exclude everything with ModbusRTU = RS485, because of “RS485Class RS485(SERIAL_PORT_HARDWARE)”

grafik

C and h nearly identical

Modbus Library with ID5816 is working for me.
I can define 20 InputRegisters and can read them in 10 Hz from the PC.
Initialisation: …ETH.begin(), and wifiServer.begin(), so switching is possible about flag “eth is connected”

Thanks a lot
Greetings Wolfgang

2 Likes

Hi WVESP32! I have to do the same of you for my end of degree project, i must use MODBUS protocol over ethernet with my esp32 board. Could you told me exactly what modification did you have to do?
I append my actual declaration and setup code working for Arduino Uno but not for ESP32 WeMos Board. I append the warnings that i get when i compile the code in the ESP32 board.

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");
}

The error message is pointing specifically to the printf define at line 32 of the modbus library you are using (which is the new Modbus library included with the Arduino IDE?). The mention of line 74 of Print.h from the ESP32 core is just a warning… but it may also be an indicator of a conflict because core/boards the library is intended to support don’t support use of the printf statement, whereas the ESP32 core does.

Since you’re using the Arduino IDE, it may be better to ask your question over on the Arduino Forum, rather than on the one for PlatformIO…

Hi pfeerick,
Yes, i use ArduinoModbus library, what library would you use for using Modbus TCP with ESP32?
I saw that one year ago you talked about the library of “sunnyboy” (esp32ModbusTCP) but at the end, our mate WVESP32 looked like he discarded that library and use other ones. Actually, i think i have the problem with ModbusTCPServer.WVESP32 didn’t use ArduinoModbus library but he used ModbusTCPServer, a library which if i include it, calls ArduinoModbus and i have the printf error again.

I expect your answer. Thank you.

Hey pfeerick,
Finally it works, i indicated the changes that i did in the post i opened two days ago.
Thanks for your help.
Have a nice weekend.

1 Like

Glad you worked it out. I don’t use ModbusTCP with the ESP32 (rather, RS485 Modbus with ESP8266), so couldn’t have helped you with that anyway.

It seems the alteration that I would have suggested, i.e. deleting or commenting out the #define printf(...) {} line in modbus-tcp.cpp worked for you, so hopefully that helps someone else in the future. If I come across the github repo for that library, I’ll do a pull request suggesting they wrap it with
!ifndef ESP8266 so future versions of the library work without needing that change.