next up previous contents index
Next: EIB-Bus Up: Bus systems Previous: matplc   Contents   Index


Modbus using rllib

You can also connect to Modbus using rllib. The data will be stored in a shared memory. Many applications can access the shared memory simultaniously. E.g. Visualization, SoftPLC, technological model ... Using rllib you can read/write many signals in 1 telegram. This seems to be more effective than reading/writing individual signals. Within rllib there is a template application for Modbus that can be easily extended to read/write the signals you are interested in. To be precise only the read signals must be defined. Only add modbusCycle() in the main function. Signals can be written using a telegram to the mailbox. All you have to define is a Modbus telegram as defined in http://www.eecs.umich.edu/~modbus/documents/PI_MBUS_300.pdf . The Telegram written to the mailbox is the same as Modbus RTU in the above documentation excluding the checksum. The visualization is quite similar to the previous example using matplc. The template program follows.

Figure 9.11: Modus daemon template using rllib 1/3
//
// Modbus daemon template                                 (C) Rainer Lehrig 2003
//
//
// Attention: this program must be run as super user
//

#include <stdio.h>
#include <stdlib.h>
#include "rlmodbus.h"
#include "rlsharedmemory.h"
#include "rlmailbox.h"
#include "rlthread.h"
#include "rlcutil.h"

#define MODBUS_IDLETIME (4*1000)/96
#define SERIAL_DEVICE   "/dev/cua0"                                   // todo: specify name of serial device
rlModbus       modbus(128+1,rlModbus::MODBUS_RTU);
rlSerial       serial;
rlSharedMemory shm("/srv/automation/shm/modbus.shm",128*sizeof(int)); // todo: specify name of shm and size
rlMailbox      mbx("/srv/automation/mbx/modbus.mbx");                 // todo: specify name of mbx
rlThread       thread;
rlThread       watchdog;

// watchdog
static char *av0 = "";
static int watchcnt1 = 0;
void *watchdogthread(void *arg)
{
  int cnt1 = -1;

  while(1)
  {
    rlsleep(5000);
    if(cnt1 == watchcnt1) break;
    cnt1 = watchcnt1;
  }
  serial.closeDevice();
  rlsleep(100);
  rlexec(av0);
  exit(0); // pcontrol may start me again if rlexec fails
  return arg;
}

Figure 9.12: Modus daemon template using rllib 2/3
// read mailbox and write to modbus
void *reader(void *arg)
{
  int ret,slave,function,buflen;
  unsigned char buf[128+1];

  mbx.clear(); // clear old messages
  while((buflen = mbx.read(buf,sizeof(buf))) > 0)
  {
    slave        = buf[0];
    function     = buf[1];
    thread.lock();
    rlsleep(MODBUS_IDLETIME);
    ret = modbus.write( slave, function, &buf[2], buflen-2);
    ret = modbus.response( &slave, &function, buf);
    rlsleep(MODBUS_IDLETIME);
    thread.unlock();
  }
  return arg;
}

// read cycle on modbus
int modbusCycle(int offset, int slave, int function, int start_adr, int num_register)
{
  unsigned char data[128+1];
  int ret;

  watchcnt1++;
  if(watchcnt1 > 10000) watchcnt1 = 0;
  thread.lock();
  rlsleep(MODBUS_IDLETIME);
  ret = modbus.request(slave, function, start_adr, num_register);
  ret = modbus.response( &slave, &function, data);
  thread.unlock();
  //printf("slave=%d function=%d ret=%d :",slave,function,ret);
  //for(int i=0; i<ret; i++) printf(" %d",(int) data[i]);
  //printf("\n");
  if(ret > 0) shm.write(offset,data,ret);
  return ret;
}

Figure 9.13: Modus daemon template using rllib 3/3
int main(int ac, char **av)
{
  int offset,ret,first;

  if(ac > 0) av0 = av[0];
  first = 1;
  while(serial.openDevice(SERIAL_DEVICE,B9600) < 0) // todo: specify serial parameters
  {
    if(first==1) printf("could not open serial device %s\n",SERIAL_DEVICE);
    first = 0;
    rlsleep(1000);
  }
  printf("%s starting\n",av0);
  modbus.registerSerial(&serial);
  thread.create(reader,NULL);
  watchdog.create(watchdogthread,NULL);

  while(1)
  {
    offset = 0;
    //    modbusCycle(offset, slave, function                 , start_adr, num_register);
    ret = modbusCycle(offset, 1    , rlModbus::ReadInputStatus, 0        , 10          ); // todo: add your cycles here
    if(ret>0) offset += ret; else continue;
  }

  // we will never come here
  serial.closeDevice();
  return 0;
}


next up previous contents index
Next: EIB-Bus Up: Bus systems Previous: matplc   Contents   Index
Rainer Lehrig 2004-02-17