dm_modbus Module

Abstraction layer over libmodbus, for Modbus RTU/TCP communication.

You may want to use the functions dm_to_signed() and dm_to_unsigned() available in module dm_c to convert unsigned to signed integers and vice versa.

Use Modbus function code 0x03 to read holding registers from a Modbus RTU connection:

integer           :: i, rc, s
integer(kind=u2)  :: regs(2)
type(modbus_type) :: modbus

! Create Modbus RTU context and connect to device 10.
rc = dm_modbus_create(modbus    = modbus, &
                      path      = '/dev/ttyUSB0', &
                      baud_rate = TTY_B19200, &
                      byte_size = TTY_BYTE_SIZE8, &
                      parity    = TTY_PARITY_EVEN, &
                      stop_bits = TTY_STOP_BITS1)
rc = dm_modbus_connect(modbus)
rc = dm_modbus_set_slave(modbus, slave=10)

! Read and output two registers.
rc = dm_modbus_read_registers(modbus, address=50, registers=regs)

do i = 1, size(registers)
    s = dm_to_signed(regs(i))
    print '("regs(", i0, ") = ", i0, " (0x", z0, ")")', i, s, s
end do

! Print the two registers as real in ABCD byte order.
print '(f12.8)', dm_modbus_get_real_abcd(regs)

! Disconnect and clean-up.
call dm_modbus_close(modbus)
call dm_modbus_destroy(modbus)

In production, add additional error handling of the return codes.

References


Uses

  • module~~dm_modbus~~UsesGraph module~dm_modbus dm_modbus iso_c_binding iso_c_binding module~dm_modbus->iso_c_binding modbus modbus module~dm_modbus->modbus modbus_rtu modbus_rtu module~dm_modbus->modbus_rtu modbus_tcp modbus_tcp module~dm_modbus->modbus_tcp module~dm_c dm_c module~dm_modbus->module~dm_c module~dm_error dm_error module~dm_modbus->module~dm_error module~dm_kind dm_kind module~dm_modbus->module~dm_kind module~dm_c->iso_c_binding module~dm_c->module~dm_kind module~dm_error->module~dm_kind module~dm_ascii dm_ascii module~dm_error->module~dm_ascii iso_fortran_env iso_fortran_env module~dm_kind->iso_fortran_env

Used by

  • module~~dm_modbus~~UsedByGraph module~dm_modbus dm_modbus module~dmpack dmpack module~dmpack->module~dm_modbus

Variables

Type Visibility Attributes Name Initial
integer, public, parameter :: MODBUS_MODE_NONE = 0

None (invalid).

integer, public, parameter :: MODBUS_MODE_RTU = 1

Modbus RTU (Remote Terminal Unit).

integer, public, parameter :: MODBUS_MODE_TCP = 2

Modbus TCP (Transmission Control Protocol).

integer, public, parameter :: MODBUS_REAL_ABCD = 0

ABCD byte order.

integer, public, parameter :: MODBUS_REAL_BADC = 1

BADC byte order.

integer, public, parameter :: MODBUS_REAL_CDAB = 2

CDBA byte order.

integer, public, parameter :: MODBUS_REAL_DCBA = 3

DCBA byte order.


Interfaces

public interface dm_modbus_create

Generic function to create Modbus RTU or TCP context.

  • public function dm_modbus_create_rtu(modbus, path, baud_rate, byte_size, parity, stop_bits) result(rc)

    Creates a new Modbus RTU context.

    The function returns the following error codes:

    • E_INVALID if a given argument is invalid.
    • E_MODBUS if no Modbus context could be created.

    Arguments

    Type IntentOptional Attributes Name
    type(modbus_type), intent(out) :: modbus

    Modbus type.

    character(len=*), intent(in) :: path

    Device path.

    integer, intent(in) :: baud_rate

    Baud rate enumerator (TTY_B*).

    integer, intent(in) :: byte_size

    Byte size enumerator (TTY_BYTE_SIZE*).

    integer, intent(in) :: parity

    Parity enumerator (TTY_PARITY_*).

    integer, intent(in) :: stop_bits

    Stop bits enumerator (TTY_STOP_BITS*).

    Return Value integer

  • public function dm_modbus_create_tcp(modbus, address, port) result(rc)

    Creates a new Modbus TCP context.

    The function returns the following error codes:

    • E_INVALID if the given arguments are invalid.
    • E_MODBUS if no Modbus context could be created.

    Arguments

    Type IntentOptional Attributes Name
    type(modbus_type), intent(out) :: modbus

    Modbus type.

    character(len=*), intent(in) :: address

    IPv4 address.

    integer, intent(in) :: port

    Port number.

    Return Value integer


Derived Types

type, public ::  modbus_type

Opaque Modbus RTU/TCP context type.


Functions

public function dm_modbus_byte_order_from_name(name, byte_order) result(rc)

Returns byte order named parameter associated with given string. Sets argument byte_order to MODBUS_REAL_ACBD if string is ABCD (case insensitive). Returns E_INVALID and sets byte_order to MODBUS_REAL_ABCD if the string is invalid.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: name

Input string.

integer, intent(out) :: byte_order

Byte order of real values.

Return Value integer

public function dm_modbus_connect(modbus) result(rc)

Connects to Modbus RTU/TCP device.

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(inout) :: modbus

Modbus type.

Return Value integer

public function dm_modbus_create_rtu(modbus, path, baud_rate, byte_size, parity, stop_bits) result(rc)

Creates a new Modbus RTU context.

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(out) :: modbus

Modbus type.

character(len=*), intent(in) :: path

Device path.

integer, intent(in) :: baud_rate

Baud rate enumerator (TTY_B*).

integer, intent(in) :: byte_size

Byte size enumerator (TTY_BYTE_SIZE*).

integer, intent(in) :: parity

Parity enumerator (TTY_PARITY_*).

integer, intent(in) :: stop_bits

Stop bits enumerator (TTY_STOP_BITS*).

Return Value integer

public function dm_modbus_create_tcp(modbus, address, port) result(rc)

Creates a new Modbus TCP context.

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(out) :: modbus

Modbus type.

character(len=*), intent(in) :: address

IPv4 address.

integer, intent(in) :: port

Port number.

Return Value integer

public function dm_modbus_error_message() result(message)

Returns error message from libmodbus.

Arguments

None

Return Value character(len=:), allocatable

public function dm_modbus_flush(modbus) result(rc)

Flushes non-transmitted data.

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(inout) :: modbus

Modbus type.

Return Value integer

public function dm_modbus_get_real(registers, byte_order, error) result(value)

Returns real value from two registers of given byte order in argument value. The argument byte order must be one of the following:

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(inout) :: registers(2)

Registers to convert.

integer, intent(in) :: byte_order

Byte order.

integer, intent(out), optional :: error

Error code.

Return Value real

public function dm_modbus_get_real_abcd(registers) result(value)

Returns real value from two registers in ABCD byte order.

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(inout) :: registers(2)

Registers to convert.

Return Value real

public function dm_modbus_get_real_badc(registers) result(value)

Returns real value from two registers in BADC byte order.

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(inout) :: registers(2)

Registers to convert.

Return Value real

public function dm_modbus_get_real_cdab(registers) result(value)

Returns real value from two registers in CDAB byte order.

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(inout) :: registers(2)

Registers to convert.

Return Value real

public function dm_modbus_get_real_dcba(registers) result(value)

Returns real value from two registers in DCBA byte order.

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(inout) :: registers(2)

Registers to convert.

Return Value real

public function dm_modbus_get_serial_mode(modbus, mode) result(rc)

Gets the current Modbus RTU serial mode (RS-232 or RS-485).

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(inout) :: modbus

Modbus type.

integer, intent(out) :: mode

Modbus RTU mode (MODBUS_RTU_RS232, MODBUS_RTU_RS485).

Return Value integer

public function dm_modbus_get_slave(modbus, slave) result(rc)

Gets current slave number in the Modbus context.

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(inout) :: modbus

Modbus type.

integer, intent(out) :: slave

Device id.

Return Value integer

public function dm_modbus_mode(modbus) result(mode)

Returns Modbus mode (MODBUS_MODE_NONE, MODBUS_MODE_RTU or MODBUS_MODE_TCP).

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(inout) :: modbus

Modbus type.

Return Value integer

public function dm_modbus_read_registers(modbus, address, registers, n) result(rc)

Reads many registers from address. The size of argument registers determines the number of registers to read, unless optional argument n is passed. The function uses the Modbus function code 0x03 (read holding registers).

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(inout) :: modbus

Modbus type.

integer, intent(in) :: address

Address to read from.

integer(kind=u2), intent(inout) :: registers(:)

Register values (unsigned).

integer, intent(inout), optional :: n

Number of registers to read on input, number of registers read on output.

Return Value integer

public function dm_modbus_set_debug(modbus, debug) result(rc)

Sets debug flag of the Modbus context. Returns E_MODBUS on error.

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(inout) :: modbus

Modbus type.

logical, intent(in) :: debug

Enable debug mode.

Return Value integer

public function dm_modbus_set_serial_mode(modbus, mode) result(rc)

Sets the Modbus RTU serial mode to RS-232 or RS-485. This API function is only supported on Linux kernels 2.6.28 onwards.

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(inout) :: modbus

Modbus type.

integer, intent(in) :: mode

Modbus RTU mode (MODBUS_RTU_RS232, MODBUS_RTU_RS485).

Return Value integer

public function dm_modbus_set_slave(modbus, slave) result(rc)

Sets slave number in the Modbus context.

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(inout) :: modbus

Modbus type.

integer, intent(in) :: slave

Device id.

Return Value integer

public function dm_modbus_version(name) result(version)

Returns libmodbus version as allocatable string.

Arguments

Type IntentOptional Attributes Name
logical, intent(in), optional :: name

Add prefix libmodbus/.

Return Value character(len=:), allocatable

public function dm_modbus_write_register(modbus, address, register) result(rc)

Writes register to address. The function uses the Modbus function code 0x06 (preset single register).

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(inout) :: modbus

Modbus type.

integer, intent(in) :: address

Address to write to.

integer(kind=u2), intent(in) :: register

Register value (unsigned).

Return Value integer

public function dm_modbus_write_registers(modbus, address, registers, n) result(rc)

Writes many registers to address. The size of argument registers determines the number of registers to write, unless optional argument n is passed. The function uses the Modbus function code 0x10 (preset multiple registers).

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(inout) :: modbus

Modbus type.

integer, intent(in) :: address

Address to write to.

integer(kind=u2), intent(inout) :: registers(:)

Register values (unsigned).

integer, intent(inout), optional :: n

Number of registers to write on input, number of registers written on output.

Return Value integer


Subroutines

public subroutine dm_modbus_close(modbus)

Closes the Modbus connection.

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(inout) :: modbus

Modbus type.

public subroutine dm_modbus_destroy(modbus)

Destroys the Modbus context.

Arguments

Type IntentOptional Attributes Name
type(modbus_type), intent(inout) :: modbus

Modbus type.

public subroutine dm_modbus_set_real(value, registers, byte_order, error)

Sets real value to registers of given byte order. The argument byte order must be one of the following:

Read more…

Arguments

Type IntentOptional Attributes Name
real, intent(in) :: value

Real value to set.

integer(kind=u2), intent(out) :: registers(2)

Registers to write to.

integer, intent(in) :: byte_order

Byte order.

integer, intent(out), optional :: error

Error code.

public subroutine dm_modbus_set_real_abcd(value, registers)

Returns real value to registers in ABCD byte order.

Arguments

Type IntentOptional Attributes Name
real, intent(in) :: value

Real value to set.

integer(kind=u2), intent(out) :: registers(2)

Registers to write to.

public subroutine dm_modbus_set_real_badc(value, registers)

Returns real value to registers in BADC byte order.

Arguments

Type IntentOptional Attributes Name
real, intent(in) :: value

Real value to set.

integer(kind=u2), intent(out) :: registers(2)

Registers to write to.

public subroutine dm_modbus_set_real_cdab(value, registers)

Sets real value to registers in CDAB byte order.

Arguments

Type IntentOptional Attributes Name
real, intent(in) :: value

Real value to set.

integer(kind=u2), intent(out) :: registers(2)

Registers to write to.

public subroutine dm_modbus_set_real_dcba(value, registers)

Sets real value to registers in DCBA byte order.

Arguments

Type IntentOptional Attributes Name
real, intent(in) :: value

Real value to set.

integer(kind=u2), intent(out) :: registers(2)

Registers to write to.