Table of Contents

Linux modbus support

This page is part of my Home Automation project.

Modbus

Modbus is a serial communication interface used in industrial automation. Modbus uses either EIA-485 (RS-485) or Ethernet as physical layer. In this document we consentrate in EIA-485.

An open source project libmodbus exists to provide modbus support under GPL license. The library supports Linux, Mac OSX, FreeBSD, QNX and Win32.

Hardware

There exists several inexpensive RS232-RS485 and USB-RS485 adapters at the market. eBox2300 has physical serial port, thus I'm using a RS232-RS485 adapter sold at DealExtreme for 4€ ($5).


RS232-to-RS485 converter

Software

Install libmodbus

At the time of writing this document, libmodbus is not included in Debian packages, thus it need to be built from sources.

Download latest source package from libmodbus download site. Following instructions apply for version 3.0.1. Debian package build-essential is required for building.

$ wget http://github.com/downloads/stephane/libmodbus/libmodbus-3.0.1.tar.gz
$ tar xvzf libmodbus-3.0.1.tar.gz 
$ cd libmodbus-3.0.1/
$ ./configure
$ make
$ make install

Test software

Here is a simple test software that reads given number of register values from modbus slave and prints them to stdout. This application is made only to study libmodbus and test modbus interface.

Build the code with the command below. In Debian, at least following packages are needed: build-essential, pkg-config.

$ cc `pkg-config --cflags --libs libmodbus` mbtest.c -o mbtest

Source code of mbtest.c:

#include <stdio.h>
#include <modbus.h>

#define MB_BITRATE 19200
#define MB_DATABITS 8
#define MB_STOPBITS 1
#define MB_PARITY 'N'
#define MB_SLAVE_ADDRESS 1

#define MB_REG_BASE 6
#define MB_REG_COUNT 4

int main ( int argc, char* argv[] )
{
  modbus_t *ctx;
  uint16_t tab_reg[MB_REG_BASE+MB_REG_COUNT];
  int n, i;
  int errno = 0;

  if ( argc != 2 )
    {
      fprintf(stderr, "Syntax: %s serial_device\n", argv[0]);
      return -1;
    }

  ctx = modbus_new_rtu(argv[1],
		       MB_BITRATE,
		       MB_PARITY,
		       MB_DATABITS,
		       MB_STOPBITS);
  if (ctx == NULL) {
    fprintf(stderr, 
	    "Unable to create the libmodbus context on serial port %s\n",
	    argv[1]);
    return -1;
  }

  if ( modbus_set_slave(ctx, MB_SLAVE_ADDRESS) )
    {
      fprintf(stderr,
	      "Failed to set modbus slave address\n");
      errno = -1;
      goto fail;
    }  

  
  if ( modbus_connect(ctx))
    {
      fprintf(stderr,
	      "Unable to connect to modbus server");
      errno = -1;
      goto fail;
    }

  n = modbus_read_registers(ctx, 
			    MB_REG_BASE, 
			    MB_REG_COUNT, 
			    tab_reg+MB_REG_BASE);
  if ( n <= 0 )
    {
      fprintf(stderr,
	      "Unable to read modbus registers\n");
      errno = -1;
      goto fail;
    }
  
  for ( i=MB_REG_BASE; i<MB_REG_BASE+n; i++ )
    {
      printf ( "[%d]: %d\n", i, tab_reg[i]);
    }

 fail:
  modbus_close(ctx);
  modbus_free(ctx);

  return errno;
}