bertmelis / esp32ModbusRTU

modbus RTU client for ESP32
MIT License
70 stars 44 forks source link
arduino async esp32 modbus-master modbus-rtu

ARCHIVED

This repo is archived no longer actively maintained.

For a complete Modbus library for ESP32, I invite you to https://github.com/eModbus/eModbus

esp32ModbusRTU

Build Status

This is a non blocking Modbus client (master) for ESP32.

Developement status

I have this library in use myself with quite some uptime (only using FC3 -read holding registers- though).

Things to do, ranked:

Installation

The easiest, and my preferred one, method to install this library is to use Platformio. https://platformio.org/lib/show/5902/esp32ModbusTCP/installation

Alternatively, you can use Arduino IDE for developement. https://www.arduino.cc/en/guide/libraries

Arduino framework for ESP32 v1.0.1 (January 2019) or higher is needed. Previous versions contain a bug where the last byte of the messages are truncated when using DE/RE Arduino framework for ESP32 (https://github.com/espressif/arduino-esp32)

Example hardware:

   3.3V --------------+-----/\/\/\/\---+
                      |       680      |
              +-------x-------+        |
    17 <------| RO            |        |
              |              B|--------+-------------------------
    16 --+--->| DE  MAX3485   |        |                   \  /
         |    |               |        +-/\/\/\/\-+    RS-485 side
         +--->| /RE           |             120   |        /  \
              |              A|-------------------+---------------
     4 -------| DI            |                   |
              +-------x-------+                   |
                      |                           |
                      +-----/\/\/\/\--------------+
                      |       680
                      +----------------/\/\/\/\------------------ GND
                      |                  100
                     ---

The biasing resistors may not be neccesary for your setup. The GND connection is connected via a 100 Ohms resistor to limit possible ground loop currents.

Usage

The API is quite lightweight. It takes minimal 3 steps to get going.

First create the ModbusRTU object. The constructor takes two arguments: HardwareSerial object and pin number of DE/RS.

esp32ModbusRTU myModbus(&Serial, DE_PIN);

Next add a onData callback. This can be any function object. Here it uses a simple function pointer.


void handleData(uint8_t serverAddress, esp32Modbus::FunctionCode fc, uint8_t* data, size_t length) {
  Serial.printf("received data: id: %u, fc %u\ndata: 0x", serverAddress, fc);
  for (uint8_t i = 0; i < length; ++i) {
    Serial.printf("%02x", data[i]);
  }
  Serial.print("\n");
}

// in setup()
myModbus.onData(handleData);

Optionally you can attach an onError callback. Again, any function object is possible.

// in setup()
myModbus.onError([](esp32Modbus::Error error) {
  Serial.printf("error: 0x%02x\n\n", static_cast<uint8_t>(error));
});

After setup, start the modbusmaster:

// in setup()
myModbus.begin();

Now ModbusRTU is setup, you can start reading or writing. The arguments depend on the function used. Obviously, serverID, address and length are always required. The length is specified in words, not in bytes!

myModbus.readInputRegisters(0x01, 52, 2);  // serverId, address + length

The requests are places in a queue. The function returns immediately and doesn't wait for the server to respond. Communication methods return a boolean value so you can check if the command was successful.

Configuration

The request queue holds maximum 20 items. So a 21st request will fail until the queue has an empty spot. You can change the queue size in the header file or by using a compiler flag:

#define QUEUE_SIZE 20

The waiting time before a timeout error is returned can also be changed by a #define variable:

#define TIMEOUT_MS 5000

Issues

Please file a Github issue if when you find a bug. You can also use the issue tracker for feature requests.

Extra

For modbus-TCP, check out esp32ModbusTCP