modbus-esp8266

repository·master·Indexed 20 days ago

https://github.com/emelianov/modbus-esp8266

A versatile Modbus library for Arduino supporting RTU, TCP, and Secure TCP (TLS) protocols. It enables the implementation of Modbus Servers and Clients on ESP8266, ESP32, and Arduino boards with Ethernet shields. The library uses an asynchronous execution model via a task() function and provides features for handling complex data types, register read/write callbacks, raw request/response functions, and the creation of Modbus bridges.

Tokens
15.4K
Snippets
40
Records
67
Agent score
70%

What's inside modbus-esp8266

  1. Overview of Modbus Library for Arduino

    master

    This library provides comprehensive Modbus support for Arduino platforms, including RTU, TCP, and Secure TCP (TLS) implementations. It is designed with a callback-driven architecture and supports both Client (Master) and Server (Slave) roles in various combinations.

    Supported Modbus Functions:

    • 0x01 - Read Coils
    • 0x02 - Read Input Status (Read Discrete Inputs)
    • 0x03 - Read Holding Registers
    • 0x04 - Read Input Registers
    • 0x05 - Write Single Coil
    • 0x06 - Write Single Register
    • 0x0F - Write Multiple Coils
    • 0x10 - Write Multiple Registers
    • 0x14 - Read File Record
    • 0x15 - Write File Record
    • 0x16 - Mask Write Register
    • 0x17 - Read/Write multiple registers
  2. Understand the Modbus communication model

    master

    The library operates using an asynchronous execution model for both Clients and Servers.

    Client Model

    When you call a function like readHreg(), the library does not wait for the response. Instead, it sends the request and immediately exits. The response is processed by the task() function as soon as it arrives.

    Server Model

    The server waits for incoming requests and processes them via the task() function.

    Important: Asynchronous Behavior

    Because calls are asynchronous, you cannot expect data to be available immediately after calling a read function. You must rely on the task() function to handle the incoming data and use callbacks or check status to know when a transaction is complete. If you call multiple read/write functions (e.g., readCoil, readHreg, writeHreg) in rapid succession, only the first one will be executed until the current transaction is finished.

  3. Handle complex data types like `float` or `uint32_t`

    master

    The Modbus standard only natively supports two data types: bit values and 16-bit values. To send larger or more complex data types, you must split them into multiple 16-bit registers.

    • int16_t (Signed 16-bit): Can be sent as a single 16-bit value.
    • float or uint32_t: Must be sent as multiple 16-bit values (typically two 16-bit registers).
  4. Switch between Modbus Master and Slave modes

    master

    Use server(uint8_t slaveId) to initialize the device as a Slave (Server). Use client() to initialize as a Master (Client) in TCP mode, or use the RTU equivalent logic.

    Warning: Switching between modes at runtime is not supported and will result in unpredictable behavior.

    • In Slave mode, server() returns the configured slave ID.
    • In Master mode, server() returns the slave ID for the active request, or 0 if no request is in progress.
  5. Supported Modbus Implementations and Roles

    master

    The library can be used in any combination of the following instances:

    • Modbus RTU: Server or Client.
    • Modbus TCP: Server or Client (supports ESP8266/ESP32 and Ethernet libraries).
    • MODBUS/TCP Security (TLS): Server (ESP8266) or Client (ESP8266/ESP32).

    Key Features:

    • Supports all Arduino platforms.
    • Callback-driven design for handling events.
    • Advanced use cases like firmware updates over Modbus and RTU-to-TCP bridging.
  6. Implement a Modbus Bridge using Bridge functions

    master

    The library provides specialized functions to create 'Bridges' that move data between different Modbus protocols or between a remote server and local registers.

    Common bridge patterns include:

    • Basic Bridge: Pulls data from a remote Modbus Server and stores it in local registers, which can then be accessed via a local Modbus Client instance.
    • ModbusRTU to ModbusTCP Bridge: A full-functional bridge converting RTU traffic to TCP.
    • Multiple Server ID: Allows a single device to respond to multiple ModbusRTU IDs.
    • ModbusTCP to Modbus RTU Simulator: A bridge that includes an on-device ModbusRTU simulator.
  7. Connect ESP32 to W5x00 Ethernet Controller

    master

    To use the W5x00 (e.g., W5500) Ethernet controller with an ESP32, connect the SPI pins according to the following mapping:

    • MOSI: GPIO23
    • MISO: GPIO19
    • SCLK: GPIO18
    • SCS (Chip Select): GPIO5
    /* SPI Pin Mapping for ESP32 <--> W5500 */
    // GPIO23  <--> MOSI
    // GPIO19  <--> MISO
    // GPIO18  <--> SCLK
    // GPIO5   <--> SCS
  8. Explore Modbus implementation examples

    master

    The repository provides several specialized examples depending on your hardware and communication protocol requirements:

    • ModbusRTU: Master and slave implementations for serial communication.
    • ModbusTCP (ESP8266/ESP32): Client and server implementations specifically for ESP8266 and ESP32 microcontrollers.
    • ModbusTCP (Ethernet W5x00): Client and server implementations for Arduino boards using W5x00 series Ethernet shields.
    • ModbusTCP Security (TLS): Client-only implementations for ESP8266 and ESP32 using TLS for secure communication.
    • ModbusRTU to ModbusTCP Bridge: A pattern for accessing a ModbusRTU slave device via a ModbusTCP server hosted on an ESP8266/ESP32.
  9. Use the Modbus TCP Client API

    master

    To act as a Modbus client on an ESP8266/ESP32, you must first initialize the client and establish a connection to a remote server.

    Important Lifecycle Note: The read/write functions are asynchronous. They send the request and return immediately. The value pointer will not contain the result when the function returns; instead, the data is populated once the response arrives and is processed by the library's .task() function. To check if a transaction is complete, use isTransaction(id) or provide a callback function.

    // 1. Initialize
    client();
    
    // 2. Connect
    if (connect(IPAddress(192, 168, 1, 10), 502)) {
        // 3. Send request (returns transaction ID)
        uint16_t id = readHreg(IPAddress(192, 168, 1, 10), 100, &myValue);
        
        // 4. Wait for result (polling or callback)
        while (!isTransaction(id)) {
            // Do other things or call task()
        }
        // Now myValue is populated
    }
  10. Configure Modbus RTU Serial Port

    master

    To use Modbus RTU, you must assign a Serial port using begin(). You can use SoftwareSerial, HardwareSerial, or any Stream object.

    If using a MAX-485 transceiver, use the txEnablePin parameter to control the transmit enable pin. If your hardware uses inverse logic for the enable pin, set txEnableDirect=false.

    For non-ESP devices, if you need to override the baudrate, call setBaudrte(uint32 baud) after calling .begin().

    modbus.begin(Serial, -1, true); // HardwareSerial, no TX enable pin
    // OR
    modbus.begin(mySoftwareSerial, 4, true); // SoftwareSerial, TX enable on pin 4
    modbus.setBaudrte(9600);