ESP-Modbus Library

repository·main·Indexed 41 days ago

https://github.com/espressif/esp-modbus

A library for implementing Modbus communication protocols (RS485, WiFi, Ethernet) on Espressif ESP32 hardware using the ESP-IDF framework. It supports Modbus TCP, RTU, and ASCII modes, and provides a Modbus Controller abstraction using Characteristic Identifiers (CID) and Data Dictionaries to simplify register access.

Tokens
22.3K
Snippets
44
Records
96
Agent score
52%

What's inside ESP-Modbus

  1. Overview of the Modbus Master Example

    main

    This example demonstrates how to use the FreeModbus stack port implementation on ESP32-based devices to act as a Modbus Master.

    As a master, the device can read and write values from slave devices connected to a Modbus segment. The example uses a data dictionary to map characteristics (names and Characteristic IDs/CIDs) to specific registers on the slave devices. It also implements a simple control algorithm: if a specific parameter (e.g., holding_data0) exceeds a limit, the master triggers an alarm (e.g., activating a relay on the slave device).

    Key Concepts:

    • Characteristics: Data points identified by a name and a CID (e.g., Temperature_1 with CID_INP_DATA_1).
    • Data Dictionary: A mapping used by the master to know which CIDs to poll from which slave addresses.
    • Multi-slave segments: The master can communicate with multiple slaves by addressing different MB_DEVICE_ADDR values.
  2. Overview of ESP-Modbus Library

    main
    ESP-Modbus is a library providing support for the Modbus data communications protocol. It enables Modbus communication over networks based on RS485 or Ethernet interfaces, allowing ESP32 devices to connect to industrial electronic devices and PLCs.
  3. ESP-Modbus Slave Basic Example Overview

    main

    This example demonstrates how to implement a Modbus slave using the Esp-Modbus API on ESP-IDF. It is designed to teach newcomers the core components of slave implementation, including:

    • Slave setup and initialization: Configuring the Modbus stack for slave mode.
    • Register area descriptor configuration: Defining how the slave responds to specific Modbus register requests.
    • Request handling: Responding to Modbus master read/write requests over various transport layers, including Serial (RTU/ASCII) and TCP.
  4. Supported Modbus communication options

    main

    The ESP-Modbus library supports the standard communication options defined by the Modbus specification. These include RTU, ASCII, and TCP/IP variants. Note that if a specific vendor uses a subset of these options, you can override the standard settings using the master or slave setup APIs.

    RTU Communication

    • 1 start bit
    • 8 data bits (LSB first)
    • 1 bit for even/odd parity (or no bit for no parity)
    • 1 stop bit if parity is used; 2 stop bits if no parity
    • Uses Cyclical Redundancy Check (CRC)

    ASCII Communication

    • 1 start bit
    • 7-8 data bits (LSB first)
    • 1 bit for even/odd parity (or no bit for no parity)
    • 1 stop bit if parity is used; 2 stop bits if no parity
    • Uses Longitudinal Redundancy Check (LRC)

    TCP Communication

    • Client (master) - server (slave) communication over TCP/IP networks
    • Uses standard port 502
    • No checksum calculation required (handled by lower layers)
  5. Understand Modbus messaging and data mapping

    main

    Modbus is an application protocol that defines messaging structures independent of the transmission medium. In a Modbus segment, a Master controls communication and can talk to one or all connected Slaves, but slaves cannot communicate directly with each other.

    Data in Modbus is organized into four types of registers:

    1. Holding Registers
    2. Input Registers
    3. Discrete Inputs
    4. Coils

    When implementing a Modbus stack, it is assumed that the number of slaves and their specific register maps are known beforehand.

  6. How the Modbus Controller and Data Dictionary work

    main

    The ESP-Modbus architecture includes a Modbus controller layer above the standard IO driver. This layer uses a Data Dictionary to abstract physical device parameters (like temperature or humidity) into Characteristic Identifiers (CID).

    Instead of interacting directly with Modbus registers, upper layers (like MQTT or MESH) interact with these CIDs. This decouples the application logic from the specific Modbus register maps of the slave devices.

    The Data Dictionary

    The Data Dictionary is a user-defined array of mb_parameter_descriptor_t structures. Each entry links a unique CID to a specific Modbus register representation on a slave device. This mapping allows the stack to automatically handle data conversion and register addressing.

    // Concept: CID -> Data Dictionary -> Modbus Register
    // The Data Dictionary maps a unique CID to a physical Modbus register address/type.
  7. Configure Slave Data Access with mb_register_area_descriptor_t

    main

    The Modbus slave stack requires you to define user-provided memory structures to store Modbus parameters. You must assign these structures to the Modbus controller using the mbc_slave_set_descriptor API before starting communication.

    One slave can define multiple area descriptors for each type of Modbus register area by using different start_offset values.

    mb_register_area_descriptor_t Fields

    FieldDescription
    start_offsetZero-based register relative offset. (e.g., for holding register address 40002, start_offset = 2)
    typeType of the Modbus register area (refer to mb_param_type_t).
    addressPointer to the memory area used to store the register data.
    sizeThe size of the memory area in bytes.

    Note: If a master attempts to access an area that has not been defined via a descriptor, the stack will generate a Modbus exception.

    #define MB_REG_HOLD_CNT             (100)
    #define MB_REG_HOLDING_START_AREA0  (0)
    
    static void *slave_handle = NULL;
    mb_register_area_descriptor_t reg_area;
    uint16_t holding_reg_area[MB_REG_HOLD_CNT] = {0};
    
    reg_area.type = MB_PARAM_HOLDING;
    reg_area.start_offset = MB_REG_HOLDING_START_AREA0;
    reg_area.address = (void*)&holding_reg_area[0];
    reg_area.size = (sizeof(holding_reg_area) << 1); // Size in bytes
    reg_area.access = MB_ACCESS_RW;
    ESP_ERROR_CHECK(mbc_slave_set_descriptor(slave_handle, reg_area));
  8. How the Modbus Controller abstraction works

    main

    The ESP-Modbus implementation uses a Modbus Controller abstraction layer to simplify register access. It relies on two key concepts:

    Characteristic Identifier (CID)

    An abstraction representing a specific Modbus register on a Slave device. It encapsulates metadata such as the register name, type, and permissions. For example, CID_EX_0 might map to a specific holding register.

    Data Dictionary

    A list defining all Modbus registers the Master is authorized to access across the network. Each entry in the dictionary maps a CID to its corresponding Modbus registers (address, format, function code) on a Slave. This allows the application to request data by CID rather than managing raw register addresses manually.

    Read/Write Lifecycle

    1. mbc_master_set_descriptor(): Attaches the Data Dictionary to the master handle.
    2. mbc_master_get_cid_info(): Retrieves metadata (name, type, permissions) for a specific CID from the dictionary.
    3. mbc_master_get_parameter() / mbc_master_set_parameter(): Executes the actual Modbus read or write operation using the CID.
  9. Configure Slave IP Address Discovery

    main

    The Modbus Master can obtain Slave IP addresses using one of three methods:

    1. mDNS Discovery (Automatic): Enable CONFIG_MB_MDNS_IP_RESOLVER. This requires the Slaves to also have mDNS enabled and a unique Modbus Slave address configured.

    2. Manual Input via stdin: Enable CONFIG_MB_SLAVE_IP_FROM_STDIN and CONFIG_MB_CONSOLE_HELPER_ENABLED. When the console prompts Waiting IP<N> from stdin:, enter the address in the format: IP <N>=<IP_ADDRESS>;<PORT> (Where N = configured Slave address - 1. Example: IP 0=192.168.1.21;1502)

    3. Hardcoded in Source Code: Manually define the addresses in the slave_ip_address_table within the Master source code.

  10. How to manage multiple Modbus instances (v2.0.0+)

    main

    Starting from version v2.0.0, the ESP-Modbus library supports creating multiple independent instances of Modbus master and slave objects.

    To use multiple instances, follow this pattern:

    1. Define your configuration options in a predefined object.
    2. Use the appropriate constructor API, passing a pointer to your configuration object as the first parameter. This returns a pointer to the created communication object.
    3. Save this returned pointer.
    4. Use the saved pointer as the instance identifier (the first parameter) in all subsequent Modbus API function calls to ensure the correct instance is addressed.
  11. How the v2.x.x API handles multiple instances

    main

    The v2.x.x release of ESP-Modbus introduces a handle-based API to support multiple concurrent Modbus master and slave instances.

    Instead of a single global state, the constructor API now returns a handle to an interface structure. This handle must be passed as the first parameter to every subsequent API call associated with that specific communication object. This allows each instance to maintain its own unique communication parameters.