Modbus

Modbus is a well known standard to communicate to devices. The modbus specification is free available from http://www.modbus.orgDifferent media is available:

  1. Serial communication point to point via RS232

  2. Multidrop bus RS485

  3. TCP/IP Ethernet port 502 (and for non root users 1502)

Terms and definitions

In simple terms, modbus has a server (slave) that has been polled by a master (client). The data exchanged can be either bits or 16bit wide words. Modbus supports the following data objects, that can exist multiple times in a device and therefore an address is used to select:

  1. Coils are bit outputs, that probably traditionally controlled relays coils. Their value can be read back.

  2. Discrete inputs are bit inputs

  3. Input registers are 16 bit wide

  4. Holding registers are 16 bit wide output registers that can be read back.

Inside the modbus protocol the address can be a value starting from 0. To know what is addressed the address plus the data object (Coils, Discrete Input, Input register or Holding register) must be specified as well. Some people like numbers and are adding an additional number to the address to define the data object. So the following assignment results, where the first number is just a prefix and does not take part of the modbus address:

0xxxx - Coils
1xxxx - Discrete inputs
3xxxx - Input registers (it is not a bug 3 and not 2 is the prefix)
4xxxx - Holding registers

An other mess might exist, the lowest modbus address is 0, inside documentation of a device it might be 1. This is just a redefinition or mapping issue.

Since modbus has a long history the term coil needs some explanation:

Write Single Coil (function code 0x05) means write an output bit, probably the first modbus implementations used relays to exchange data

Read Coils (function code 0x01) means read back the status of the output bits

Read Discrete Inputs (function code 0x02) means read the input bits

Data is exchanged in the following formats:

  1. Protocol Data Unit (PDU) is the pure data free of addressing information

  2. Application Data Unit (ADU) is PDU plus addressing data and checksum. In case of Modbus TCP/IP, no check sum is there since this is already very well handled by TCP/IP.

Within the PDU there are two data files:

  1. The 8bit wide function Function code. Usually the function code is sent is echoed back. However on a failure, the most significant bit is set to indicated that the transmission of the data failed. This is called an exception.

  2. Contains the data to be transmitted. It can be data to be sent or to be received or in case of failure, it can be an exception code that indicates the reason. Due to historic reasons the data can be maximum 253 byte, since the size of the RS232/485 ADU was set to 256 byte, on TCP/IP the ADU size can be up to 260 bytes.

The data transmission mode must be per default RTU (Remote Terminal Unit) that uses binary data to be more compact, as an option it can also be human readable ASCII.

Libmodbus

Libmodbus is a library to get modbus support under Linux. First get it on the PC emerge libmodbus. This installs the libraries well, but the sample code is not merged. Therefore go to /usr/portage/distfiles and copy/extract the libmodbus archive to a directory where you like to work.

Goto the test directory where sample applications are. There are always two of them a master application that requests the connection and a slave application that responses. Now compile them as

gcc random-test-slave.c -o random-test-slave `pkg-config --libs --cflags modbus`

To test you need to start first the slave in a window and then the master in an other window. The programs communicates just with the IP address 127.0.0.1 and therefore the data does not leave the computer.

      modbus_init_tcp(&mb_param, "127.0.0.1", 1502);

To communicate to an other computer, the source code must be modified. Therefore check out the IP address using ifconfig and add it to the master code.

      modbus_init_tcp(&mb_param, "192.168.1.31", 1502);

Now compile and run it.

Freemodbus

The freemodbus package is more targeted to small cpu's not necessary running an operating system. See https://www.freemodbus.org/. There are sample demo projects for different microcontrollers as for the AVR family. However your specific AVR might not be directly supported, as the ATmega324P. To support it, you have to modify just the files in the subdirectory /port. Files to modify are:

  1. port.h

  2. portserial.c

Since the freemodbus packed is targeted to small microprocessors and such microprocessors do not have a huge amount of RAM, no modbus table is preset. Instead freemodbus allows to access the peripherals directly without the need to copy the data into RAM. The following functions are called to get and write the data:

  1. eMBRegInputCB

  2. eMBRegHoldingCB

  3. eMBRegCoilsCB

  4. eMBRegDiscrete

A parameter can be passed to the functions eMBRegCoilsCB and eMBRegCoilsCB to define if the function writes or reads.

Freemodbus supports RS485. With a #define RTS_ENABLE a pin of the microcontroller gets active that can control the direction of the RS485 driver chip (75176).

Support for modbus TCP/IP is there but this has a higher complexity since a TCP/IP stack is required. For Linux


Linurs Servernest startpage