Some questions about Modbus from a newbie

Hello there, I am interested in making my Arduino communicate with a PC to deliver data to a SCADA software. I did a little research and the most suitable solution seems to be to use Simple Modbus Slave library for Arduino, since Modbus can be used in SCADAs, which act like a master then. To this point everything is ok, but further some questions came to my mind:

  1. Is it really needed to use RS-485 for Modbus and why can't I do it over USB (since TX and RX are used over USB)?

  2. Also, here: http://i.imgur.com/NffJGNY.jpg?1 I saw lots of converters used, while can't it be simple RS-485 to USB?

  3. Moreover in the examples both of master and slave there are some values used, like here:

analogWrite(LED, holdingRegs[PWM_VAL]>>2);

but there is nowere written whar PWM_VAL holds or did I miss something?

I would be grateful if somebody could make this things clear for me. :slight_smile:

RS485 is commonly used in industrial networks due to it being fairly immune to noise along with its ability to cover distances of > 1000 feet ,neither attribute shared with USB. Ultimately, modbus over tcp is the direction most taken these days and ultimately the physical transport layer really isn't that important to understanding what modbus is all about.

Does the posted code fragment have any connection to modbus? Or is this just a general programming question? Really no way to answer the question. Posting code fragments usually generate more questions than they answer.

Yes, you can use the USB to act as your communications path using the Modbus protocol.
This is something I have done using the Simple Modbus Slave library.
I now use TCP rather than RTU mode for a number of reasons, one being that with TCP you can use the normal Modbus packet size of 123 data words.
The Arduino hardware serial buffer limits this size while using RTU mode, which is anything using async serial.

As avr_fred says, RS-485 is what is typically used in industrial environments, for its ablity to be robust in noisy EMI environments.

Your code question about PWM_VAL relates to the index number of a holding register in the Arduino.
You shall see it in an enum{...} statement near the top of your code.
This is a holding register that takes data into the Arduino from another device.
I recall the code was documneted and explained.
What SCADA software are you looking to use?


Paul

Thanks Paul, this clarifies a lot.

I have succeeded with simulating an Arduino circuit in Proteus with an old modbus library written by Juan Pablo Zometa. Since it is not supported with Arduino IDE over 1.X, I thought I'd move to Simple Modbus library, but then some problems occured.

The circuit for the tutorial is as attached.

It works pretty well with tutorial code based on old modbus library, but when I try to port it to Simple Modbus I get "Illegal function" error while trying to write from ScadaBr to Arduino slave (it works with an old code, included as an attachment). Below my code:

#include <SimpleModbusSlave.h>

/* slave registers example */
enum {        
  MB_REG0,
  MB_REG1,
  MB_REG2,
  MB_REG3,
  MB_REG4,
  MB_REG5,
  MB_REG6,
  MB_REG7,
  MB_REG8,
  MB_REG9,
  MB_REG10,
  MB_REG11,
  MB_REG12,
  MB_REG13,
  MB_REGS
};

unsigned int holdingRegs[MB_REGS]; /* this is the slave's modbus data map */

void setup() 
{
  modbus_configure(&Serial, 9600, SERIAL_8N1, 1, 2, MB_REGS, holdingRegs);
  pinMode(13,OUTPUT);
  pinMode(12,OUTPUT);
  pinMode(11,OUTPUT);
  pinMode(10,OUTPUT);

  pinMode(9,INPUT);
  pinMode(8,INPUT);
  pinMode(7,INPUT);
  pinMode(6,INPUT);
}


void loop() 
{
  /* This is all for the Modbus slave */
  modbus_update();

  holdingRegs[MB_REG0]=analogRead(0);
  holdingRegs[MB_REG1]=analogRead(1);
  holdingRegs[MB_REG2]=analogRead(2);
  holdingRegs[MB_REG3]=analogRead(3);
  holdingRegs[MB_REG4]=analogRead(4);
  holdingRegs[MB_REG5]=analogRead(5);
  holdingRegs[MB_REG6]=digitalRead(6);
  holdingRegs[MB_REG7]=digitalRead(7);
  holdingRegs[MB_REG8]=digitalRead(8);
  holdingRegs[MB_REG9]=digitalRead(9);

  switch ( holdingRegs[MB_REG10]) {
  case 1:

    digitalWrite(10,HIGH);
    break;
  case 0:
    digitalWrite(10,LOW);
    break;
  default: 
    digitalWrite(10,LOW);
  }

  switch ( holdingRegs[MB_REG11]) {
  case 1:

    digitalWrite(11,HIGH);
    break;
  case 0:
    digitalWrite(11,LOW);
    break;
  default: 
    digitalWrite(11,LOW);
  }

  switch ( holdingRegs[MB_REG12]) {
  case 1:

    digitalWrite(12,HIGH);
    break;
  case 0:
    digitalWrite(12,LOW);
    break;
  default: 
    digitalWrite(12,LOW);
  }

  switch ( holdingRegs[MB_REG13]) {
  case 1:

    digitalWrite(13,HIGH);
    break;
  case 0:
    digitalWrite(13,LOW);
    break;
  default: 
    digitalWrite(13,LOW);
  }
}

modbus.txt (19.6 KB)