Go Down

Topic: MODBUS Slaves with Arduino (Read 64734 times) previous topic - next topic

OZ_Willy

I have seen a few posts lately on MODBUS so I thought I might post what I use with arduino.
The library I use is located here:
http://code.google.com/p/arduino-modbus-slave/downloads/detail?name=MODBUS.zip&can=2&q=

I have multiple slaves running. I use the code posted below on ALL of them, all I change is the slave ID. I keep all the pins the same, that way when I upload this code onto ANY arduino, it works. You should not have to change ANYTHING ELSE!

I also have this running over Xbee's through a Digi Connectport X4, which converts it to TCP. I then use Mango M2M as my SCADA package. I can now get my Analog and digital data from anywhere in the world, or open and close my roller doors, anything. I can even write Analog values. All my logic is done in Mango. You could probably do a mesh with a Xbee as a coordinator on a PC, transmitting to all the MODBUS slaves,(leave all destination addresses as zero's and set the slave Xbees to routers), but have not tried it because I have an X4

I DO NOT think you need to use RS485 for this. Just connect a PC straight up to your freshly programmed arduino, and run some sort of MODBUS master or test software, using the register number as listed in the code. Remember, in the SCADA software do not use the whole address number, for instance, to access pin 2, you would be reading a COIL on Slave 1 at address 2, not address 10002. Some SCADA packages use ZERO offsets, so subtract 1, so the address for pin 2 would be 1.

Code: [Select]
#include <modbus.h>
#include <modbusDevice.h>
#include <modbusRegBank.h>
#include <modbusSlave.h>

/* PINS
Add more registers if needed
Digital input pins 2,3,4,5,6,7
Digital output pins 8,9,12,13
Analog output pins 10,11 (PWM)
Analog input pins 0,1,2,3,4,5
*/


modbusDevice regBank;
modbusSlave slave;

int AI0,AI1,AI2,AI3,AI4,AI5;


void setup()
{   
  regBank.setId(1); ///Set Slave ID

//Add Digital Input registers
  regBank.add(10002);
  regBank.add(10003);
  regBank.add(10004);
  regBank.add(10005);
  regBank.add(10006);
  regBank.add(10007);
// Add Digital Output registers
  regBank.add(8);
  regBank.add(9);
  regBank.add(12);
  regBank.add(13);
//Analog input registers
  regBank.add(30001);
  regBank.add(30002);
  regBank.add(30003);
  regBank.add(30004);
  regBank.add(30005);
  regBank.add(30006);
//Analog Output registers
  regBank.add(40010); 
  regBank.add(40011); 

  slave._device = &regBank; 
  slave.setBaud(9600);   
 
  pinMode(2,INPUT);
  pinMode(3,INPUT);
  pinMode(4,INPUT);
  pinMode(5,INPUT);
  pinMode(6,INPUT);
  pinMode(7,INPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  pinMode(12,OUTPUT);
  pinMode(13,OUTPUT);
   
}
void loop(){

  while(1){   
  //Digital Input
    byte DI2 = digitalRead(2);
    if (DI2 >= 1)regBank.set(10002,1);
    if (DI2 <= 0)regBank.set(10002,0);
    byte DI3 = digitalRead(3);
    if (DI3 >= 1)regBank.set(10003,1);
    if (DI3 <= 0)regBank.set(10003,0);
    byte DI4 = digitalRead(4);
    if (DI4 >= 1)regBank.set(10004,1);
    if (DI4 <= 0)regBank.set(10004,0);
    byte DI5 = digitalRead(5);
    if (DI5 >= 1)regBank.set(10005,1);
    if (DI5 <= 0)regBank.set(10005,0);
    byte DI6 = digitalRead(6);
    if (DI6 >= 1)regBank.set(10006,1);
    if (DI6 <= 0)regBank.set(10006,0);
    byte DI7 = digitalRead(7);
    if (DI7 >= 1)regBank.set(10007,1);
    if (DI7 <= 0)regBank.set(10007,0);
                               
  //Digital output
    int DO8 = regBank.get(8);
      if (DO8 <= 0 && digitalRead(8) == HIGH)digitalWrite(8,LOW);
      if (DO8 >= 1 && digitalRead(8) == LOW)digitalWrite(8,HIGH);
    int DO9 = regBank.get(9);
      if (DO9 <= 0 && digitalRead(9) == HIGH)digitalWrite(9,LOW);
      if (DO9 >= 1 && digitalRead(9) == LOW)digitalWrite(9,HIGH);
    int DO12 = regBank.get(12);
      if (DO12 <= 0 && digitalRead(12) == HIGH)digitalWrite(12,LOW);
      if (DO12 >= 1 && digitalRead(12) == LOW)digitalWrite(12,HIGH);
    int DO13 = regBank.get(13);
      if (DO13 <= 0 && digitalRead(13) == HIGH)digitalWrite(13,LOW);
      if (DO13 >= 1 && digitalRead(13) == LOW)digitalWrite(13,HIGH);
           
  //Analog input  ***READ Twice deliberately
    AI0 = analogRead(0);
    delay(10);
    AI0 = analogRead(0);
    regBank.set(30001, (word) AI0);
    delay(10);
   
    AI1 = analogRead(1);
    delay(10);
    AI1 = analogRead(1);
    regBank.set(30002, (word) AI1);
    delay(10);
   
    AI2 = analogRead(2);
    delay(10);
    AI2 = analogRead(2);
    regBank.set(30003, (word) AI2);
    delay(10);
   
    AI3 = analogRead(3);
    delay(10);
    AI3 = analogRead(3);
    regBank.set(30004, (word) AI3);
    delay(10);
   
    AI4 = analogRead(4);
    delay(10);
    AI4 = analogRead(4);
    regBank.set(30005, (word) AI4);
    delay(10);
   
    AI5 = analogRead(5);
    delay(10);
    AI5 = analogRead(5);
    regBank.set(30006, (word) AI5);
    delay(10);
       
  //Analog output
    word AO10 = regBank.get(40010);
    analogWrite(10,AO10);
    delay(10);
    word AO11 = regBank.get(40011);
    analogWrite(11,AO11);
    delay(10);
       
  slave.run(); 
  }
}



veseo

Hi,

I'm also a Modbus entusiast, also if is not suitable for M2M application due to its master/slave polling nature. I've build a similar protocol, called MaCaco that allow peer-to-peer event based communication that is then bridged via Modbus.

All these are included in an open source project called Souliss, and I was willing to include a SCADA interface for that, but right now I didn't started to time constrains. Would you like to help us?

Thanks,
Dario.
Souliss - Open-source Distributed Home Automation with Arduino and Android

http://www.souliss.net
Follow at @soulissteam

@veseotech

zdendule

Hi,
I read this topic about modbus, because I am interesting about it, but I am beginer. This library for modbus is comfortable and running very nice. Is there similar library for modbus via RS485 with parameter for pin switch for bus driver?

hugo007

I have a Siemens S7 -200 PLC that I would like to test using ModBus RTU but unfortunately I don't have a library for MicroWin.
Does anyone have this library?
Debian,Mint,Ubuntu
Arduino Mega 2560
Arduino Nano
Arduino Duemilanove
MAC OS Montain Lion
Raspberry PI Model B

OZ_Willy

Sorry for the belated reply.
The code and library above is for Modbus RTU over RS485. It is just the Digi Connectport that converts the RTU to TCP.
You should be able to use this code with ANY SCADA system or HARDWARE that supports STANDARD MODBUS RTU registers and addressing.
1. Get an Arduino, ANY arduino.
2. Load up the code as above.
3. Add a RS-485 shield, and add a button to pin 2.
4. Get a PC, and load up SCADA/HMI software that supports MODBUS RTU.
5. Connect a RS232 to 485 converter OR a USB to RS485 converter. Connect it to the Arduino shield.
6. In the SCADA software, add a data source as Com port(USB-485), Baud rate(9600), Slave Number(As per arduino code) and a "TAG" or "point" as  an "Input status",address(try 1 or 2)
7. Go live with the SCADA software and press the button. Hey presto! It should be read in the software.
8. Do the same with other arduino inputs, except for the data type.
MODBUS DATA types: (Yea, I know there are others, but these are all we need)
Input status = Read a arduino input (1 or 0)
Coil status = Write a arduino output (1 or 0)
Input register = Read adruino analog input (0 to 1023) Use 2 byte unsigned integer in TAG settings
Holding register = Write arduino analog output (0 to 255)  Use 2 byte unsigned integer in TAG settings

Remember, get rid of the RS-485 if you only have one slave!, it is used because 485 supports multidrop, this is where the slave ID's come in.

You can do SO MUCH with MODBUS and ARDUINO. I have soil moisture, voltage, lux, temperature, humidity values all coming in flawlessly.
I can open and close roller doors, lights on and off, set lights to a certain brightness......what next.....imagine.

As far as the Siemens PLC goes, you can't use arduino with it unless you use the arduino as a master, and I don't see the point.

H

PS If I have missed anything, I apologise

OZ_Willy

For anyone interested in an AWESOME SCADA package, I recommend MANGO M2M.
Google Mango M2M to get to the Mango webpage, where you will find details on installing and downloading.

Use this link to download http://mango.serotoninsoftware.com/downloads/mango-1.12.4.zip
because the links on the page direct you to Mango Automation, which is the commercial version, easily
the best value for money or those wishing a bit more. It uses DGLux, a state of the art graphical dashboard.

I use 1.12.4, as it is the latest version that I can get to work. Follow the install instructions to the LETTER
on the website. If 1.12.4 does not work, substitute the "4" in the link above with another version.

hugo007

#6
Mar 05, 2013, 12:45 am Last Edit: Mar 05, 2013, 12:51 am by HugoPT Reason: 1
thanks for your reply It help me clarifying my head.I know Mango a couple of years. When I had used Mango I also develop a small install embedded solution using a WRAP ALiX board with all Scada Software installed on it.It works pretty well
This way I could have a small board that doesn't look a pc, and its very small :smiley-mr-green:
It runs at 700MHZ but it does the job.I'm using Linux Debian  in a CF card.
See more details here about my tutorial here:
http://devforum.i9box.net/index.php?topic=3.0
Debian,Mint,Ubuntu
Arduino Mega 2560
Arduino Nano
Arduino Duemilanove
MAC OS Montain Lion
Raspberry PI Model B

zdendule

Hallo,
ok, I know, that is modbus library for RS485, but for transmitting I need bus driver, example SN75176, and it need plugged pins for switching TR/RX. One of ways is conect to converter RS485/TCP IP, but for more slave devices I need twowire bus with busdriver to 485. Past it I can plug this group devices to one converter to TCP IP. Isnt it?  Zd.

platoxii

Hello ,OZ_Willy

Your code after compile work perfectly ,by the way the SCADA I used is modscan32

But I face some trouble ,I want to communicate via RS485  not via USB port  so I following this picture  to connect max485 IC
and the use 485 to 232 convert to PC.

(http://dereenigne.org/wp-content/uploads/modbus.png)

But this time  modscan32 connect  fail . Could you tell me how to fix it?  

Thank you all

EVP

I have got Modbus working with a arduino mega as a master using the modbus master lib. I have changed the lib so it can address more than one slave and am using it to communicate with two flow meters. This is done using RS485. The fact that is is RS485 and not RS232 seems to make no difference as i just use a converter on the cable i haven't need to change any code at all. Well not quite true i did have problems at first with coms being fine to one or the other but not both i solved this with some "delay(11);" statements ( 11 was arrived at by trial and error) in between slave change and also making sure i emptied the transmit and receive buffers seemed to help. All in all it wasn't to difficult to get working.

platoxii

#10
Feb 07, 2014, 04:27 am Last Edit: Feb 07, 2014, 04:29 am by platoxii Reason: 1
Thank for your reply EVP

My goal is simple ,I want to communicate to arduino via RS485 not USB port  and arduino as a slave my PC as a master

I use modscan32 as my SCADA .OZ_Willy's code work perfectly via USB , I can read write arduino in modscan32 .
http://i.imgur.com/KYaXI07.jpg?1
http://i.imgur.com/gRMd3Hd.jpg?1

But when I want to connect arduino via RS485  modscan32 told me time out(no response) .
http://i.imgur.com/EaTAUyn.jpg?1

I follow this picture to make a max485 wiring .
http://dereenigne.org/wp-content/uploads/modbus.png
http://i.imgur.com/NffJGNY.jpg?1

Could anyone give me some advise.Thanks so much.


suby

Quote
I follow this picture to make a max485 wiring .

I'm afraid that the problem isn't the wiring. It's just the MAX485 transceiver control:
- when the modbus library sends an answer, it should put the MAX485 in transmit mode as long as the message is being send;
- the modbus library doesn't wait for the transmission end. It just waits until the outcoming message is moved to the HardwareSerial output stream.
Try the Modbus port shown here:
http://forum.arduino.cc/index.php?topic=213432.msg1579599#msg1579599

BR

Tomsky_Pilot

Dear friends, who can help?

I would like use arduino nano with SCADA Movicon. I connected arduino with Movicon, please have a look attached file with screen shots.  But buton on pin 2 and var0002 doesn't work.

BR

suby

Quote
I would like use arduino nano with SCADA Movicon. I connected arduino with Movicon, please have a look attached file with screen shots.  But buton on pin 2 and var0002 doesn't work.

These buttons use to work with Modbus Function 5. Buttons use to write to a coil or boolean variable.
You should make sure that your Modbus Library implements this function 5. In other topic, I posted my own Modbus library that implements it. It has been successufully tested with a Modbus Master simulator.

shahin

hi, I am a beginner and sorry if my question looks stupid!
Where can i find the description of functions in the "modbus.h" library or other developed libraries?
for example i cannot understand this line of code:  "modbusDevice regBank;"
thanks a lot

Go Up