++ed by:
1 non-PAUSE user
Author image Julio Fraire
and 1 contributors


Device::Modbus - Perl distribution to implement Modbus communications


A Modbus RTU client:

 my $client = Device::Modbus::RTU::Client->new(
     port     => '/dev/ttyUSB0',
     baudrate => 19200,
     parity   => 'none',
 my $req = $client->read_holding_registers(
     unit     => 4,
     address  => 0,
     quantity => 2,

 my $resp = $client->receive_response;

A Modbus TCP client:

 my $client = Device::Modbus::TCP::Client->new(
     host => '',

 my $req = $client->read_holding_registers(
     unit     => 3,
     address  => 2,
     quantity => 1

 $client->send_request($req) || die "Send error: $!";
 my $response = $client->receive_response;

A Modbus server:

 use Device::Modbus::TCP::Server;
     package My::Unit;
     our @ISA = ('Device::Modbus::Unit');
     sub init_unit {
         my $unit = shift;
         #                Zone            addr qty   method
         #           -------------------  ---- ---  ---------
         $unit->get('holding_registers',    2,  1,  'get_addr_2');
     sub get_addr_2 {
         my ($unit, $server, $req, $addr, $qty) = @_;
         $server->log(4,"Executed server routine for address 2");
         return 6;

 my $server = Device::Modbus::TCP::Server->new(
     log_level => 4,
     log_file  => 'logfile'

 my $unit = My::Unit->new(id => 3);



Modbus is an industrial communication protocol. It is implemented by many industrial devices such as servo motors, temperature controllers, force monitors, and Programmable Logic Controllers. Device::Modbus is a set of Perl modules that should allow for writing both Modbus clients and servers.

The Modbus data model

With Modbus, a client sends requests to a server device, which returns responses. We'll use the term unit when referring a device capable of processing Modbus requests. Most of the time, a unit is one physical device, but a physical device may contain several units. For example, a gateway between different communication protocols may provide several units, and each of these units could represent a physical device down the line. In practice, a unit may be defined as an entity which provides an addressable space.

Data within a unit is accessible through the following addressable tables:

  • Discrete inputs

  • Discrete outputs (or coils)

  • Input registers

  • Holding registers

Note that discrete outputs are called coils as well. This name makes reference to the automation origin of the protocol, where a coil is the actuator of an electro-mechanical relay.

Tables may even overlay each other. For example, it is not uncommon to address a particular discrete input as a bit of a register address: bit 34 may be the 3rd bit of the 3rd input register. In this distribution, addressable tables are called zones.

To summarize, the Modbus data model breaks a unit into zones in which data is addressable.

Now, Modbus uses Protocol Data Units. The PDUs are the basic blocks defined by the protocol; they are the binary messages that flow between clients and servers. PDUs encapsulate a request from a client or a response from a server. They are independent from the underlying communication layers.

PDUs are further encapsulated into Application Data Units, which add a header and (in the RTU case) a footer with further information as needed for the communication layer. Device::Modbus handles the RTU and the TCP variants of the protocol through Device::Modbus::RTU and Device::Modbus::TCP.

Finally, clients produce requests which are sent to servers, and they receive requests in return. This distribution provides the tools to build both servers and clients.

Request generalities

Let's talk now about requests. Requests have basically four parameters. The first is implicit in the request code itself, sice each kind of request is directed at a particular zone. The other parameters are the starting address, the number of registers or bits to work on, and, in the case of requests that send information, the data.

For example, we have Read Coil, Write Single Coil and Write Multiple Coils, which refer to the Discrete Outputs zone. As for addresses, a read request for multiple registers that starts at address 1 and demands 5 registers will fetch regiesters 1, 2, 3, 4 and 5. This is true in the vast majority of cases, but see Device::Modbus::Unit for a more general interpretation.


The main protocol is described in the following documents:


The RTU and TCP variants are implemented in two separate distributions, Device::Modbus::RTU and Device::Modbus::TCP. This way you can install only what is needed for your application.

Documentation for writing clients

A client must be able to:

1. Open a connection to a server
2. Create request objects
3. Send requests to a server
4. Receive responses to its requests
5. Close the connection to the server

The first point, which depends on the communication layer, is described in Device::Modbus::RTU::Client and Device::Modbus::TCP::Client. Items 2, 3, 4 and 5 are common to all clients, and therefore, they are documented in Device::Modbus::Client.

Writing servers

Servers are more complex. They must:

1. Define one or more units, their addressable zones, and implement their functionalities
2. Add those units to a Modbus server
3. Define the interface where the server will listen for connections
4. Start the server

Points 1, 2, and 4 are independent of the communication layer and are documented in Device::Modbus::Server. The documentation for point 3 is in either Device::Modbus::RTU::Server or Device::Modbus::TCP::Server.


You will find some articles and examples in my blog, http://7mavida.com/tag/Device::Modbus.

Other distributions

These are other implementations of Modbus in Perl which may be well suited for your application: Protocol::Modbus, MBclient, mbserverd. The first two implement Modbus clients; the third, implements servers.


You can find the repository of this distribution in GitHub.


Julio Fraire, <julio.fraire@gmail.com>


Copyright (C) 2015 by Julio Fraire This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.14.2 or, at your option, any later version of Perl 5 you may have available.