Modbus

Page Contents

References

Brief Intro

  • Big endian, application layer messaging protocol,

  • Request / reply protocol, services specified by function codes. A working slave must always respond with either an exception or a meaningful result.

  • Simple PDU (protocol data unit):

    • 1-byte function code, followed by data: {Function Code | Data}
      Prodocol Data Unit (PDU)
      Func Code Data
      1 byte n bytes
    • Built by client, sent to server,
    • Max size when taking into account ADU header and footer = 256 bytes - server address (1 byte) - CRC (2bytes) = 253 bytes,
    • Function tells server what action to perform,
    • Three types:
      • MODBUS request - mb_req_pdu = {function_code, request_data},
      • MODBUS response - mb_rsp_pdu = {function_code, response_data} - Normal response echoes function code back,
      • MODBUS exception response - mb_excep_rsp_pdu = {exception-function_code, exception-code} - Exception response echoes function code | 0x80. Exception code is one of:

        Exception CodeMeaning
        0x01Illegal function
        0x02Illegal data address
        0x03Illegal data value
        0x04Slave device failure
        0x05Acknowledge
        0x06Slave device busy
        0x07n/a
        0x08Memory parity error
        0x09n/a
        0x0AGateway path unavailable
        0x0BGateway target failed to respond

    • In PDU each data item address from 0 to 65535,
  • ADU (application data unit):

    • Wraps a PDU : Additional address | PDU | Error check = Additional address | Function Code | Data | Error check,
    • Adds an address prefix and a CRC suffix,
    • Lets MODBUS work on specific busses,
  • The RTU frame over RS485 looks like this:

    Prodocol Data Unit (PDU)
    Start Slave ID Func Code Data CRC Stop
    3.5 bytes 1 byte 1 byte n bytes 2 bytes 3.5 bytes
    Application Data Unit (ADU)

    In the same way that the client device echoes back the function code to the master, it also echoes back it's own ID in its response. This is so that the master knows who the response is from [Ref].

  • Data model based on "tables", which are essentially registers of which there ar 4 types:

    • Discrete inputs - RO single bits,
    • Coils - RW single bits,
    • Input registers - RO 16-bit words,
    • Holding registers - RW 16-bit words,

    "Tables" can overlay eachother or not,

    For each table, protocol allows individual selection of 65,536 data items,

  • Function codes:

    • Public:
      • Well defined and guaranteed unique,
      • Validated by MODBUS-IDA,
      • Conformance test available,
      • 1 - 64

      Most commonly recognised ones are:

      Function Code Register Type
      1 Read Coil
      2 Read Discrete Input
      3 Read Holding Reigsters
      4 Read Input Registers
      5 Write Single Coil
      6 Write Single Holding Register
      15 Write Multiple Coils
      16 Write Multiple Holding Registers

    • User definded:
      • No guarantee of uniqueness,
      • 65 - 72 or 100 to 110
    • Reserved

Some Public 16-bit Access Tables

A summary of some of the most common 16-bit tables (read registers):

Read Holding Registers 0x03
  • Request:
    Function code1 byte0x03
    Start address2 bytes
    Num registers2 bytes0x0001 to 0x007D
  • Response:
    Function code1 byte0x03
    Byte count1 byte2N
    Register value2N bytes
  • RError:
    Error code1 byte0x83
    Exception code1 byte1, 2, 3 or 4
Read Input Register 0x04
  • Request:
    Function code1 byte0x04
    Start address2 bytes
    Num registers2 bytes0x0001 to 0x007D
  • Response:
    Function code1 byte0x04
    Byte count1 byte2N
    Input registers2N bytes
  • RError:
    Error code1 byte0x84
    Exception code1 byte1, 2, 3 or 4
Write Single Register 0x06
  • Request:
    Function code1 byte0x06
    Register address2 bytes
    Value2 bytes
  • Response:
    Function code1 byte0x06
    Register address2 bytes
    Value2 bytes
  • RError:
    Error code1 byte0x86
    Exception code1 byte1, 2, 3 or 4
Write Multiple Register 0x16
Read/Write Multiple Register 0x23
Mask Write Register 0x22
Read Exception Stats 0x07
Diagnostic 0x08 Subcodes 0x00-0x18, 0x20

Nice YouTube Tutorial

Command Line Utility - Modpoll

Modpoll is a command line based Modbus master simulator and test utility. It runs on Windows and Linux.

Example usage (note that unless specified modpoll assumes register addresses start at 0x1):

    modpoll [-0] -1 -a 101 -r 1 -c 5 -b 2400 -p none -t 4:hex COM5 [Write values]
              ^   ^  ^      ^    ^                      ^           ^
              ^   ^  ^      ^    ^                      ^           If not present then read else write
              ^   ^  ^      ^    ^                      ^
              ^   ^  ^      ^    ^                      16-bit holding registers, display as hex
              ^   ^  ^      ^    Number of registers to read
              ^   ^  ^      Number of first register read
              ^   ^  Address of slave device
              ^   Poll only once then exit
              First reference is 0 (PDU addressing) instead 1

Complete help listing:

modpoll 3.6 - FieldTalk(tm) Modbus(R) Master Simulator
Copyright (c) 2002-2018 proconX Pty Ltd
Visit https://www.modbusdriver.com for Modbus libraries and tools.

Usage: modpoll [OPTIONS] SERIALPORT|HOST [WRITEVALUES...]
Arguments:
SERIALPORT    Serial port when using Modbus ASCII or Modbus RTU protocol
              COM1, COM2 ...                on Windows
              /dev/ttyS0, /dev/ttyS1 ...    on Linux
HOST          Host name or dotted IP address when using MDBUS/TCP protocol
WRITEVALUES   List of values to be written. If none specified (default) modpoll reads data.
General options:
-m ascii      Modbus ASCII protocol
-m rtu        Modbus RTU protocol (default if SERIALPORT contains \ or COM)
-m tcp        MODBUS/TCP protocol (default otherwise)
-m udp        MODBUS UDP
-m enc        Encapsulated Modbus RTU over TCP
-a #          Slave address (1-255 for serial, 0-255 for TCP, 1 is default)
-r #          Start reference (1-65536, 100 is default)
-c #          Number of values to read (1-125, 1 is default)
-t 0          Discrete output (coil) data type
-t 1          Discrete input data type
-t 3          16-bit input register data type
-t 3:hex      16-bit input register data type with hex display
-t 3:int      32-bit integer data type in input register table
-t 3:mod      32-bit module 10000 data type in input register table
-t 3:float    32-bit float data type in input register table
-t 4          16-bit output (holding) register data type (default)
-t 4:hex      16-bit output (holding) register data type with hex display
-t 4:int      32-bit integer data type in output (holding) register table
-t 4:mod      32-bit module 10000 type in output (holding) register table
-t 4:float    32-bit float data type in output (holding) register table
-i            Slave operates on big-endian 32-bit integers
-f            Slave operates on big-endian 32-bit floats
-e            Use Daniel/Enron single register 32-bit mode (implies -i and -f)
-0            First reference is 0 (PDU addressing) instead 1
-1            Poll only once only, otherwise every poll rate interval
-l #          Poll rate in ms, (1000 is default)
-o #          Time-out in seconds (0.01 - 10.0, 1.0 s is default)
Options for MODBUS/TCP, UDP and RTU over TCP:
-p #          IP protocol port number (502 is default)
Options for Modbus ASCII and Modbus RTU:
-b #          Baudrate (e.g. 9600, 19200, ...) (19200 is default)
-d #          Databits (7 or 8 for ASCII protocol, 8 for RTU)
-s #          Stopbits (1 or 2, 1 is default)
-p none       No parity
-p even       Even parity (default)
-p odd        Odd parity
-4 #          RS-485 mode, RTS on while transmitting and another # ms after