Arduino Forum

Using Arduino => Networking, Protocols, and Devices => Topic started by: JUGmobile on Jul 07, 2013, 09:36 pm

Title: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Jul 07, 2013, 09:36 pm
Hello guys!

I'm working on an arduino project that require bulletproof communication between few arduinos (up to 30 or more, up to 100m) in disruptive environment (like near frequency inverter). I have one master device, that is communicating with few slaves. The master can send information-data, to the slaves, or read info-data from them. In project each slave will have few pushbuttons and an display (7-segment or graphic display). When the pushbutton is pressed on slave, the information of that pushbutton has to be transmited to the master. Also master device can send information to the slaves, so slaves can change information on display. Display will show only numbers and maybe few signs. That's about it.

My main goals are:


Real time in my case means up to 1sec to address all slaves and get response from them.

For the communication standard I choosed RS485, which is the best option for my project, I suppose, and have few advantages over CAN, SPI, Ethernet, I2C. On top of that I need a protocol for communication. There is a lot of libraries on the web for arduino that implement RS485 communication into arduino. I'm a little afraid, that these libraries aren't really bulletproof + many of them uses delay function that is not helpful at all for my main code. After some time investigating communication between arduinos I decided to stick with the ModBus protocol. Since ModBus is a little complicated for me and my knowledge I'm asking here for help.

I'm still at the begining phase of programming this. I have found a ModBus library for arduino, called SimpleModbus, that contains master and slave example code. The whole library project can be found here: SimpleModbus (https://code.google.com/p/simple-modbus/).

For my master device I choose Arduino Due (http://arduino.cc/en/Main/ArduinoBoardDue), and for the slaves Arduino Leonardo (http://arduino.cc/en/Main/ArduinoBoardLeonardo). For RS485 transceiver I choose SN65HVD75D from Texas Instruments, which is working at 3.3V, just like DUE and Leonardo [datasheet (http://www.farnell.com/datasheets/1637354.pdf)].

(http://shrani.si/f/21/jz/46Wh2r6c/dsc02152.jpg)

Current configuration


For the beginning I'm trying to establish communication only between master and one slave device. I haven't connect all the pushbuttons and displays, because firstly I want succesfully establish communication betwen arduinos using ModBus protocol. The hardware is the easiest part of design. Just arduino board, few ICs, breadboard and some wires. The hardware part is working flawlessly (for now  :P ).

So I have connected everything and now I'm stuck with programming. I will go trough most parts of the code and will try to explain what I do understand and what I do not. All the code and libraries are available here:  SimpleModbus (https://code.google.com/p/simple-modbus/)

MASTER: SimpleModbusMasterExample

Code: [Select]

#include <SimpleModbusMaster.h>
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate

// If the packets internal retry register matches
// the set retry count then communication is stopped
// on that packet. To re-enable the packet you must
// set the "connection" variable to true.
#define retry_count 5

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

Few lines of code that defines some parameters. Timeout is time in ms that defines how much is max. time for master to wait, till slave responds. If slave wouldn't respond, master would call next slave.
Polling defines how fast will master call slaves (but I don't know what exactly nr. 200 means).
Retry_count is counter, that defines max. nr. of unsuccessful tryes of calling one slave. If slave don't respond 5 times in row, the master will stop calling him.
TxEnablePin is just a digital output for /RE-DE pins on RS485 transmitter that defines direction (transmit or receive data).

Code: [Select]

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
 PACKET1,
 PACKET2,
 // leave this last entry
 TOTAL_NO_OF_PACKETS
};

I'm not 100% sure what this is. I understand part that I can freely add or remove packets. I think this packets contains informations-data of what we want to send to the slave or what we want to read from the slave? Each packet can contain up to 256 bytes of information but serial buffer can contain only 128 bytes of information so this is limited to 128 bytes. But I'm not sure how to handle this packets.

Code: [Select]

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Create a packetPointer to access each packet
// individually. This is not required you can access
// the array explicitly. E.g. packets[PACKET1].id = 2;
// This does become tedious though...
packetPointer packet1 = &packets[PACKET1];
packetPointer packet2 = &packets[PACKET2];

// The data from the PLC will be stored in the regs array
unsigned int regs[10];

Packet pack... is an array of packets. With line packets[1] = 0; I probably write a zero value to the PACKET2. I'm not sure if I'm correct?
packetPointer is just an pointer that points to the corresponding packet.
regs[10] array is, well I don't know what.

Code: [Select]

void setup()
{
 // The modbus packet constructor function will initialize
 // the individual packet with the assigned parameters. You can always do this
 // explicitly by using struct pointers. The first parameter is the address of the
 // packet in question. It is effectively the "this" parameter in Java that points to
 // the address of the passed object. It has the following form:
 // modbus_construct(packet, id, function, address, number of registers, register array)
 
 // read 2 registers starting at address 0  
 modbus_construct(packet1, 2, READ_HOLDING_REGISTERS, 0, 2, regs);
 
 // write the 10 registers to the PLC starting at address 2  
 modbus_construct(packet2, 2, PRESET_MULTIPLE_REGISTERS, 2, 10, regs);
 
 // P.S. the register array entries above can be different arrays
 
 // Initialize communication settings etc...
 modbus_configure(baud, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
}

Not sure what this is, but if I'm correct, modbus_construct create an map that contains all the informations that will be send to slave, like slave ID, function (receive or transmit data to the slave), what data (packet) to send... I would appreciate if someone could explain this line.
modbus_configure configures modbus setting. Nothing complicated

Code: [Select]

void loop()
{
 modbus_update();
 
 // update the array with the counter data
 regs[2] = packet1->requests;
 regs[3] = packet1->successful_requests;
 regs[4] = packet1->failed_requests;
 regs[5] = packet1->exception_errors;
 regs[6] = packet2->requests;
 regs[7] = packet2->successful_requests;
 regs[8] = packet2->failed_requests;
 regs[9] = packet2->exception_errors;
}

The part that I don't understand at all.
What is modbus_update? What are next lines of code?

I couldn't fit whole post in one post, so the post continue in next post.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JUGmobile on Jul 07, 2013, 09:36 pm
SLAVE: SimpleModbusSlaveExample

Code: [Select]

#include <SimpleModbusSlave.h>

#define  ledPin  13 // onboard led

Nothing special.

Code: [Select]

// Using the enum instruction allows for an easy method for adding and
// removing registers. Doing it this way saves you #defining the size
// of your slaves register array each time you want to add more registers
// and at a glimpse informs you of your slaves register layout.

//////////////// registers of your slave ///////////////////
enum
{    
 // just add or remove registers and your good to go...
 // The first register starts at address 0
 ADC0,    
 ADC1,        
 ADC2,
 ADC3,
 ADC4,
 ADC5,  
 LED_STATE,
 TOTAL_ERRORS,
 // leave this one
 HOLDING_REGS_SIZE
 // total number of registers for function 3 and 16 share the same register array
};

Very similar part of the code like packets in the master code. I do not understand, why nr. of "registers" isn't same as nr. of "packets". Again this "registers" probably contains informations about slave device, informations that we want to send to the master device.

Code: [Select]

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array

void setup()
{
 /* parameters(long baudrate,
               unsigned char ID,
               unsigned char transmit enable pin,
               unsigned int holding registers size,
               unsigned int* holding register array)
 */
 
 modbus_configure(9600, 1, 2, HOLDING_REGS_SIZE, holdingRegs);    
 
 pinMode(ledPin, OUTPUT);
}

holdingRegs is an array of all "registers". Not sure what to do with this.

Code: [Select]

void loop()
{
 // modbus_update() is the only method used in loop(). It returns the total error
 // count since the slave started. You don't have to use it but it's useful
 // for fault finding by the modbus master.
 
 holdingRegs[TOTAL_ERRORS] = modbus_update();
 
 for (byte i = 0; i < 6; i++)
 {
   holdingRegs[i] = analogRead(i);
   delayMicroseconds(500);    
 }
 
 // read the LED_STATE register value and set the onboard LED
 // function 16 and one whole register is used 0000h == OFF
 // and anything except zero is ON
 digitalWrite(ledPin, holdingRegs[LED_STATE]);
}

Here we write analog values from analog inputs to "registers" ADC0-ADC5?
Here we have again modbus_update. I think this is command to send respond to the master or?


Final words and questions:
I would love to here some answeres, explanations from guys who knows Modbus well. If someone is successfully established modbus connection between arduinos please respond here in this thread. If someone can help me with tip on how to write sketch, please post your solution down in reply.

All I want to do for now is successfully connect 2 arduinos with modbus protocol and send some data from one to another.

This is a long post, so I hope this thread wont die soon. I hope this thread would be in help ti other programmers too. I have searched all the arduino forum and haven't found my answeres so I created a new topic.

Some usefull links for newbies:
Modbus protocol explained (http://www.simplymodbus.ca/faq.htm)
SimpleModbus library (https://code.google.com/p/simple-modbus/)

Thank you for your time!
Jakob
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JuanB on Jul 08, 2013, 09:39 am
Hi Jakob,

The library is written following a state machine principal. There are 3 states running in the back ground (not at the same time obviously). Calling modbus_update() checks the 3 states and thus calling this function frequently in your code will result in a quicker turnaround.

To communicate with a slave you will need to establish the id, the function you want to use (reading or writing, function 3 or 16), the starting address you want to read from and the amount of registers you want to read.

The packets you create with the enum instructions are just the index number you will use to explicitly refer to that specific packet. The TOTAL_NUMBER_OF_PACKETS is the number amount for the array of packets namely:
Code: [Select]
Packet packets[TOTAL_NO_OF_PACKETS];

This is effectively the array of packets that will be processed sequentially.

Obviously referring to a single packet you will have to use dot notation or pointer notation i.e.
Code: [Select]
// Create a packetPointer to access each packet
// individually. This is not required you can access
// the array explicitly. E.g. packets[PACKET1].id = 2;
// This does become tedious though...
packetPointer packet1 = &packets[PACKET1];


The regs array is any named unsigned int array. This is the array that will contain the slaves response information you requested (when using function 3) or it could be the array of data you would want to write to the slave. These arrays can be different arrays when assigning them to a packet. I.e. you could use 20 different arrays on 20 different packets.

modbus_constuct() is a function that does the assigning of packet information for you so you don't have to use pointer notation when putting together a packet.

P.s. The master and slave examples in the library folder were not design to communicate with each other. The SimpleModbusMaster example I used to communicate with an LSIS GM7 plc and the SimpleModbusSlave example was the slave to the GM7 plc and various other testing software.

Some more info I extracted from an email I sent to a fellow arduinist:

The library works on a state machine principal. The state machine is updated every call to modbus_update(). I.e. frequent calls in a large program is better. The SM has 3 states 2 of which is timing related. One is the timeout delay which allows the slave to respond within a certain amount of time and the other one is the turn around delay which is basically the polling rate of each packet. The timeout delay needs to be as long as the slowest anticipated response of a slave. As the amount of slaves increase the turn around delay can be decreased since more slaves equal more latency in response. The turn around delay is what I call "a breather delay". For example, if you have one slave and you poll it it takes 100ms to respond, as soon as your master detects a successful response it will poll the slave again but the slave has not yet returned to its ""listening state" which results in a non response which in turn will result in a timeout error. In this instance I would set the timeout to 300-500ms and the polling delay to 100ms. In general modbus is not a fast protocol and few commercial slaves respond so quickly. I have found that 500-1000ms timeout works the best and depending on the distance and amount of slaves a polling delay of 100-200ms.

Let me know if you need any other help.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: joerju on Jul 10, 2013, 06:50 pm
I am currently trying to achieve communication with the SimpleModbus library as well. Were you successful?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JUGmobile on Jul 10, 2013, 07:21 pm
Hi joerju! Well I'm still trying. I need more time for this to figure out the process.

Thank you very much JuanB for your answer. I will ask more questions soon :) but firstly I want to try it myself.

Joerju, post your progress here pls.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JuanB on Jul 16, 2013, 07:01 am
Updated the libraries so parity and byte frame size can be selected to adhere more to wards the modbus standard.

There are also new example codes that will allow communication between an arduino master and arduino slave. Using a potentiometer on the master one can vary an LED's brightness on the slave and also vice versa.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JUGmobile on Jul 17, 2013, 04:22 pm

Updated the libraries so parity and byte frame size can be selected to adhere more to wards the modbus standard.

There are also new example codes that will allow communication between an arduino master and arduino slave. Using a potentiometer on the master one can vary an LED's brightness on the slave and also vice versa.


Superb! With this examples everything become so clear. It is actually simpler to communicate over this modbus protocol than I thought (thanks to you and your libraray). But I still haven't establish communication between my DUE and Leonardo. I had to changed my hardware part a little since I figured out that Leonardo is working on 5V logic not 3.3V (don't know why I thought Leonardo is on 3.3V logic). So now hardware part is working, and one more thing I had to change, I hope I did it correct:

Since Arduino IDE 1.5.2 (which is neccessary for DUE) do not support different parity and stop bits options, I had to make a little changes in libraries. So this is what I changed so far:
Master libraries SimpleModbusMaster.cpp
In modbus_configure I have deleted byteFormat, from this:

Code: [Select]
void modbus_configure(long baud,
unsigned char byteFormat,
unsigned int _timeout,
unsigned int _polling,
unsigned char _retry_count,
unsigned char _TxEnablePin,
Packet* _packets,
unsigned int _total_no_of_packets)
{
Serial.begin(baud, byteFormat);

// Modbus states that a baud rate higher than 19200 must use a fixed 750 us
        ...
        ..
        .
}


to this:

Code: [Select]
void modbus_configure(long baud,

unsigned int _timeout,
unsigned int _polling,
unsigned char _retry_count,
unsigned char _TxEnablePin,
Packet* _packets,
unsigned int _total_no_of_packets)
{
Serial.begin(baud);

// Modbus states that a baud rate higher than 19200 must use a fixed 750 us
        ...
        ..
        .
}


Master libraries SimpleModbusMaster.h
In modbus_configure I have deleted byteFormat, from this:

Code: [Select]
void modbus_configure(long baud,
unsigned char byteFormat,
unsigned int _timeout,
unsigned int _polling,
unsigned char _retry_count,
unsigned char _TxEnablePin,
Packet* _packets,
unsigned int _total_no_of_packets);


to this:

Code: [Select]
void modbus_configure(long baud,
unsigned int _timeout,
unsigned int _polling,
unsigned char _retry_count,
unsigned char _TxEnablePin,
Packet* _packets,
unsigned int _total_no_of_packets);


Slave libraries SimpleModbusSlave.cpp
From this (byteFormat deletion):

Code: [Select]
void modbus_configure(long baud,
unsigned char byteFormat,
unsigned char _slaveID,
                      unsigned char _TxEnablePin,
unsigned int _holdingRegsSize,
                      unsigned int* _regs)
{
  Serial.begin(baud, byteFormat);
slaveID = _slaveID;
  ...
  ..
  .
}   


to this:

Code: [Select]
void modbus_configure(long baud,

unsigned char _slaveID,
                      unsigned char _TxEnablePin,
unsigned int _holdingRegsSize,
                      unsigned int* _regs)
{
  Serial1.begin(baud);
slaveID = _slaveID;
  ...
  ..
  .
}   


And last one: Slave libraries SimpleModbusSlave.h
From this (again byteFormat):

Code: [Select]
void modbus_configure(long baud,
unsigned char byteFormat,
unsigned char _slaveID,
                      unsigned char _TxEnablePin,
                      unsigned int _holdingRegsSize,
                      unsigned int* _regs);


to this:

Code: [Select]
void modbus_configure(long baud,
unsigned char _slaveID,
                      unsigned char _TxEnablePin,
                      unsigned int _holdingRegsSize,
                      unsigned int* _regs);


Also on slave side I had to change every Serial command to Serial1 command, cause Leonardo is using null serial port (Serial.xxx) for communication with computer over terminal and 1st serial port (Serial1.xxx) for communication with other hardware (arduino etc.).
Also I had to delete byteFormat from Master example and from Slave example (in modbus_configure line) to get no errors.

But still with these changes I'm unable to establish communication between arduinos. Due is sending an modbus message to Leonardo every 1 second (probably because timeout is set to 1000 ms), but Leonardo is not responding at all. If I print holdingRegs[PWM_VAL] on Leonardo over null serial port to computer terminal, I get value 0.

I don't know what can cause this problem but I hope not the Arduino 1.5.2 IDE. Any Idea?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JUGmobile on Jul 17, 2013, 08:55 pm
Well, I installed Arduino IDE 1.0.5 and try to establish connection with no success. Then I connect 2 Arduino Leonardos (so 1 Leonardo for master and 1 Leonardo for slave, instead of DUE for master) and get half of communication successful established. Then I tried to program Leonardos (master and slave) with IDE 1.5.2 and it is working the same way as with IDE 1.0.5.
Arduino IDE is not causing problems.

Looks like something is wrong on master (DUE) hardware part. I will try to figure this out but untill I find a solution, I will work with 2 Leonardos.

Here I am for now: I have changed libraries to work with Leonardo (Serial.xxx to Serial1.xxx) and IDE 1.5.2 (no parity and stop bits selection). I have successfuly establish connection in one way: Master->Slave. With potentiometer on master side I can regulate LED connected to PWM pin on slave side. Slave is responding to master request (watched on oscilloscope), but master somekind does not proccess informations that he gets. So I can not regulate LED on master side over potentiometer on slave side. Also master stops sending request to slave after 10 requests sended to slave (when retry_count is set to 5).

Problem is:
1) master send request to slave,
2) slave gets request (physical, measured with oscilloscope),
3) slave process request,
4) slave returns answer to master
5) master gets answer (physical, measured with oscilloscope)
6) master do not process slave answer

After 5 requests (10 actually: PRESET_MULTIPLE_REGISTERS - 5 times and  READ_HOLDING_REGISTERS - 5 times), master stops sending request to slave, due to retry_count which is set to 5. If I set retry count to 5000000, it still stops sending requests.

What can be wrong?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JUGmobile on Jul 18, 2013, 07:11 pm
Nothing new to show :( I tried to use libraries with parity and stop bit options (no changes from original libraries), only thing I have changed is Serial.xxx to Serial1.xxx, so I can work with Leonardo (Leonardo for master and another Leonardo for slave).

Again same problem. Master can control slave, but cannot process answer from slave. Here is picture of communication from oscilloscope:

(http://shrani.si/f/1m/wR/46U4LUB4/untitled-1.png)














    Oscilloscope settings:
    Time - 5ms/div
    RX channel - 2V/div
    TX channel - 2V/div



From picture above we can see that answer from slave is a bit shorter than master request. I think this is all right, or maybe not? But anyway, this is what master gets as an answer from slave, but still does not react on this answer.

JuanB: on what hardware were you testing this library? I realy don't think that hardware can cause this problem, since master can control slave, but who knows.

And many thanks for all help!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JuanB on Jul 24, 2013, 08:52 pm
Hi JUGmobile,
I tested the libraries on the Duemilanove. Imust admit I did not test the arduino master/slave examples with two Duemilanove's since individually they tested fine. Are you using 680Ohm pull up and pull down resistors?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JUGmobile on Jul 24, 2013, 09:38 pm
Hi JuanB,
Well I haven't tryed with pull up/down resistors. Now I connected 680E: A line to Vcc and B line to ground and unfortunately it's still not working.

Have you got an option to test this library on 2 Arduinos? I don't know what can cause this problem, but hardware part looks ok, since everything looks normal when watching signals on osciloscope.

Thank you for your time!
Jakob
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JuanB on Jul 26, 2013, 07:42 am
Hi Jakob,

I have another 328 lying around somewhere, I will hook it up on a bread board and connect them. Give me a few days...

In the mean time, try to remove a packet. Try just requesting a read function (F3) from the slave and see if you can get the LED to vary when turning the slave pot. Then use just F16 to request a write to the slave and see if the master pot varies the slave LED.

Use the two Read sketches together and the two Write sketches together.

SimpleModbusMasterArduinoRead.ino
Code: [Select]

#include <SimpleModbusMaster.h>

#define baud 9600
#define timeout 1000
#define polling 200
#define retry_count 5
#define TxEnablePin 2
#define LED 9

enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS
};

Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
unsigned int readRegs[1];

void setup()
{
  modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0, 1, readRegs);
  modbus_configure(baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
  analogWrite(LED, readRegs[0]/4);
}


SimpleModbusSlaveArduinoRead.ino
Code: [Select]

#include <SimpleModbusSlave.h>

#define  LED 9

enum
{     
  ADC_VAL,           
  HOLDING_REGS_SIZE
};

unsigned int holdingRegs[HOLDING_REGS_SIZE];

void setup()
{
  modbus_configure(9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);   
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
  holdingRegs[ADC_VAL] = analogRead(A0);
}


SimpleModbusMasterArduinoWrite.ino
Code: [Select]

#include <SimpleModbusMaster.h>

#define baud 9600
#define timeout 1000
#define polling 200
#define retry_count 5
#define TxEnablePin 2
#define LED 9

enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS
};

Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
unsigned int writeRegs[1];

void setup()
{
  modbus_construct(packet1, 1, PRESET_MULTIPLE_REGISTERS, 0, 1, writeRegs);
  modbus_configure(baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
  writeRegs[0] = analogRead(A0);
}


SimpleModbusSlaveArduinoWrite.ino
Code: [Select]

#include <SimpleModbusSlave.h>

#define  LED 9

enum
{     
  PWM_VAL,       
  HOLDING_REGS_SIZE
};

unsigned int holdingRegs[HOLDING_REGS_SIZE];

void setup()
{
  modbus_configure(9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);   
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update(); 
  analogWrite(LED, holdingRegs[PWM_VAL]/4);
}
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JuanB on Jul 26, 2013, 03:03 pm
Jakob,

Try a 10k resistor pull-up on the Rx pin to Vcc. Another user has found that noise triggered the Rx receive interrupt on his driver ic.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JuanB on Jul 26, 2013, 03:39 pm
More info,

The SimpleModbusMasterArduino and SimpleModbusSlaveArduino examples were tested by another arduinoist using a Mega as the master and a Micro as the slave with great success.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JUGmobile on Jul 27, 2013, 12:58 pm
Now I can say hurray!

Looks like I had same problems as "another user". I connected 10kE resistor from RX on master side to VCC and now it's working flawlessly! Again thank you very much for all the help!

Have a nice day,
Jakob
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 28, 2013, 02:53 pm
Awesome!

Just to finalize for further reviewing of this thread; Does the example code work successfully using the Mega/Leonardo or/and Leo/Leo?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Jul 28, 2013, 03:41 pm
Well, few things need to be changed for Leonardo and for Due.
Leonardo as master:
In SimpleModbusMaster.cpp few lines of code needs to be changed. Since Leonardo uses Serial.xxx command for communicating over USB with computer, and Serial1.xxx for TX1/RX1 for communication with other arduinos (including this modbus protocol), the Serial.xxx needs to be changed to Serial1.xxx.

Leonardo as slave:
In SimpleModbusSlave.cpp few lines of code needs to be changed. Exactly the same solution. Serial.xxx needs to be changed to Serial1.xxx.

Due as master:
Due only works with IDE 1.5.x. IDE 1.5.x does not support different parity and stop bits configuration so few lines of code needs to be changed in SimpleModbusMaster.cpp from this:
Code: [Select]
void modbus_configure(long baud,
                               unsigned char byteFormat,
                               unsigned int _timeout,
                               unsigned int _polling,
                               unsigned char _retry_count,
                                unsigned char _TxEnablePin,
                                Packet* _packets,
                                unsigned int _total_no_of_packets)
{
   Serial.begin(baud, byteFormat);
   *****
   ***
   *

to this:
Code: [Select]
void modbus_configure(long baud,
                               unsigned int _timeout,
                               unsigned int _polling,
                               unsigned char _retry_count,
                                unsigned char _TxEnablePin,
                                Packet* _packets,
                                unsigned int _total_no_of_packets)
{
   Serial.begin(baud, byteFormat);
   *****
   ***
   *


and in SimpleModbusMaster.h from this:
Code: [Select]
void modbus_configure(long baud,
unsigned char byteFormat,
unsigned int _timeout,
unsigned int _polling,
                                *****
                                ***
                                *

to this:
Code: [Select]
void modbus_configure(long baud,
unsigned int _timeout,
unsigned int _polling,
                                *****
                                ***
                                *


And byteFormat also needs to be removed from example code.

Due as slave:
Exactly same issue with IDE 1.5.x: byteFormat needs to be removed from example code, SimpleModbusSlave.cpp and from SimpleModbusSlave.h. This also has to be done for programming any other arduino with IDE 1.5.x.

I haven't tested Due-Leonardo configuration yet, cause hardware incompatibility (Due is working with 3.3V logic and Leonardo with 5V), but I have found a perfect solution for that. You can easily use 5V RS485 transceivers with 3.3V logic microcontrollers with simple solution. Details can be found in following PDF document: How to interface a 5V Transceiver to a 3V Controller (https://www.google.si/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CCoQFjAA&url=http%3A%2F%2Fe2e.ti.com%2Fcfs-file.ashx%2F__key%2Ftelligent-evolution-components-attachments%2F00-142-01-00-00-69-72-23%2F3V-MCU-to-5V-XCVR-Interface.pdf&ei=8Rz1UfqiDcnoswaMp4DwAg&usg=AFQjCNHbd6LI1U8uBYuqmpTNcEh3Qyikpg&bvm=bv.49784469,d.Yms).

Leonardo-Leonardo configuration is working good with your libraries, but Master and Slave libraries has to be changed. I have not tested Mega-Leonardo configuration because I don't have any Mega board, but I think it should work fine (of course on leonardo side, libraries has to be changed).

Have a nice day,
Jakob
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Jul 29, 2013, 08:54 pm
Amm and one another question: is there a possibility to tell something to all slaves at the same time? I mean Master say "Lets light the LED on pin 13" and all slaves instantly light the LED on pin 13.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 29, 2013, 10:20 pm
Use id = 0 with function 16. This is used for broadcasting.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Jul 29, 2013, 10:28 pm
Superb, thank you!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Aug 03, 2013, 07:22 pm
Successfully established connection between Leonardo (as Master) and Due (as Slave) with example code provided with libraries. BAS70 schottky diode is working perfectly well!

(http://shrani.si/f/3z/JV/3HCbYdzj/zajeta-slika.png)


But somekind, I can not establish connection between Due (as Master) and Leonardo (as Slave). I'll try to research this problem soon.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 05, 2013, 03:36 pm
Updated SimpleModbusMaster to V10. It now supports function 1, 2 and 15 with broadcasting also on 15. I have also altered the modbus_configure() method to allow the selection of different Serial instances (hardware serial ports).

I must say I have helped allot of users with the hardware side of the modbus protocol so here is a list of pre-flight checks:

1. 120ohm termination resistors on either end of the bus line.
2. 680ohm pull up and pull down resistors on bus line. Usually half way on the bus line depending on your layout.
    Using a MAX487 which has a quarter unit load (48k vs standard 12k) the pull up and down resistor combination can theoretically drive 48 nodes.
    Any voltage between -200mV and 200mV is not defined.
3. 10k pull up resistor from the Rx line (MAX487 driver pin DI) to Vcc.
4. Make sure the slave supports the correct function.
5. Make sure about the correct address.
6. Both master and slave driver ic's must run on the same voltage usually 5V.
7. If the slave is not responding initially try increasing the timeout and polling values. You can also increase the retry count to help in debugging initially.
    Writing (Function 16) usually takes longer than reading.
8. Use 2x twisted pair cable with shield on long distance communication where possible. The one pair you use for communication and the other either for 0V
    or 0V and Vcc supply.
    Contrary to popular believe RS485 is a 3 wire topology. You need a common reference (0V).
9. Connect a 100ohm 0.5W resistor in series between each node's 0V and the bus line 0V to avoid excessive unbalanced current draw.
9. The only bad questions are no questions and then... frustration and smoke ;-)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Aug 08, 2013, 07:53 pm
Great update, but library does not compile successfully on IDE 1.5.2 (hope arduino team make an update on that soon!). The problem is again parity and now the hardwareserial.h added too.

And I'm still trying to figure out why communication is only working when Leonardo is master and Due is slave and not in the opposite way (Due as master and Leonardo as slave). I have checked all of your points from first to double nine (the very last one makes sense) :) I have checked all points except 2nd (only about MAX487 part -> way too expensive). I do not know what can cause this problem. I'm still on example code provided with libraries and will be using them till I find a solution for problem.

So what is the problem: Hardware seems ok (or maybe not, again!), since everything works fine when Leo as master and Due as slave. But when Due is master and send a message to Leonardo as slave, Leonardo does not respond to it. Leonardo does get the message (at least phisicaly), but TX on Leonardo just stays on 5V all the time. So master (due) continue sending messages to the slave, till retry_count counts to deifined nr.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 08, 2013, 09:13 pm
Hi Jakob,

You are not alone with this kind of problem, take a look at these threads:

http://forum.arduino.cc/index.php?topic=151014.0

http://forum.arduino.cc/index.php?topic=153928.0

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Aug 08, 2013, 10:42 pm
Well this was genius! Exactly the solution I needed. I added a delay function of 3ms immediately after Serial.flush command in master library and now it works like a charm. I'm still not fully satisfied with this solution (delay command) so I will research this problem a bit more.

JuanB, I don't know how to thank you for all your help.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 09, 2013, 02:26 pm
No problem Jakob, glad I could be of help ;-)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 23, 2013, 04:22 pm
Hi,
I'm newbie to arduino.

I'm having a modbus enabled meter which has kWh value in register 286. I have a python code to read the register the meter and i know the packet formatting also.

Can you please guide me how to read the register from this meter using arduino.

I have arduino Leonardo.

I tried simple modbus library with RS-485 chip from Maxim MAX485.

My connections, i followed from this post : http://aglasspool.wordpress.com/2010/03/23/arduino-heatmiser-via-rs485/

But used simple modbus to read data.

I get some strange characters after i start the program. And the com light on the meter also doesn't blink.

Can you please help me..

Thanks in advance.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 23, 2013, 04:53 pm
Follow the connection on the simpleModbus site. Use V10. Make sure you use a 10k pull up indicated on the drawing. What type of meter is it? I will help you with the code..
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 23, 2013, 06:28 pm
Thanks for the reply.

I'm using different meters.
The one i'm reading is Fineco Meters from china. they provide only kWh which is register 286 and no. of words to read is 2

I've ElMeasure meter also LG119. Address map : http://www.elmeasure.com/downloads/mod_lgplus.pdf
In elmeasure it says register 40159 but from my python code im reading address as 158 to get Wh reading instead of 40158 and no. of words to read is 2

Schneider SmartLink ACTI 9.  Address Map : http://download.schneider-electric.com/files?p_File_Id=44883058&p_File_Name=DOCA0004EN-03.pdf
Pg. 60
I'm reading register 14204 and 14208 from my python code to get kW and kWh  and no. of words to read is 4 for each address.
Schneider adjusts the baud rate itself, no need to wirte.

Now from my computer i'm reading via serial configuration 9600, 8E1

I need to read the values from arduino leonardo. I've ordered this breakout board for better operation http://www.ebay.com/itm/271200250359?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1497.l2649
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 23, 2013, 06:42 pm
This is my code which i have burned inside arduino

Code: [Select]
#include <SimpleModbusMaster.h>
#define baud 9600
#define timeout 1000
#define polling 2
#define retry_count 50

#define TxEnablePin 2
#define LED 13

enum
{
 PACKET1,
 TOTAL_NO_OF_PACKETS,
};

Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
unsigned int readRegs[4];
void setup()
{
  /// Schneider Modbus Slave Id 1 and start register 14204 and length 4
 modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 14204, 4, readRegs);
 ///// Starting serial for Leonardo
 Serial.begin(9600);
 while (!Serial) { ; }
 
 modbus_configure(&Serial1, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
 pinMode(LED, OUTPUT);
}

void loop()
{
 modbus_update();
 
 if (Serial1.available()){
   /// Write the received data from Serial 1 to Serial
   Serial.write(Serial1.read());
   delay(1000);
 }
 analogWrite(LED, readRegs[0]>>2);
}
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 23, 2013, 07:51 pm
On the Leo you can only use the Serial1 object. Although you have done this you cannot access the Serial1 object methods as this will conflict with the library. The information should be stored in the array you initialized the packet to, in this case readRegs[4]. This array contains the unsigned int values read from the slave. Since modbus only specifies unit16 values you will have to read 2 registers per float value. You will need to shift the two consecutive unsigned integers together to form the float32 value. You can then use Serial (USB) to transmit the two registers to the PC.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 23, 2013, 08:04 pm
So the  readRegs[4] contains the 4 words read from the slave.
readRegs[0] 1st word
readRegs[1] 2nd word
readRegs[2] 3rd word
readRegs[3] 4th word

Actually i want to read the registers and store the data on SD Card.
Arduino will read the data periodically and update the file by over writing the entries in the file.
The file will act as a sort of database.
As of now just for debugging i am printing the output to Serial1.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 23, 2013, 08:50 pm
Yes, readRegs[] contains the requested registers information.

According to the arduino product page you must use Serial for USB transmission and Serial1 for UART (modbus) on the Leo.
http://arduino.cc/en/Main/ArduinoBoardLeonardo
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 26, 2013, 10:05 am
Hello,

I tried with the schematics from simple modbus. Didn't Work.

Tried a breakout board for RS-485. Didn't work.

Serial port hangs never enters the if condition where it checks if hardware serial is available using breakout board.

Reading output of hardware serial. Giving junk values without even connecting wires.

Please help. Thanks
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 27, 2013, 07:34 am
Hi meetjeremy,

Again, you can not access the Serial1's objects methods directly. You must transmit the contents of readRegs[] using Serial.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 27, 2013, 09:37 am
If you see the third attachment in my previous post. I have done that.

Still no output  :(
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 27, 2013, 10:15 am
The third attachment still uses Serail1.available() and the other one uses Serial1.read(). This wont work.

Use Serial.println(readRegs[]) or something similar like you already did to transmit the received values from Serial1 (the modbus connection). Again you cannot use Serial1.available() since it will most of the time be empty depending when you read it. The library reads the received information and stores it in the assigned register array, in this case readRegs[]. This is the only way of interfacing with the information received.

If you want to know if the request packet is successful than access the packets following information counters like this:
packet1->requests;
packet1->successful_requests;
packet1->failed_requests;
packet1->exception_errors;

Also try not to use delay() with values larger than 100ms. It will affect the polling and timeout values.

If you want to periodically send the received information from readRegs[] to Serial (USB) than rather use millis() in a timely manner or check if the value linked to the regdRegs[] index has changed.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 27, 2013, 11:18 am
Hello JuanB,

Thanks for the reply.

I printed this
Code: [Select]
void loop()
{
  modbus_update();
  //if (Serial1.available()){
    /// Write the received data from Serial 1 to Serial
    //Serial.println(Serial1.read());
    //Serial.println(readRegs[]);
    Serial.println(packet1->requests);
    Serial.println(packet1->successful_requests);
    Serial.println(packet1->failed_requests);
    Serial.println(packet1->exception_errors);
    //Serial.println(readRegs[1]);
  //}
  analogWrite(LED, readRegs[0]>>2);
}

but i'm getting

50
0
50
0

that is requests made 50 but all failed requests.

Even the comm. light on the meter is not blinking.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 27, 2013, 03:50 pm
Hi meetjeremy, since the information is scattered could you please mail me your complete sketch to bester.juan@gmail.com.

Maybe I have asked this but did you connect the driver ic (or break out board) according to the RS485 connection schematic on the SimpleModbus site?

What arduino are you using?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 28, 2013, 06:56 am
Hello JaunB,

Thanks for the reply.

I'm using Leonardo for this project.

Yes i have connected the circuit according to the schematics.

I have sent you the code in your mail.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 28, 2013, 09:52 am
Hi Jeremy,

Assuming that you are referring to the ElMeasure meter LG119:

Try using the address 159 directly as some master implementations include an offset automatically.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 28, 2013, 01:52 pm
Hello JuanB,

i tried reading for register 40159 and tried 159 also. It didn't read. I read it via rs485 usb converter also it didn't send anything. So now i'm not reading from Elmeasure.

---------------------------------------------------------------------------------------------------------------------------------

I tried the same with Fineco (China) meter also and the readReg[] gives different values. The communication led on the meter is blinking. And when addressed on a Daisy chain only that particular meter is read. But the values are not proper.

Code: [Select]

    //Serial.println(readRegs[0]);  0
    //Serial.println(readRegs[1]);  0
    //Serial.println(readRegs[2]);  12801
    //Serial.println(readRegs[3]);  2
    //Serial.println(readRegs[4]);  259
    //Serial.println(readRegs[5]);  29
    //Serial.println(readRegs[5]);  21762
    //Serial.println(readRegs[6]);  241
    //Serial.println(readRegs[7]);  0
    //Serial.println(readRegs[8]);  0
    //Serial.println(readRegs[9]);  0
    //Serial.println(readRegs[10]);0
    //Serial.println(readRegs[11]);0


Another thing.. If i remove the 10k resistor then the communication light blinks for every 1 second properly. Else if i have the 10k resistor then the light blinks very fast continuously with very less gap.

Best thing i'm now able to see the communication light blinking, but now i don't know how to get the proper data.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 28, 2013, 02:12 pm
Hi jeremy,

This is strange indeed, although if the code is so short and depending on the response of the slave than the led flash rate should theoretically be very quick not 1 second intervals as you have described. If I connect an led (with 220ohm resistor)on the TxRxEnable output the led will flash according to the polling rate of 200ms which is editable in the code. So rather leave the 10k in place as the 1 second interval you are perceiving is most likely the timeout of 1000ms expiring due to false reception.

Your statement: "I read it via rs485 usb converter also it didn't send anything." Are you referring that you have used another modbus implementation via an USB-RS485 converter?

Maybe the ElMeasure meter LG119 is dead?

Anyway...

Mail me the code for the Fineco (China) meter and the complete data sheet so I can have a look at the address space.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 28, 2013, 02:27 pm
Hello JuanB,

Ya i think Elmeasure is dead. Let me check with other modbus readers.

Let me try to connect a 220ohm resistor wit led at txrxenable pin.

Ok i'll mail you the data sheet.

Thanks
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 28, 2013, 02:45 pm
Hello JaunB,

I tried the LED. Yes its flashing for every 200 ms.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Aug 28, 2013, 03:11 pm
Hi meetjeremy,

Have you connected GND from master to slave (from one RS485 device to other)? This is one more possibility why it's not working.
Hf, Jakob
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 28, 2013, 03:46 pm
also..

You can use hex values in the ide. Change the id, baud and parity if necessary.

Code: [Select]

#include <SimpleModbusMaster.h>

// Fineco

#define baud 9600
#define timeout 1000
#define polling 200
#define retry_count 10

#define TxEnablePin 2
#define LED 13

enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS,
};

Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
unsigned int readRegs[1];
void setup()
{
  modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0x011E, 1, readRegs);
  ///// Starting serial for Leonardo
  Serial.begin(9600);
  while (!Serial) { ; }
 
  modbus_configure(&Serial1, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
  Serial.print("requests: ");   
  Serial.println(packet1->requests);
  Serial.print("successful_requests: "); 
  Serial.println(packet1->successful_requests);
  Serial.print("failed_requests: "); 
  Serial.println(packet1->failed_requests); 
  Serial.print("exception_errors: "); 
  Serial.println(packet1->exception_errors);
  Serial.print("Active energy: "); 
  Serial.println(readRegs[0]);                         
}


Of course, missed that one, thanks Jakob. Definitely need a common reference.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 28, 2013, 04:18 pm
No luck..

i connected with the ground of arduino to the slave.

this is the result..

requests: 10
successful_requests: 0
failed_requests: 10
exception_errors: 0
Active energy: 0

Do you think 100 ohm might be the problem.. because when i removed it, the comm. led stopped blinking.
i'll try with 120 ohm and let you know.

Thanks.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 29, 2013, 08:32 am
Jeremy,

If it still does not work after connecting the 120ohm resistor please measure the voltage across the 120 ohm resistor while the master driver ic (MAX485) is in receive mode. The differential voltage must be more than 200mV or less than -200mV.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 30, 2013, 08:31 am
Hi,

Still No output,

I have connected 120 ohm resistor.

The voltage across 120 ohm resistor is 84 mV When i measured.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 30, 2013, 08:55 am
Could you post your connection schematic including the break out board schematic...
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 30, 2013, 08:58 am
Hello JaunB,

Verry Good news..

I rewired the board one connection was wrong..

Now things are working fine.

I'm getting data.... Thanks a lot..

And I really mean it.. Thanks a ton for you help....
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 30, 2013, 12:08 pm
Thank goodness ;-)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 30, 2013, 12:09 pm
... what connection was bad?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 30, 2013, 02:26 pm
The 680 ohm resistors were placed wrongly.

Now everything works perfectly.

Thanks.

(https://forum.arduino.cc/index.php?action=dlattach;topic=176142.0;attach=52758)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: meetjeremy on Aug 31, 2013, 09:20 am
Hello JaunB,

Is it mandatory that we have to pass hardware serial only in this line of code

modbus_configure(&Serial1, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);

OR

can we send software serial also? if yes, how to do it?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Sep 03, 2013, 02:08 pm
Hi Jeremy,

Yes you can only use hardware serial objects, but you can change the cpp and h file to use software serial instead. I will upload such a library soon...
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Morale64 on Sep 10, 2013, 09:07 pm
I noticed that if the connection drops for example by turning off the slave when the slave is rekindled communication does not resume, if I increase the timeout I can wait few seconds to turn on the slave and the comunication will resume. but I would like the communication resumption even long after it has lost. Thanks
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Sep 10, 2013, 09:26 pm
Hi Morale64,

What master are you using to poll the slave?

If you are using SimpleModbusMaster than the retry has most likely expired depending on the timeout and polling values. You can reactivate the corresponding packet by setting the "connection" attribute to true (1) if it is indeed false (0).
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Morale64 on Sep 11, 2013, 07:38 am
Hi JuanB,
well so where a specific packet don't work for a time lager then "timeout X retryes" the connection become 0 and it will never become 1, I have understand?
In this case we can check the state And change it.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: ryardman on Oct 19, 2013, 03:14 am
Juan,

I am trying to use your Simple Modbus lib without success.  I have read through all the post here and tried each of the suggestions to no avail.  I even order the the resistors and MAX487s from digiKey per your schematic.  I have rewired the board twice in hopes of getting it to work.  I get more than 200mv across the 120 resistor on the comm line.  What is the best way to trouble shoot this?  I have tried the serial dump and I get 10 tries and 10 fails.  I added the delay(3) to the master cpp code.  Still not working.

Oh... I am using IDE 1.0.5 and 2 uno R3 boards.

Any ideas?

Thanks
-=Ryan
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Oct 19, 2013, 11:06 am
Hi ryardman,

Have you used SimpleModbusMasterArduino.ino and SimpleModbusSlaveArduino.ino sketch together? The examples are made to work with each other and with proper wiring this should work "right out of the box".  At first do not try to change the example code. Just programm UNOs to these 2 sketches and rewire board. Be carefull how to connect resistors. And maybe if you have an oscilloscope put an image of your "dataflow" here.
Hf, Jakob
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: ryardman on Oct 19, 2013, 05:06 pm
Hi Jakob,

Thanks for the reply.  Yes I am using those 2 sketches and only made the change to add the delay(3) as you did to the master cpp.  I have rewired the board a few times now, still no luck.  When you say becareful with the resistors where should they be?

I have a xProtoLab micro oscilloscope... but I not sure where to connect the wires.  I tried using the protocol sniffer on the comm lines and it displays a bunch of HEX codes.

I will take some photos of my wiring and upload them in another post.

-=Ryan
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: ryardman on Oct 19, 2013, 05:32 pm
photos of my modbus with max487 wiring
-=Ryan

(https://forum.arduino.cc/index.php?action=dlattach;topic=176142.0;attach=56966)

(https://forum.arduino.cc/index.php?action=dlattach;topic=176142.0;attach=56968)

(https://forum.arduino.cc/index.php?action=dlattach;topic=176142.0;attach=56970)

(https://forum.arduino.cc/index.php?action=dlattach;topic=176142.0;attach=56972)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Oct 19, 2013, 07:09 pm
At first resistors between A and B line are meant to be positioned at the end of lines.  And for testing on breadboard you could try to connect none or only one resistor at the end of A-B line. Try to remove pull-up and pull-down resistors, and remove everything from the A-B line except 120E resistor. The LEDs are not meant to be there.

Then the software side: the delay I have used in library isn't 3 seconds but it is 3us so use the delayMicroseconds() (http://arduino.cc/en/Reference/DelayMicroseconds) function.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: ryardman on Oct 19, 2013, 09:52 pm
I will try your suggestions.  thanks.  What do you mean by the LEDs are not meant to be there?  I thought the sketches control the Dimness of LEDs via pin 9? 

Without the LEDs how would you know if the modbus is working?

Thanks
-=Ryan
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Oct 19, 2013, 10:22 pm
Oh sorry for that. LEDs are correct, I though they are connected to A and B line.
Hf, Jakob
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: ryardman on Oct 22, 2013, 04:35 am
OK found the problem.  The code I downloaded had ArduinoSlave ID set to 1, but the master was sending to ID 2.  After correcting this it worked.

Thanks
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: royemmerich on Oct 28, 2013, 12:10 am
Dear Juan,

Firstly, hello from a fellow South African :D Secondly, thanks so much for all your selfless work on this topic so far. I'm very impressed!

My request:
I have a Midnite Solar Classic Lite charge controller which I want to communicate with:

http://goo.gl/jCLxq4 (http://goo.gl/jCLxq4)

It is capable of talking MODBUS RTU over RS232 (fixed 19200 baud) or TCP and I have tested both using modpoll (http://www.focus-sw.com/fieldtalk/modpoll.html (http://www.focus-sw.com/fieldtalk/modpoll.html)) on my Linux desktop.

As I have a multi-drop RS485 (9600 baud) bus on my site, I am wanting to use an Arduino Uno as a translater/converter from RS232 (using SoftwareSerial) to RS485 (using the Rx/Tx pins).

Although I'm new to MODBUS, from how I understand things MODBUS is MODBUS, irrespective of the underlying physical layer (RS232/485 or TCP). My question to you is this. Is it possible to use SimpleModbus over RS232 and if so what should be changed in your library (if anything) to get this to work?

Many thanks
Roy
P.S. From this post:

https://code.google.com/p/simple-modbus/issues/detail?id=10 (https://code.google.com/p/simple-modbus/issues/detail?id=10)

it seems like I would have to have the following hardware setup:
Uno -> RS485 transciever -> RS485 to RS232 converter -> charge controller

P.S.2 Another option would be to get an ethernet shield and just communicate via TCP using this library:
http://myarduinoprojects.com/modbus.html (http://myarduinoprojects.com/modbus.html)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Nov 05, 2013, 07:23 am
Hi Ryan,

My apologies. I have fixed the slave example in SMSV8.

Title: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: JuanB on Nov 05, 2013, 08:20 am
Hi Roy,

Thanks for the South Africa greeting   XD

Modbus is the software protocol and RS232/422/485 is the topology.

Since there is a difference in RS232 and TTL232 you will need a level translator to level shift the +-10V RS232 signal to 0 - 5V TTL232 for the arduino.

I had a look at the CLASSIC LITE 250 manual and could not find anything related to modbus RS232 only tcp which is way different.

On the simplemodbus site you will find a diy level shift circuit which I have tested extensively and works very well indeed.

So basically you want to use the arduino to act as a master (using the software serial library) to communicate with the CLASSIC LITE 250 which has only RS232 at 19600 baud. The arduino will than also act as a slave on your RS485 9600 baud bus system. All this communication works using modbus. Is all this correct so far?

If the train of though above is correct than the modbus master library needs to be changed to accommodate the software serial core library. This is easy.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: royemmerich on Nov 05, 2013, 09:02 pm
Quote
Modbus is the software protocol and RS232/422/485 is the topology.


Yes I am aware of this :)

Quote
Since there is a difference in RS232 and TTL232 you will need a level translator to level shift the +-10V RS232 signal to 0 - 5V TTL232 for the arduino.


Yes, I am using this little board from Sparkfun:

https://www.sparkfun.com/products/11189 (https://www.sparkfun.com/products/11189)

Quote
I had a look at the CLASSIC LITE 250 manual and could not find anything related to modbus RS232 only tcp which is way different.


I agree , their documentation of the MODBUS over RS232 functionality is very sparse. The Midnite solar folks have a cool forum filled with very helpful people. I have fully documented what I've done to communicate with the Classic via RS232 from my desktop using the modpoll simulator. Suffice to say it certainly does work:

http://midniteforum.com/index.php?topic=1431.0 (http://midniteforum.com/index.php?topic=1431.0)

Quote
So basically you want to use the arduino to act as a master (using the software serial library) to communicate with the CLASSIC LITE 250 which has only RS232 at 19600 baud. The arduino will than also act as a slave on your RS485 9600 baud bus system. All this communication works using modbus. Is all this correct so far?

If the train of though above is correct than the modbus master library needs to be changed to accommodate the software serial core library. This is easy.


Yes, this is almost correct. I do have the option to communicate with the Classic via MODBUS over TCP but that would mean having to get an ethernet shield which I would prefer not to do right now. Getting MODBUS over TCP going on the Arduino is however on my todo list.

Also, as I am building up a general purpose logger with the intention of being able to communicate with as many different devices as possible and with MODBUS being one of the most widespread industrial protocols in use, I would very much like to be able to do MODBUS over RS232 too, preferably with the same code base.

I hope this explains things a bit more clearly? I'm glad that you say it should be easy to do what I need to do. I will take a look at your code again and see whether I can figure it out myself.

Thanks in advance.

Roy
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Nov 06, 2013, 06:24 am
Hi Roy,

Is there no way to change the baud rate of the CLASSIC LITE 250 or the baud rate of the other slave devices on your bus?
To adhere the to the modbus protocol a few things must be implemented by the manufacturer like odd parity, choice between 9600 and 19200 baud rates and RTU mode. Most devices do implement this. If the controller can't then maybe the other devices can.

If you can change the baud rates on either side than you can just use an auto receive/transmit circuit like the one on the simplemodbus site and supply it with an auxiliary 5V supply from the controller (if it has).

I you can't change anything well... If you want I will help you out on changing the library for SoftwareSerial. Bear in mind that SoftwareSerial uses an interrupt to receive which is very cpu intensive. How SoftwareSerial and HardwareSerial interact is something of a prediction  :smiley-slim:
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: schiavanoelettro1 on Dec 04, 2013, 05:30 pm
I'd like to implement a sort of Modbus RTU over Bluetooth protocol.
I tried to use SimpleModbus library, Master Bluetooth send right command to Slave Bluetooth, but Slave didn't answer.

But If I send string command from the Master, Slave answer well and all works.

I understand that "problem" is in SimpleModbus library that is thinked and structured for RS485 channel.
But how and where could I change SimpleModbus library to work well both on RS485 anb Bluetooth channel?

P.S.: Sorry for my English  :smiley-red:
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Dec 04, 2013, 10:44 pm
Hy schiavanoelettro1,

I cant help you with that, just want to say, if you make it works, please post here code. I might need this in future, who knows. Also what BT modules are you using?

Regards, Jakob
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Dec 05, 2013, 06:43 am
Hi schiavanoelettro1,

I need a bit more information to diagnose. What type of BT module are you using? Is there a spec sheet? How are you interfacing with the module? TTL232, RS232, SPI, bit bang? What size is the receive buffer of the module? What is the through put of the module?

Juan Bester
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: schiavanoelettro1 on Dec 05, 2013, 07:28 am
I'm using a pair of HC-05 Bluetooth Module with backplane without RS232 converter.
One is configured as Master and the other as slave.

http://www.exp-tech.de/service/datasheet/HC-Serial-Bluetooth-Products.pdf

To do my experiments, I use 2 Arduino Mega, so I can read data flow on serial monitor.

Serial parameters are same for all:
in modbus library I put : 9600,8,N,1
in every BT modules I put: 9600,8,N,1.

What is the matter, doctor?

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Dec 05, 2013, 09:06 am
The manual is a bit much to go through now but if you are sure that master and slave are correctly paired by verifying this on the led connections than it seems like the BT module is just a TTL232 to BT translator.

I couldn't find anything on response times from switching over from Tx to Rx but this shouldn't matter much as modbus is a master request slave response protocol. Although RS485 is mostly used RS232 or TTL232 is no problem as modbus is just the protocol, any topology could be used.

There is the inter-character and frame delays that must be taken into account though. I would try to change the T1_5 constant by changing "T1_5 = 16500000/baud" in line 412 in the SimpleModbusMaster.cpp file to some larger value, say "T1_5 = 5000". This will allow the BT modules buffer to fill while the arduino is processing the reply.

The same has to be done in SimpleModbusSlave.cpp in line 60. Change "T1_5 = 15000000/baud" to "T1_5 = 5000".

I would also increase the timeout value depending on the BT modules response and the distance between master and slave.

Could luck.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: schiavanoelettro1 on Dec 05, 2013, 10:54 am
Sometimes slave reply, sometimes no.

But surely it is a forward step.

:-)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: schiavanoelettro1 on Dec 05, 2013, 11:21 am
I tried to increase both T1_5 (inter-character delay) and T3_5 (frame delay) up to 20000, but nothing changed.

Only few times slave answer correctly.

So?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Dec 05, 2013, 01:40 pm
Did you use a 10k tie up resistor from Rx to Vcc?

What are your polling and timeout values? Try a 3sec timeout and 1sec polling.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: schiavanoelettro1 on Dec 05, 2013, 03:50 pm
COOOOOOOMEEEEEEEEE OOOOONN....

Everything works well.

It's fantastic.

:)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: schiavanoelettro1 on Dec 05, 2013, 04:00 pm
This is the instruction that saves my working day:

In SimpleModbusSlave.cpp (only in this file and not in SimpleModbusMaster.cpp) I added delay 50 instruction:

Code: [Select]
  while ((*ModbusPort).available())
  {
  // The maximum number of bytes is limited to the serial buffer size of 128 bytes
  // If more bytes is received than the BUFFER_SIZE the overflow flag will be set and the
  // serial buffer will be red untill all the data is cleared from the receive buffer.
  if (overflow)
  (*ModbusPort).read();
  else
  {
  if (buffer == BUFFER_SIZE)
  overflow = 1;
  frame[buffer] = (*ModbusPort).read();
  buffer++;
///////////////////////////////////////////////////////////////
  delay (50):
///////////////////////////////////////////////////////////////
  }
  delayMicroseconds(T1_5); // inter character time out
  }

  // If an overf
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: schiavanoelettro1 on Dec 05, 2013, 04:02 pm
Thanks JuanB.
A lot.
Bye.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: schiavanoelettro1 on Dec 05, 2013, 04:08 pm
Last question.

Is it possible to use a Software Serial instead Hardware Serial with SimpleModbus library?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Dec 06, 2013, 06:15 am
It is possible and it's not too difficult but bear in mind that the cpu will work overtime due to the interrupt driven nature of library.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: jfrisbie on Dec 20, 2013, 07:09 pm
I have tried all the changes noted here however I still receive  "error: 'SERIAL_8N2' was not declared in this scope" when I try to compile on IDE version 1.5.4? Is there a download of the complete modified library somewhere?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Dec 25, 2013, 05:58 pm
I don't think the 1.5.* environment supports these defines (byte format). You can remove them in the cpp and h files. The testing was done on the V1.05 with a Duemilanove.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Dec 29, 2013, 02:38 pm
jfrisbie, check the very first page from this thread. I had the same problem with parity and stop bits incompatibility on my DUE and IDE 1.5.x. I just removed that option (SERIAL_8N2) from the library and recompile program without problems.

Regards,
Jakob
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: hillcz on Jan 09, 2014, 09:07 pm
And if i need 8N2 format? Any solution?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: hillcz on Jan 11, 2014, 02:00 pm
I have MODBUS MASTER V10

But with this warning

SimpleModbusMaster\SimpleModbusMaster.cpp.o: In function `modbus_configure(HardwareSerial*, long, unsigned int, unsigned int, unsigned char, unsigned char, Packet*, unsigned int)':
C:\arduino-1.5.5-r2\libraries\SimpleModbusMaster/SimpleModbusMaster.cpp:430: warning: undefined reference to `HardwareSerial::begin(unsigned long)'


Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: cmassicot on Jan 17, 2014, 05:16 pm
Hello,

This library is exactly what I needed but I  am struggling to get it working.

I am implementing a Modbus Slave on an Arduino Uno R2.

I built the simple Modbus slave example in the Arduino with the default settings

modbus_configure(&Serial, 9600, SERIAL_8N2, 2, 2, HOLDING_REGS_SIZE, holdingRegs);   

I am trying to read the first register at address 0 using the USB connection  from my laptop to the Arduino Uno. My serial configuration is also 8N2 on my Laptop.

The Hex command I am sending is 0203 0000 0001 8439

The Uno receives the command (RX led flashing) but it does not reply.

Is there a problem with my Modbus command,is there a problem with using the USB connection with this library, is it the Uno?

Any help would be much appreciated.

Thanks

Charles
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: cmassicot on Jan 17, 2014, 08:33 pm
OK It is solved

2 things

1 . My Command was wrong, I had forgotten that the address range in Modbus starts at 0x4000, not zero, the right command was 0203 4000 0001 91F9

2. Communication to the Modbus library does not work through the USB input on the Uno (This is not a big problem since I was only using it for testing) Once I used the pins 0 and 1 for Serial communication, it started to work.

Thanks for your very useful library  JuanB

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jan 27, 2014, 08:11 am
I'm glad it works!

What happens when you use Qmodbus or MTester on the slave? The usb "should" still work as the PC will detect the 16U2/8U2 as a standard serial port if setup for COM.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: bsahilu on Feb 05, 2014, 05:43 pm
Hey ModBus gurus,

I'm putting together a system that has ONE Master using an Arduino Mega controller and (ideally) 32 Slaves using Arduino Unos.
Each Slave has:
(1) DC motor running off of an h-bridge to perform a function
(2) input switches to determine state of above motor

The Master's only function is to periodically monitor the state changes of each Slave's switches and also send out commands to activate the motor state via a user input.

Currently, I have 2 Slaves and 1 Master.  It's working really well.....excccccccept, I only have communication going in ONE direction.  MASTER ----> SLAVE

For some reason it isn't getting any responses BACK.

I will include my setup shortly, but I figured someone might have a typical solution for this problem off top.

Also, in the modbus_configure() of the Slave, it allows me to define the SELF ID.  How come in the modbus_configure() of the Master, it doesn't?  How do the Slaves packet their data and send it to the Master?

Perhaps this is why I'm not getting any responses back??

FYI, I'm using the latest revs of both SimpleModBusMaster & SimpleModBusSlave

Thanks in advance guys!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Feb 05, 2014, 09:04 pm
Hi bsahilu,

I don't quite understand what you are trying to do? There can be theoretically only one master in modbus. When a master sends a request to a slave the slave will respond by usually echoing its slave id and function requested in the first two bytes. It does not need to know the master's id (there is none). The master listens (waits for timeout or successful response) from the slave. All salves including the master "listens" on the multidrop network. When a slaves parses the frame and verifies the first byte is it's slave id it will process the request and the other slaves will go back to there idle or listening state. The master is, in a sense, the custodian of the network, nothing can happen with out it. If a slave needs to communicate to another slave it needs the master to extract the information from its self and then write it to another slave.

To clarify:

Can  you write/read registers to/from slave 1 and 2 with the master?

Note:

In the beginning of this thread many user experienced problems with the mega due to the quirkiness of the hardwareSerial library. I think a delay was added in the library to stop the frame from being truncated.

The libraries were tested on a Duemilanove between various slaves and masters from power meters to alarm panels and PLC's.

If you want to you can mail me your code so I can have a look at it...

Cheers....
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: bsahilu on Feb 07, 2014, 12:21 am
JuanB,

Thanks for your reply.

Please pardon my newbie questions (as you've seen in the previous post) , I'm new to ModBus. 
So let me explain my objective:

I have a system that locks a drawer via a mechanism operated by a DC motor, the state of the drawer and the state of the lock are monitored by inputs from 2 mechanical switches.   
Is DRAWER: Open/Closed?
Is LOCK: Locked/Unlocked?

Since there are multiple drawers, there will be a dedicated Uno board for each drawer. Hence these will all be the SLAVE units.

I will be connecting them via a daisy-chain bus leading back to the main controller, an Arduino Mega running a sketch that will continuously poll the slave units for lock and drawer status.  I will also need to send LOCK/UNLOCK commands to each lock based on some other criteria.  The addressing capabilities of the ModBus system easily lends itself to a perfect match for my application.

Now on to my frustration.
My understanding of ModBus was initially skewed.  I understood that the packet being constructed by the MASTER contains the recipient's address along with the necessary data, then broadcasted throughout the network.  The information will ONLY be processed by the SLAVE whose address matched (unless it's a broadcast address ZERO).  Where I got hazy was when the SLAVE receives that data, how does it package the requested information and sends it to the MASTER? What is the handshake that's done to insure that the message only goes to the MASTER rather than other SLAVES who are also in LISTENING mode?

Looking back at your previous response, you state that the SLAVE responds by echoing its address and somehow the MASTER knows the message is for itself and processes it.  Perhaps I'm not the only one that's a bit confused by that.  However, in thinking about it, by echoing the its address prevents the OTHER slaves from caring about its message.  So does that mean the MASTER will take any message since it's all high and mighty?

Anyways, my more pressing problem is that I can send commands to each lock and it process it, but requesting the status of the 2 switch states is NOT working.  Even though, yesterday, I managed to get that to work....intermittently.

1. I've tried putting in a delayMicroseconds(3);
2. I've tried putting in pull-up resistors on the RX line

The only things I do NOT have are any terminating resistors (it's on my desk with short cables) or the 680E resistors.

Any ideas?


JaunB, I'll send you my code shortly.




Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: platoxii on Feb 07, 2014, 02:47 am

also..

You can use hex values in the ide. Change the id, baud and parity if necessary.

Code: [Select]

#include <SimpleModbusMaster.h>

// Fineco

#define baud 9600
#define timeout 1000
#define polling 200
#define retry_count 10

#define TxEnablePin 2
#define LED 13

enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS,
};

Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
unsigned int readRegs[1];
void setup()
{
  modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0x011E, 1, readRegs);
  ///// Starting serial for Leonardo
  Serial.begin(9600);
  while (!Serial) { ; }
 
  modbus_configure(&Serial1, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
  Serial.print("requests: ");   
  Serial.println(packet1->requests);
  Serial.print("successful_requests: "); 
  Serial.println(packet1->successful_requests);
  Serial.print("failed_requests: "); 
  Serial.println(packet1->failed_requests); 
  Serial.print("exception_errors: "); 
  Serial.println(packet1->exception_errors);
  Serial.print("Active energy: "); 
  Serial.println(readRegs[0]);                         
}


Of course, missed that one, thanks Jakob. Definitely need a common reference.


Sorry, I have a question . When I tried to compile this code ,error show up.It's show serial1 not declare in this scope

in line 29

Thanks
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Feb 07, 2014, 06:13 am
Hi bsahilu,

Think of the slaves as IO extensions of the master. The master expects the slave that it requested to respond. It monitors that. If another slave responds or the frame has errors the master will reject the response and try again later.

In your code you use modbus_update() in a while loop (and various other places which is probably why it still works). This can not be done since the function is the entry point for the State Machine running in the background. It can be called numerous times to speed up response times in the main sketch but there should not be any condition linked to it.

It is also not advisable to block construct_packet() since this initializes the packet with the necessary information and addresses it needs to poll correctly. Think dangling memory pointers etc... BAD!

The correct practice is to manipulate the the data that will be written to or read from the slave, not inhibit the communication procedures. This means manipulating the register array you initialized the packet to, in this case readRegs[] and writeRegs[]. The State Machine will take care of the communication in the back ground. The slaves are always polled sequentially at the scan rate. This means slaves are always updated with the packet you assigned to it, only the data in the packet is changing according to your logic.

E.g.

You are writing the lock state not by selecting different slaves and updating the writeRegs[] but by pre-assigning slave id's and then assign different register arrays to different packets. You can then update each set of registers linked to that specific packet which in turn is linked to a specific id. Does that make sense...

Further E.g...
You would just manipulate the writeRegs[0] with a 0 or 1 which is then continuously transmitted to the slave. All the logic of your drawer system is in your master code, but the inputs and outputs in this case are extended by the slaves. This is what I meant in the very first sentence above.

The intermittent nature of your communication is most likely linked to not using the pull-up and pull-down resistors. Termination resistors are always a good idea when the distance exceeds 1 meter and absolutely necessary when in the vicinity of noisy equipment (motors, VF drives etc..).
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Feb 07, 2014, 06:14 am
Hi platoxi,

Can you compile the example sketches? What version of arduino IDE are you using?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: platoxii on Feb 07, 2014, 06:40 am
Hello JuanB

Which one  example sketches you mean? I add many modbus example in my library but not all of them can be compile successful

But if you mean simpleModbusMasterArduino ,yes it's can be compile.I download version is SimpleModbusMasterV9

My IDE is arduino-1.0.5-r2

Thank for your reply
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Feb 07, 2014, 07:13 am
The examples in the master and slave libraries are written to communicate with each other. A Duemilanove was used in testing.

Both libraries compile successfully under V1.05 and communicates successfully between master and slave.

Use the examples in the libraries to build your code on. It should compile and run with out any problems. The latest is V10 which adds function 1, 2 and 15. MasterV10 and SlaveV8 examples can communicate directly with each other.

SMMV11 and SMSV9 are on its way. I have added the option in SMSV9 to adjust the baud, and id dynamically in the code. I have also updated the BUFFER size in both libraries since the arduino team changed it in V1.05.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: bsahilu on Feb 07, 2014, 07:43 pm
JuanB,

I'm trying to digest what you've written.  I will revise my logic and report back.

In the mean-time, thank you for taking the time to look at my code.

I'm learning A LOT!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: dgtldan on Feb 07, 2014, 08:05 pm
Hi JuanB,

Does your library provide support for Function Mode 10 in Modbus protocol?

I am using a device which used this mode for direct target positions and speed command and looking for a suitable library.

Thanks.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Feb 07, 2014, 08:35 pm
Hi bsahilu,

No problem. Drop me a mail when your ready..
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Feb 07, 2014, 08:38 pm
Hi dgtldan,

I'm assuming that's 10hex which is function 16. It does support this function.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Paulinho19 on Feb 17, 2014, 09:22 pm
I'm trying to use this library with the Arduino Due but I'm getting the following error when compiling:

ModbusMaster.ino: In function 'void setup()':
ModbusMaster:26: error: 'SERIAL_8E1' was not declared in this scope

Any idea how to solve this?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Feb 17, 2014, 09:30 pm
The libraries compile in the arduino V1.05 environment. The arduino environment supporting the Due and Mega (i think) does not support the library, more specifically the hardwareSerial library does not support parity. You will need to edit the cpp file and remove the parity options. This is easy.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Paulinho19 on Feb 17, 2014, 09:47 pm
Hum...

I removed the "byteFormat"

now it complies but I get the following warning:

SimpleModbusMaster\SimpleModbusMaster.cpp.o: In function `modbus_configure(HardwareSerial*, long, unsigned int, unsigned int, unsigned char, unsigned char, Packet*, unsigned int)':
C:\Users\Paulo\Documents\Arduino\libraries\SimpleModbusMaster/SimpleModbusMaster.cpp:431: warning: undefined reference to `HardwareSerial::begin(unsigned long)'

Did I miss something?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Feb 17, 2014, 10:12 pm
Try casting:

Code: [Select]

(*ModbusPort).begin((unsigned long)baud);

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: bsahilu on Feb 22, 2014, 12:30 am
JuanB,

I'd like to report that my project using your Modbus method works flawlessly !  I implemented the suggestions you stated and it made more sense.  And I can read and send data reliably.

Unfortunately, Now, I'm forced to abandon the ModBus approach.  The need to have auto-slave address detection is becoming a driving factor.  My search for that topic returns convoluted schemes that just sound ridiculously complicated and people are just utterly pessimistic regarding collisions. I get it, there is no (need for) collision detection when you have only ONE master.

Here's a brief description of the re-direction on the project scope.  If I have 100+ (or more) devices that are NOT physically accessible (no direct or pre-deployment programming of the address) AND they must be loaded with identical firmware, how do I access them to automatically detect and change their ID's respectively.  I do however, have a unique serial provided by a physical IC on the board of each device.  I want a means for all to be fired up and each to broadcast their unique serial and have a central unit provide/assign addresses.

I'm looking at CAN bus.  Any suggestions? In my search it seems like that's possible.  Leads would greatly be appreciated.

Thanks again!

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Feb 24, 2014, 07:15 am
Hi bsahilu,

I'm glad you got the lib to work!

A multimaster approach is always going to be difficult because of collision detection and/or collision avoidance schemes you need to implement. CAN is perfect for this since it is, in it self, a message base protocol based on a differential multi input AND gate concept. This is a however a simplification of it.

However, in my experience, the multimaster principal is not often used in the industry since CAN can also do master/slave based communication using the RTR (Remote transmission requests). CANOpen is a successful implementation of this. A master/slave concept allows easy communication direction control which is ,by its nature, very deterministic. I.e. You can be sure that a slave will be requested in X amount of time.

The multimaster concept is not so much deterministic as it is priority based. A slave with a low priority (a high value address) may not be requested for quite some time on a large bus.

In my line of work determinism is much more important.

But, your question is two fold. For communication to work a device needs to have some sort of id. This is true for all communication protocols.

Id detection is not the same as multimaster protocol and in my mind you should not need multimaster since each device already has a unique serial id. Since A master is in control of communication direction you will only need to implement  "id scan code". This is not trivial as you will maybe have to deal with timeouts and collisions at first. However it is definitely not impossible as it has nothing to do with multiple masters on the bus line. Onewire is such a protocol.

Can you not DIP switch assign each device with a unique id. Since modbus allows for communication to 255 slaves an 8 selectable DIP switch will set the address. If all the slaves contain the exact same information then the request packet will only differ by id. On boot up, sequence through 1 - 255 to establish if the slave is there, if not the retry count will reached and that slave will not be polled, speeding up communication. As it is the library can already do this but you will need to assign id's. Maybe you could make the modbus part of your controller as an add-on. This add-on will contain the microcontroller, 8 select-able DIP switches and the driver ic that you can interface to the controller. Each controller can then be married to such a modbus add-on with a unique id.

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: bsahilu on Feb 24, 2014, 09:03 am
JuanB,

Thank you again for taking the time to respond.  I agree that ultimately the setup I'm aiming for is in fact a SINGLE master MULTI-slave relationship. 

Unfortunately, DIP switches are not an option.  Firstly, the overall foot-print of the final board will not have room for a DIP.   And secondly, due to the nature of how these units will be physically mounted, there will NOT be any access to them to manually set a physical address by way of a DIP switch. 

All 100+ units will be connected at the same time (the wiring and installation is done by an outside contractor), and the controller/master-node would have to assign each slave a node address.  Essentially like a DHCP server. In fact, I was thinking of going that route: TCP/IP stack with a custom controller board that would incorporate an internal DHCP server/router. It might be a bit over-kill....

The ability for auto configuration is A MUST. 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Feb 24, 2014, 10:20 am
Do you have a list of the physical IC's serial numbers or is it a random number from a manufacturer?

The TCP option is probably a bit overkill but will solve your predicament. At least its a standard, from connectors to cabling to protocol.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: bsahilu on Feb 24, 2014, 04:27 pm
JuanB,

It will be a random serial IC.  And I have to view it from a perspective where I have NO prior knowledge of how it's setup...meaning: I have to treat each node as a black-box.

Yes, I'm also thinking the TCP option might be justified to say it's 'future-proof.'


Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: jocker99 on Apr 08, 2014, 04:01 pm
Hi to all, i am a newbie for modbus protocol and i want use it for read data from ducati energia smart piu' (it's a enrgy monitoring)
i want use a arduino uno and a max485 chip,
now i use a SimpleModbusMaster version 11,  and i write this:
Code: [Select]

enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

packetPointer packet1 = &packets[PACKET1];
void setup()
{
// 0x13 is the address of data, 2 is the word, the  word i 16 bit, this value i read from manual of Ducati Energia   
modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0x13, 2, readRegs);
modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
}

void loop()
{
  modbus_update();

lcd.print("requests:");
lcd.print(packet1->requests);
lcd.print("successful_requests: "); 
lcd.print(packet1->successful_requests);
lcd.print("failed_requests: "); 
lcd.print(packet1->failed_requests); 
lcd.print("exception_errors: "); 
lcd.print(packet1->exception_errors);
lcd.print("Active energy: "); 
lcd.print(readRegs[0]);
   delay(2000);
}

but don't work and i have this result
requests:   9
successful_requests: 0 
failed_requests: 10 
exception_errors:0
Active energy:0 

  i don't know where is the problem,  can you help me?
Best reagrds
J.


Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Apr 30, 2014, 03:33 pm
Hi jocker99,

Can you mail me your sketch and the modbus manual for your device?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: chzeinar on May 07, 2014, 12:09 pm
Hi Juan!

I read this thread and I am very impressed by your work. Fortunately I encountered the problem of "the other user" quite a long time ago with a mega1280-project using ModbusMaster library.

Now I want to shift to the due and the ModbusMaster is no longer working. I want to use auto-TXRX-enable switching to save IO-Pins.
It seems as this should be working with your library but i cannot find the correct intialisation without using the TxEnablePin:

<CODE>
  modbus_configure(&Serial, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
<\CODE>

(1) Could you be so nice and tell me, what I have to write instead?

(2) Is it necessary to change the library to use the due or is ist sufficient to write SERIAL_8N1?

Thank you for your answer!!

Greetings from Vienna, Austria

Christian
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: dvj215 on May 10, 2014, 11:36 am
Hi, I am using the Arduino due board & trying to compile the code but getting error message as under,

Arduino: 1.5.6-r2 (Windows 8), Board: "Arduino Due (Programming Port)"

Using library SimpleModbusMasterV10 in folder: C:\Users\admin\Documents\Arduino\libraries\SimpleModbusMasterV10 (legacy)



D:\Aurdino\Software\arduino-1.5.6-r2/hardware/tools/g++_arm_none_eabi/bin/arm-none-eabi-g++ -c -g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=156 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM -D__SAM3X8E__ -mthumb -DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON -DUSB_MANUFACTURER="Unknown" -DUSB_PRODUCT="Arduino Due" -ID:\Aurdino\Software\arduino-1.5.6-r2\hardware\arduino\sam\system/libsam -ID:\Aurdino\Software\arduino-1.5.6-r2\hardware\arduino\sam\system/CMSIS/CMSIS/Include/ -ID:\Aurdino\Software\arduino-1.5.6-r2\hardware\arduino\sam\system/CMSIS/Device/ATMEL/ -ID:\Aurdino\Software\arduino-1.5.6-r2\hardware\arduino\sam\cores\arduino -ID:\Aurdino\Software\arduino-1.5.6-r2\hardware\arduino\sam\variants\arduino_due_x -IC:\Users\admin\Documents\Arduino\libraries\SimpleModbusMasterV10 C:\Users\admin\AppData\Local\Temp\build3646064460777858058.tmp\SimpleModbusMasterArduino.cpp -o C:\Users\admin\AppData\Local\Temp\build3646064460777858058.tmp\SimpleModbusMasterArduino.cpp.o

SimpleModbusMasterArduino.ino: In function 'void setup()':
SimpleModbusMasterArduino.ino:171: error: 'SERIAL_8N2' was not declared in this scope
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on May 10, 2014, 12:49 pm
dv215, you really need to read this thread before posting this questiong you have.
I am sure if you have read it you would have found your answer.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on May 10, 2014, 01:15 pm
JuanB,
Just want to let you know I appreciate your fine work on making this library available.
I am using the Eclipse IDE with the Arduino 1.5.2 toolchain.

I downloaded the version 9 of Modbus Slave and have it seemingly working fine on a Ether Mega 2560 board.
I edited out the serial parity sections for it to compile correctly under the 1.5.2 toolchain.

Since I'm on Mac OSX and Linux I wanted to test it, so I downloaded a GUI based Modbus master program which will only operate under Windows unfortunately, this one http://www.protoconvert.com/SoftwareTools/Modbus/ModbusMasterSimulator.aspx (http://www.protoconvert.com/SoftwareTools/Modbus/ModbusMasterSimulator.aspx)

So I ran that within VirtualBox which I have Windows XP and set up the COM port to be directed back to the USB port to which the Arduino Ether Mega (Freetronics) is connected to.
Well, blow me down, it works, albit with some time-outs  :D

I might even try making a small SCADA test using CitectSCADA I have on my XP image.
(My aim is to lessen my dependance expensive Allen Bradley Control/Compact Logix PLCs in my future projects, and to use start using Modbus with a mixture of Arduino based controllers together PLCs that can talk Modbus)

Next is to write some nice Python code to have my Cubieboard talk Modbus to serial1 on the Ether Mega.
Then the Cubieboard is my local server and link back to the outside world.

So, yes, your code works on Arduino Mega under 1.5.2 (Eclipse IDE), keep up the good work  :D
____
Paul (Tasmania)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: dvj215 on May 11, 2014, 04:37 am
Hi, Thanks for providing valuable information. Have checked the modbus master? I have downloaded the library https://github.com/4-20ma/ModbusMaster. I am using Arduino DUE board. And software 1.5.6-r2. While verifying the code got the message as under. I have add the MODBUS MASTER lib.

Arduino: 1.5.6-r2 (Windows 8), Board: "Arduino Due (Programming Port)"

Using library modbusmaster in folder: D:\Aurdino\Software\arduino-1.5.6-r2\libraries\modbusmaster (legacy)



D:\Aurdino\Software\arduino-1.5.6-r2/hardware/tools/g++_arm_none_eabi/bin/arm-none-eabi-g++ -c -g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=156 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM -D__SAM3X8E__ -mthumb -DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON -DUSB_MANUFACTURER="Unknown" -DUSB_PRODUCT="Arduino Due" -ID:\Aurdino\Software\arduino-1.5.6-r2\hardware\arduino\sam\system/libsam -ID:\Aurdino\Software\arduino-1.5.6-r2\hardware\arduino\sam\system/CMSIS/CMSIS/Include/ -ID:\Aurdino\Software\arduino-1.5.6-r2\hardware\arduino\sam\system/CMSIS/Device/ATMEL/ -ID:\Aurdino\Software\arduino-1.5.6-r2\hardware\arduino\sam\cores\arduino -ID:\Aurdino\Software\arduino-1.5.6-r2\hardware\arduino\sam\variants\arduino_due_x -ID:\Aurdino\Software\arduino-1.5.6-r2\libraries\modbusmaster C:\Users\admin\AppData\Local\Temp\build1812282103286227477.tmp\sketch_may10a.cpp -o C:\Users\admin\AppData\Local\Temp\build1812282103286227477.tmp\sketch_may10a.cpp.o

In file included from sketch_may10a.ino:2:
D:\Aurdino\Software\arduino-1.5.6-r2\libraries\modbusmaster/ModbusMaster.h:83: fatal error: util/crc16.h: No such file or directory
compilation terminated.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on May 12, 2014, 01:46 pm
Hi  rockwallaby,

I'm glad it all works!!

You might not know this but I have ported SimpleModbusMasterV10 (old version but stable) to the Processing environment to create my own SCADA system. https://code.google.com/p/processing-modbus/

There are two GUI libraries that make visual designing a breeze.
http://www.lagers.org.uk/g4p/
http://www.sojamo.de/libraries/controlP5/

I will in the near future port the latest stable Modbus masterV11 to Processing.

It works flawlessly at all baud rates.

What I did find is because of the latency involved with the FTDI driver interface with the OS and then again with the OS with the Java Virtual machine which again interfaces with the RXTX serial library results in some serious latency that manifests itself as timeouts when polling a slave. The modbus frame timing is almost always the culprit. To overcome this timing limitation the frame receive time is increased to around 20 to 30ms.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on May 12, 2014, 02:17 pm
Hi JuanB,
I had a quick look at your links, thanks for them, I will continue with my own SCADA based on HTML5 and as a web application.

My idea is that I will use a small Linux board such as a Cubieboard-2 I have and continue to develop a combination of C/C++, Node.JS and Python based server, using web sockets for reasonably fast next to real-time viewing, especially from remote sites.

You can get some idea of some of what I will do at this link http://paulalting.com/hydrosolar/hydrosolar.php (http://paulalting.com/hydrosolar/hydrosolar.php)
It is my own home based renewable ernergy system, a combination of micro-hydro and solar.

Still a lot of work ahead, but progress is being made each day toward the sort of SCADA and control systems I would like in my more industrial systems.
____
Paul
Title: Please Help me with ModBus RTU Master on DUE
Post by: chzeinar on May 16, 2014, 07:11 pm
Hi JuanB, hi Modbus-experts,

Thank you for your efforts to make Arduino modbus-capable!!

I am trying to get my due and your SimpleModbusMaster-library (V10) to work together.

I commented out the "byteFormat"-Statements in

SimpleModbusmaster.cpp
Code: [Select]
   
void modbus_configure(HardwareSerial* SerialPort,
long baud,
//unsigned char byteFormat,
unsigned int _timeout,
unsigned int _polling,
unsigned char _retry_count,
unsigned char _TxEnablePin,
Packet* _packets,
unsigned int _total_no_of_packets)
{
//...
}


in SimpleModbusMaster.h
Code: [Select]

void modbus_configure(HardwareSerial* SerialPort,
long baud,
                                                                                       //unsigned char byteFormat,
unsigned int _timeout,
unsigned int _polling,
unsigned char _retry_count,
unsigned char _TxEnablePin,
Packet* _packets,
unsigned int _total_no_of_packets);


and in the example I changed modbus_configure in void setup()
Code: [Select]

modbus_configure(&Serial, baud, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);


So far I think I have done all that was described at page 2 of this thread.

Unfortunately I get the following error when compiling (1.5.6r2 on Xubuntu 12.04, Arduino running as sudo):

SimpleModbusMasterArduino.ino: In function 'void setup()':
SimpleModbusMasterArduino:171: error: invalid conversion from 'Packet*' to 'unsigned char'
SimpleModbusMasterArduino:171: error: cannot convert '<anonymous enum>' to 'Packet*' for argument '8' to 'void modbus_configure(HardwareSerial*, long int, unsigned char, unsigned int, unsigned int, unsigned char, unsigned char, Packet*, unsigned int)'


Can you tell me what I am doing wrong?

Is it possible NOT to write to the TxEnablePin, as I am using auto-enable and want to save IO-pins?


Thank you very much for your time

Christian
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: dvj215 on May 17, 2014, 05:52 am
Hi,
I got some information from JAKOB, as under, try & update everyone.

On the link below is a .zip file containing Master and Slave library for IDE 1.5.x. Down below is also link to the another .zip file containing two examples. The example in the library folder does not work.

Download this: https://dl.dropboxusercontent.com/u/16262939/V8.rar
Examples: https://dl.dropboxusercontent.com/u/16262939/Examples.rar

If the library doesn't want to compile or the examples don't work, let me know. As far as I'm concerned they should work NP.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: chzeinar on May 18, 2014, 12:15 am
Thank you!

I have no due here right now but it compiles without errors :)

Greetings from Vienna!!!

Christian
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on May 18, 2014, 01:37 am
dvj215,
The only difference between the example in the library and the example in that 'Examples.rar' file is what has been discussed at quite some length here already, namley, the removal of the serial parity section in the instance configuration.

Like I said earlier, it would be worth your while to read this whole thread.
Then you will know and understand better what you needed to do.

So, again, for the sake of clarity, the original line to configure the instance in the SimpleModbusSlave code:
Code: [Select]
modbus_configure(9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);
And the modified line:
Code: [Select]
modbus_configure(9600, 1, 2, HOLDING_REGS_SIZE, holdingRegs);

That is the only difference between the two examples, look for yourself.
Of course you will need to make the appropriate changes in the library code as well, again, as has been discussed here in this thread quite clearly.

I am thinking people may only become confused with your post, saying 'The example in the library folder does not work' and with offering another place to download from.

This will be more so as you don't clearly state under what conditions you are using this library, for example, what version of the Arduino IDE are you using and for which board.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: ee4lif3 on May 20, 2014, 08:12 pm
Hi everyone, I am trying to use the simple modbus library and am not able to get it to work, completely. I am using arduino unos with the MAX487 transceiver. I have quadruple checked that the circuity matches that of the example on the simple modbus website. Now here's my problem, I get communication on the first data transaction (the master requests and the slave responds) and my data comes through but after the first request the slave fails to respond. I have added an LED to the txEnable of the master and slave to see when data is transmitted and the master sends a packet, the slave responds, then the master sends another packet but the slave has no response. Has anyone encountered this behavior? And does anyone have an idea as to how to fix it? I have even tried implementing the delays others have said caused their arduinos to communicate, but without success. Any help would be greatly appreciated, Thanks! (oh and the code I am using is simply the examples give with the library)

EDIT: Well I figured out the issue, I was trying to serially read the data and since the uno only has one serial port, it was breaking the connection. I have confirmed the values on an LCD display, so the library definitely works. Thanks for the great library!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: chzeinar on May 21, 2014, 10:02 pm
Code: [Select]
(Sorry, this posting comes as code, I cannot get rid of the code statement)

  Hi you!

I had a very similar problem today, there is a timeout after several failed requests, so it works a couple of time an then shuts down. Set

packets->continue=1

in your loop().
This does not explain the failed requests but helps to keep the communication going.

I have mysterious failed requests but using this quick&dirty solution you can narrow down the problem.

Greetings from Vienna

PS:  I managed to modify V11 to make it usable with the due and with or without TxEnablePin.
     If anybody wants more info I will publish it here after some tests
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: pridhvi on May 26, 2014, 09:58 am
I am Using the following code and I am getting the errors..................Please help me


code-  https://github.com/angeloc/simplemodbusng/blob/master/SimpleModbusMaster/SimpleModbusMaster.cpp

errors are:

sketch_may26a.ino: In function 'void constructPacket()':
sketch_may26a:100: error: 'struct Packet' has no member named 'no_of_registers'
sketch_may26a:101: error: 'struct Packet' has no member named 'no_of_registers'
sketch_may26a:108: error: 'struct Packet' has no member named 'no_of_registers'
sketch_may26a:113: error: 'struct Packet' has no member named 'no_of_registers'
sketch_may26a.ino: In function 'void checkResponse()':
sketch_may26a:159: error: 'struct Packet' has no member named 'illegal_function'
sketch_may26a:160: error: 'struct Packet' has no member named 'illegal_data_address'
sketch_may26a:161: error: 'struct Packet' has no member named 'illegal_data_value'
sketch_may26a:162: error: 'struct Packet' has no member named 'misc_exceptions'
sketch_may26a:179: error: 'struct Packet' has no member named 'incorrect_function_returned'
sketch_may26a:187: error: 'struct Packet' has no member named 'incorrect_id_returned'
sketch_may26a.ino: In function 'void check_packet_status()':
sketch_may26a:219: error: 'struct Packet' has no member named 'timeout'
sketch_may26a:236: error: 'struct Packet' has no member named 'total_errors'
sketch_may26a:236: error: 'struct Packet' has no member named 'timeout'
sketch_may26a:237: error: 'struct Packet' has no member named 'incorrect_id_returned'
sketch_may26a:238: error: 'struct Packet' has no member named 'incorrect_function_returned'
sketch_may26a:239: error: 'struct Packet' has no member named 'incorrect_bytes_returned'
sketch_may26a:240: error: 'struct Packet' has no member named 'checksum_failed'
sketch_may26a:241: error: 'struct Packet' has no member named 'buffer_errors'
sketch_may26a:242: error: 'struct Packet' has no member named 'illegal_function'
sketch_may26a:243: error: 'struct Packet' has no member named 'illegal_data_address'
sketch_may26a:244: error: 'struct Packet' has no member named 'illegal_data_value'
sketch_may26a.ino: In function 'void check_F3_data(unsigned char)':
sketch_may26a:250: error: 'struct Packet' has no member named 'no_of_registers'
sketch_may26a:271: error: 'struct Packet' has no member named 'checksum_failed'
sketch_may26a:280: error: 'struct Packet' has no member named 'incorrect_bytes_returned'
sketch_may26a.ino: In function 'void check_F16_data()':
sketch_may26a:295: error: 'struct Packet' has no member named 'no_of_registers'
sketch_may26a:300: error: 'struct Packet' has no member named 'checksum_failed'
sketch_may26a.ino: In function 'unsigned char getData()':
sketch_may26a:343: error: 'struct Packet' has no member named 'buffer_errors'


Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on May 26, 2014, 11:47 am
What Arduino IDE are you using? Probably IDE 1.5.x?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: pridhvi on May 26, 2014, 12:10 pm
I am using Arduino Uno
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: pridhvi on May 27, 2014, 08:27 am
Hello,

I am working on modbus using rs485 serial interface. I wanted to communicate master and slave on the basis of reply only if query posted. Can any one suggest working libraries .....
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on May 28, 2014, 02:35 pm
Hi pridhvi,

This is exactly Modbus. Use the SimpleModbusMaster and SimpleModbusSlave libraries from my drive https://drive.google.com/folderview?id=0B0B286tJkafVSENVcU1RQVBfSzg&usp=drive_web
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: dvj215 on May 29, 2014, 06:56 am
Tried to compile with Arduino board DUE. get error message,  as under, (please check with due board)

Arduino: 1.5.6-r2 (Windows 8), Board: "Arduino Due (Programming Port)"

D:\Aurdino\Software-1\arduino-1.5.6-r2/hardware/tools/g++_arm_none_eabi/bin/arm-none-eabi-g++ -c -g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=156 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM -D__SAM3X8E__ -mthumb -DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON -DUSB_MANUFACTURER="Unknown" -DUSB_PRODUCT="Arduino Due" -ID:\Aurdino\Software-1\arduino-1.5.6-r2\hardware\arduino\sam\system/libsam -ID:\Aurdino\Software-1\arduino-1.5.6-r2\hardware\arduino\sam\system/CMSIS/CMSIS/Include/ -ID:\Aurdino\Software-1\arduino-1.5.6-r2\hardware\arduino\sam\system/CMSIS/Device/ATMEL/ -ID:\Aurdino\Software-1\arduino-1.5.6-r2\hardware\arduino\sam\cores\arduino -ID:\Aurdino\Software-1\arduino-1.5.6-r2\hardware\arduino\sam\variants\arduino_due_x C:\Users\admin\AppData\Local\Temp\build2693646653201034910.tmp\ModbusMasterV4.cpp -o C:\Users\admin\AppData\Local\Temp\build2693646653201034910.tmp\ModbusMasterV4.cpp.o

since error message id more than 9500 characters only showed few lines. You can compile & check.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: pridhvi on Jun 06, 2014, 07:19 am
Hello,
I am working  on modbus for serial communication using RS485 interface. Can anyone suggest working libraries. I want to use arduino board as slave and modbus simulator as master. Can anyone help with providing working libraries.


Cheers!!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: dvj215 on Jun 06, 2014, 01:25 pm
Attached program I have tested with my Arduino Due board. The DUE is working as slave & installed MODSCAN software into PC. PC will work as MASTER. I am able to communicate on MODBUS RTU protocol with DUE board.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: chzeinar on Jun 15, 2014, 12:34 pm
Hi Community!

I try to establish a communication with Arduino as modbusmaster and a HMI as slave (ID=1) using RS485.
I just want to set a holding register (address=1) and read a coil status (address=0).

I (rather q&d)  modified SimpleModbusMaster.c and SimpleModbusMaster.h (V11) slightly to use it on the Due and to be able to switch off the TxEnablePin:

SimpleModbusMaster.h:
Code: [Select]

#ifndef SIMPLE_MODBUS_MASTER_H
#define SIMPLE_MODBUS_MASTER_H

// SimpleModbusMasterV11mod

/*
   This lib was modified by Christian Zeinar, 2014-05-22 to make it usable with
   the Arduino Due, just Enter fot byteFormat *ANY* char, e.g. 'n'
   
   If you do not want to use the TxEnable Pin just write any PinNumber >=99

  ....nothing else was changed



SimpleModbusMaster.c:
Code: [Select]

/*modbus_configure was slightly changed*/
void modbus_configure(HardwareSerial* SerialPort,
long baud,
unsigned char byteFormat,
unsigned int _timeout,
unsigned int _polling,
unsigned char _retry_count,
unsigned char _TxEnablePin,
Packet* _packets,
unsigned int _total_no_of_packets)
{
// Modbus states that a baud rate higher than 19200 must use a fixed 750 us
  // for inter character time out and 1.75 ms for a frame delay for baud rates
  // below 19200 the timing is more critical and has to be calculated.
  // E.g. 9600 baud in a 11 bit packet is 9600/11 = 872 characters per second
  // In milliseconds this will be 872 characters per 1000ms. So for 1 character
  // 1000ms/872 characters is 1.14583ms per character and finally modbus states
  // an inter-character must be 1.5T or 1.5 times longer than a character. Thus
  // 1.5T = 1.14583ms * 1.5 = 1.71875ms. A frame delay is 3.5T.
// Thus the formula is T1.5(us) = (1000ms * 1000(us) * 1.5 * 11bits)/baud
// 1000ms * 1000(us) * 1.5 * 11bits = 16500000 can be calculated as a constant

if (baud > 19200)
T1_5 = 750;
else
T1_5 = 16500000/baud; // 1T * 1.5 = T1.5

// initialize
state = IDLE;
  timeout = _timeout;
  polling = _polling;
retry_count = _retry_count;
TxEnablePin = _TxEnablePin;
total_no_of_packets = _total_no_of_packets;
packetArray = _packets;

ModbusPort = SerialPort;

/********** changes ***********/
#if ARDUINO>=150  //look if IDE >= V.1.5.x
        (*ModbusPort).begin(baud);
    #else
        (*ModbusPort).begin(baud, byteFormat);
    #endif

if (TxEnablePin <99)  //to disable TxEnablePin
{
pinMode(TxEnablePin, OUTPUT);
digitalWrite(TxEnablePin, LOW);
}
/**** end of changes ****/
}


which compiles without errors.

To communicate with my HMI (slave-id=1) I wrote:
Code: [Select]

  // read 1 register starting at address 0 
  modbus_construct(packet1, 1, READ_COIL_STATUS, 0, 1, coilRegs)
  // write 1 register starting at address 1 
  modbus_construct(packet2, 1, PRESET_MULTIPLE_REGISTERS, 1, 1, writeRegs);


To detect communication problems I print successfull and failed requests.
Whether or not the HMI is connected I get only successfull requests with packet2 and only failed requests with packet1.

If I change the slave-id to 0, I get only successfull requests with both packets, again, whether or not the HMI is or anything else connected.

As I understand ist, without a Modbus network there should be no successfull requests, or do I misunderstand something?

I connected the Arduino (via SP3072) to a modbus slave simulator  (Modbus PLC Simulator, free) and get the correct signals with the holding register, not with the coils.
To make things more funny, when the modbus slave simulator is connected, I get the right values on PC, but the library only reports failed requests, when deconnecting, the failed request stay constant again and the successfull requests increase.

The problem ist, my HMI does not do anything, it should at least (succsessfull requests) change the strings according to the holding register.

I struggled a couple of nights an I must confess I have no idea what goes wrong. I woul appreciate any help very much!!

Thank you for your time an ideas!!

Greetings from Vienna, Christian
PS:
I checked and rechecked the HMI with Chipkit Modbus scanner and the RMMS Modbusmaster tool (both free software) and a FTDI usb2rs485 cable (hardware).
If I print a button on the HMI I get Coil #0=1 (on PC), if I set the register 400002 to 0x00 (on PC) I get a string on the HMI and another string if I set it to 0x01. So far the HMI works.

I checked my hardware (UART<->RS485) with a simple loopback:
Serial2 and Serial3 have a SP3072 and I can read an write from one RS485 interface to the other. The same hardware worked perfect with Arduino Mega and ModbusMaster-library. So I am quite sure there is no HW-problem
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jun 16, 2014, 04:23 pm
Hi chzeinar,

I have uploaded a master library that compiles under V1.5.6. It still implements TxRxEnable pin toggle but you don't have to use it. If you want to get rid of it just comment it out lines 433, 434 and 491. I don't know if the library you have does that.
Any how, that should not affect the communication if you are not using it. I have added a delay in the sendPacket() function as some users had problems with the DUE core UART library. This will stop the frame from being truncated.

Remember an id of 0 is a broadcasting request for functions 15 and 16. So the master does not expect a response. SMM will automatically increment the successful request counter.

Start out with writing one register to the HMI using only one packet and see if it is displayed.

Please bear in mind that I have not tested function 1,2 and 15 as much as I have tested 3,4 & 16 as most equipment out there usually implements functions 3,4 and 16.

If you need any other assistance send me the details of the HMI and your sketch,
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: ArturoMesa on Jun 17, 2014, 03:42 pm

Hi all, are doing a great job!!

We are testing with SimpleModusSlaveV8 library and are not able to activate outputs in Arduino, I explained in detail that happens to us:

What steps will reproduces the problem?

1. SimpleModbusSlaveV8 library with Arduino UNO.

Two. Conexion CI MAX485.

Three. PCs with XP operating system.

April. Windmill Software used for testing, Cas Modbus Scanner
ModBusPoll ...

May. Arduino program is loaded in the example of the library, SimpleModbusSlaveExample.

6. Plot script is generated to activate the arduino output 13 with the function ... 16

0A 10 00 0D 00 01 02 00 01 CRC

7. Arduino response occurs with the following frame

00 0A 90 02 BC 03 00 and the output is not active

8. Works perfectly with analog and digital readouts, function 3.

What is the expected output? What do you see instead?

The expected value would have to be the first 6 bytes of the frame costs, 0A 10 00 0D 00 01, and change the output to arduino.

The value obtained is 00 0A 90 02 BC 03 00  and the output does not change state.


What version of the product are you using? On what operating system?

SimpleModbusSlaveV8 in arduino IDE 1.0.5-R2 and Windows PC with XP operating system.


Please provide any additional information below.

Know the origin of the problem, all readings are correct but we can not change the status of the outputs.


Thank you very much for everything!!

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jun 18, 2014, 09:20 am
Hi ArturoMesa,

Please use SMSv9. This library has been tested many, many times on the Duemilanove using V1.05r2.

I have attached a test sketch so that you can read an adc value from address 0 using F3 and toggle an led by using F16 to write a 1 or 0 to address 1.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: chzeinar on Jun 21, 2014, 12:53 am
Good evening Juan, good evening community!!

Thank you Juan for your time and patience, SMM V12 DUE works perfect.
I have communication with PC and with my HMI, successful requests only.

I thought the unability of the Due not to speak modbus were its greatest flaw, but you repaired it!!

Greetings from Vienna, Austria, Europe

Christian
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Suyog on Jun 25, 2014, 05:20 pm
Greetings from India.
First of all congratulations to JuanB for making such wonderful library.  :D
Coming to the problem. I am reading temperature data from a PID controller. Everything is working almost fine. But there is minor glitch. After every two readings, some garbage is prefixed to third reading.  Next two readings are again ok... so on and on
Code: [Select]
#include <SimpleModbusMaster.h>
#define baud 9600
#define timeout 1000
#define polling 200
#define retry_count 10
#define TxEnablePin 2
float x;

enum
{
  PACKET1,
  PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
unsigned int readRegs[1];


void setup()
{
     Serial.begin(9600);
     modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 138, 1, readRegs);
     modbus_configure(&Serial, baud, SERIAL_8O1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
  }

void loop()
{
  modbus_update();
  x = readRegs[0];
  Serial.print(x/10);
  Serial.print("\n");
  delay (2000);
}


Any opinions on what might be causing this problem?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jun 27, 2014, 08:58 am
Hi Suyog,

First you need to fix your dangling pointer by removing the unused packet 2.

You cannot use the Serial object explicitly once you have assigned it to the Modbus state machine object. You are interfering with the reception and transmission of packages. Use Serial1 or whatever but it must be a different Serial object if you want to call print.

What arduino board are you using? I'm guessing a Leo, UNO or Duemilanove since you are using parity options.

If you are using an UNO or Duemilanove you are out of luck unless you use the SoftwareSerial lib.

If however you have a Leo than use Serial1 for Modbus and Serial for everything else as this is USB.

lastly try not to use long delays in your program as it interferes with the state machine timing. Rather use millis(). See blink without delay http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay (http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Suyog on Jun 27, 2014, 06:05 pm
Hi
Thanks for reply
1) I am using Mega 2560.

2) Yes indeed it was serial issue.  Solution was that I used Serial1 for MAX485 and Serial for usb communication  :) (really dumb of me)
Code: [Select]
modbus_configure(&Serial1, baud, SERIAL_8O1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);

3) packet 2 was is removed. But keeping it didn't created any issue.

one more question
Can you tell how to read values from multiple slaves? first will be modbus_construct() for each slave, what should be in readRegs field for each slave? and in main loop when we call modbus_update(); where is data of other slaves?

Thanks

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jun 27, 2014, 08:28 pm
The data received from the various slaves are stored in the register array you assigned in modbus_construct(). Use different regs arrays for different packets..easy..

modbus_update() is only called to update the finite state machine. You can call it as many times as you like to update the FSM more frequently.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: ebs-soft on Jul 04, 2014, 09:47 pm
Nice Modbus Lib .... you wrote somewhere that you have ported the Lib to a Atmega64?
This MC is used in one of my projects which should be changed from a small slave function to a ModBus_Master.
Is there and Download available from this port  or maybe any Hints?
regards
Eric 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sbeghers on Jul 06, 2014, 01:51 pm
Hello JuanB,
i want to read Eastron SDM320M multimeter registers with Arduino Mega 2560 (next step is to use with Arduino Yun).
I'm using MAX485 chip with schema in attached.
Voltange out of A-B modbus is more then 200mV, so i attend to receive data.
I'm using SimpleModbusMaster V10 and i attached manual of Eastron multimeter.
It's default comunication parameters are:
ID: 1
Protocol: MOUBUS RTU with 16 bit CRC
Baud Rate: 9600
Parity: EVEN
Stop Bits: 1
Data Bits: 8
For first step now i want to read Voltage register (30001)

Sketch is:

#include <SimpleModbusMaster.h>
#define baud 9600
#define timeout 1000
#define polling 200
#define retry_count 10
#define TxEnablePin 2
#define LED 9

enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS
};

Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
unsigned int readRegs[2];

void setup()
{
modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 30007, 2, readRegs);
modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
  Serial.print("requests:");
  Serial.print(packet1->requests);
  Serial.println("");
  Serial.print("successful_requests: "); 
  Serial.print(packet1->successful_requests);
  Serial.println("");
  Serial.print("failed_requests: "); 
  Serial.print(packet1->failed_requests); 
  Serial.println("");
  Serial.print("R1:");
  Serial.print(readRegs[0]);
  Serial.println("");
  Serial.print("R2:");
  Serial.print(readRegs[1]);
  Serial.println("");
  Serial.print(" ");
  Serial.println(""); 
  delay(2000);
}

Result of monitor is in attached
Where am I wrong?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Jul 06, 2014, 03:06 pm
On which register address is voltage information? 30001 or 30007. In description you have voltage register at 30001 and in sketch you are reading from 30007.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sbeghers on Jul 06, 2014, 05:39 pm
Volatge is in 30001, Current is in 30007. (you can read in manual)
I'm sorry my post.... i checked to read before voltage then current.
but i haven't difference of respond
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Jul 06, 2014, 10:08 pm
I believe you are sending wrong modbus request. In the manual on page 8 you can see that these registers for voltage and current are accessable via function 4 - READ_INPUT_REGISTERS and not via function 3 - READ_HOLDING_REGISTERS.
Regards,
Jakob
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 07, 2014, 11:37 am
Hi sbeghers,

I cant find the manual online... anyhow..

When the manufacturer states an explicit address of 30001 or similar than the function is implicitly indicated. In this case function 4 which is address space 3xxxx.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: cmcgonag on Jul 08, 2014, 03:00 pm
I was told to post my question in this thread. I already created another thread with the information here:

http://forum.arduino.cc/index.php?topic=253467.0

It is weird to me that I am seeing ZERO TX/RX lights light up. When I load the master code I see them light up. I would expect a flash on the RX when I poll the shield. Also curious if something could be conflicting with the TX/RX pins....also do I need to set a pull up resistor to filter out noise on the circuit? The schematic for the shield seems to show one is already in place.


I am using an UNO. I think I have the latest and greatest arduino software installed. Not at home to check currently.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sbeghers on Jul 09, 2014, 09:49 am
Hi JuanB,
I chanced in 4 - READ_INPUT_REGISTERS:

modbus_construct(packet1, 1, READ_INPUT_REGISTERS, 30001, 2, readRegs);

But I receive this data.
I becoming crazy
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 09, 2014, 12:43 pm
Hi sbeghers,

You cannot use Serial once assigned to the modbus state machine. You will have to use another serial object when using Serial.print() etc. Since you are using a Mega you have more than one port already so use Serial1 for modbus and Serial as is since its connected to the PC. Because of the state machine and modbus timing you cannot use long delays. 100ms is usually maximum. Use millis() for rudimentary multitasking.

Also since the explicit address implicitly indicates the function to be used you cannot use it in the address space. Once the function is selected, in this case function 4, you only need to index your slaves address space. Using 30001 as an example make sure of the starting index it could be 0 or 1.

So to recap the modbus information will look like this:
Code: [Select]

modbus_construct(packet1, 1, READ_INPUT_REGISTERS, 0, 2, readRegs);
modbus_configure(&Serial1, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 09, 2014, 01:03 pm
Hi Colin,
I had a look at the shield and it doesn't use a pull up on the Rx line. It also implement TxRxEnable automatically using Q1 on the Tx line so you must not connect the TxRxEnable pin to pin 2 & 3 as indicated on my sketch. It won't work if you do. Sometimes you don't need the 10k pullup on Rx.

What RS485 driver are you using on the PC side?

If you want to make sure of the comms between pc and the UNO just use the usb connection instead of the shield. It will work provided that you setup Qmodbus correctly.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: xKNGx on Jul 11, 2014, 06:16 pm
Hi JuanB

I read over the entire thread, very nice that you are so active on the forum!

Right now I have 2 Arduino UNO that I have connected through MAX487 chips.
The example LED program works. And I am able to send INT from slave to master and see on Serial Monitor.
The next step for me is to make a slave that I can connect to a Schneider Electric M238 PLC.
I believe I just have to set my PLC to read the correct slave ID and address (starting from zero?) See picture.

Will QModbus be helpful to test? Do I connect using USB or MAX487?

Thanks,
xKNGx
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 11, 2014, 08:26 pm
Hi xKNGx,

Thank you, I try to help where I can as I believe in open source..

Yip, make sure of the connections first. The A & B lines on the MAX487 (most manufacturers got it wrong) are incorrectly labeled A+ and B-. RS485 standard refers to A- and B+. The defacto standard these days are to use D+ and D- to avoid confusion. Just match the PLC + to the A+ of the driver and - to the B- of the ic. Use 680 ohm pull ups and pull downs and a 120 ohm termination resistor. Don't forget to use a 10k pull up on the Rx pin of the Arduino. I sometimes found that when the receive part of the driver ic is disabled the output, Ro, goes tristate (high impedance) and the Rx receive interrupt pin's known state on the atmega is not well defined which leads to false reception if there is noise or static around the pin. Also try to use a 100nF decoupling capacitor close to the driver ic's Vcc and GND pins. This will help with transient noise on the supply line feeding the driver and anything else that runs of the 5V. For ground loop safety connect a 100 ohm 5W resistor between the ground pin of the driver and the reference line going to the PLC's reference pin. This pin on the PLC is sometimes called SG, GND or REF. RS485 is a 3 wire topology not two wires. Connect your UNO's GND straight to the drivers ic's GND pin.

Make sure of the device ID matches the slaves ID.
The address space of the SimpleModbusSlave library is referenced to zero so no offset is required. E.g. address 0 is the ADC_VAL of the example sketch. To test that the PLC is indeed reading the correct data I would move a static value say 12345 into ADC_VAL and 24561 into PWM_VAL(comment out analoRead() and analogWrite() code) and than read these two registers and verify them using the PLC's supplied diagnostic software or display it on an HMI if you have one.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: cmcgonag on Jul 12, 2014, 12:00 am
Juan,

Thanks for the response. I use this modbus adapter:

http://www.usconverters.com/usb-rs485-converter-xs885

What changes should I make to your code to make it work with my shield? I would like to us a more supported library if possible. I would prefer to not have to modify the shield.

Looking at the shield schematic, I assumed that the 10K resistor that connected to VCC was a pull up resistor...it seems to trace back to the RX line.

I was able to get it working without the shield over USB.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sbeghers on Jul 13, 2014, 02:49 pm
Hi JuanB,
thank yuo very much for your support.
I attached for you power meter manual.
I change how you suggest to me.

What i want is to read Voltage: address register 30001, float format, page 8 in manual

The sketch is:

#include <SimpleModbusMaster.h>

/////////////////// Port information ///////////////////
#define baud 9600
#define timeout 100
#define polling 200 // the scan rate

// If the packets internal retry register matches
// the set retry count then communication is stopped
// on that packet. To re-enable the packet you must
// set the "connection" variable to true.
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

#define LED 9

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Create a packetPointer to access each packet
// individually. This is not required you can access
// the array explicitly. E.g. packets[PACKET1].id = 2;
// This does become tedious though...
packetPointer packet1 = &packets[PACKET1];


// Data read from the arduino slave will be stored in this array
// if the array is initialized to the packet.
unsigned int readRegs[2];

// Data to be written to the arduino slave
// unsigned int writeRegs[1];

void setup()
{
  // The modbus packet constructor function will initialize
  // the individual packet with the assigned parameters. You can always do this
  // explicitly by using struct pointers. The first parameter is the address of the
  // packet in question. It is effectively the "this" parameter in Java that points to
  // the address of the passed object. It has the following form:
  // modbus_construct(packet, id, function, address, data, register array)
 
  // For functions 1 & 2 data is the number of points
  // For functions 3, 4 & 16 data is the number of registers
  // For function 15 data is the number of coils
 
  // read 1 register starting at address 0 
  modbus_construct(packet1, 1, READ_INPUT_REGISTERS, 0, 2, readRegs);
 
  // write 1 register starting at address 1 
// modbus_construct(packet2, 1, PRESET_MULTIPLE_REGISTERS, 1, 1, writeRegs);
 
  */
  modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
 
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
 
  Serial.print("Regs[0]:");
  Serial.print(readRegs[0]);
  Serial.println("");
  Serial.print("Regs[1]:");
  Serial.print(readRegs[1]);
  Serial.println("");
  Serial.print(" ");
  Serial.println(""); 
  delay(1000);   

What Monitor show me is in attached.
I attend voltage like 215.5 Volt in this moment i write to you

If I change address register in 1 i receive data like now but non what i attend.




Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sbeghers on Jul 13, 2014, 02:55 pm
I forgot Monitor
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: joad on Jul 13, 2014, 03:12 pm
Hi, I'm a real newbie in Arduino so please excuse me if my question is obvious.
I have got everything to work (SMS V9) but I can not write "single-pointW, funktion 06 I must use function 16. Is this right, doesnt the lib support function 06 or have I done something wrong?

I use modscan32 for windows for testing and In the settings for the protocol I have to click the "force command 15 & 16 for single-point writes.

Edit:
I found the following, which is the answer to my question:
Quote
This code is for a Modbus slave implementing functions 3 and 16
function 3: Reads the binary contents of holding registers (4X references)
function 16: Presets values into a sequence of holding registers (4X references)


But is there any library that supports Preset Single Register (FC = 06)

Edit2:
I added the following for FC06:
It works! But I need help to ensure that error handling is correct.
Code: [Select]
  else if (function == 6)
 {
 broadcastFlag = 0;
 // Check if the recieved number of bytes matches...
 // id + function + (2 * address bytes) + (2 * value bytes)(2 * CRC bytes) = 8 bytes
 if (buffer == 8)
 {
 if (startingAddress < holdingRegsSize) // check exception 2 ILLEGAL DATA ADDRESS
 {
// if (maxData <= holdingRegsSize) // check exception 3 ILLEGAL DATA VALUE
// {
   address = 4; // start at the 8th byte in the frame
   regs[startingAddress] = ((frame[address] << 8) | frame[address + 1]);
 // only the first 6 bytes are used for CRC calculation
 crc16 = calculateCRC(6);
 frame[6] = crc16 >> 8; // split crc into 2 bytes
 frame[7] = crc16 & 0xFF;

// The normal response is an echo of the query, returned after the register contents have been written.
// the request + 2 crc bytes
 if (!broadcastFlag) // don't respond if it's a broadcast message
 sendPacket(8);
//}
//else
//  exceptionResponse(3); // exception 3 ILLEGAL DATA VALUE
 }
 else
 exceptionResponse(2); // exception 2 ILLEGAL DATA ADDRESS
 }


Thanks
/J
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 14, 2014, 12:01 pm
Hi Colin,

I am not a fan of tying the TxRxEnable pin to Q1 since this allows for some timing errors to sneak in. My sketch also depicts a similar schematic. It does work though but I have not tested it on long runs and in noisy environments. I suggest you make your own shield if possible with a tulip socket so you can use any driver you want. You can than have access to the ground line through a 100ohm resistor to the external reference and you can tie the TxRx enable lines to any digital pin of the atmega so that the software can toggle it for you. If you really want auto TxRx than take a look at the circuit cellar pdf at https://drive.google.com/drive/#folders/0B0B286tJkafVSENVcU1RQVBfSzg/0B0B286tJkafVM0tadDVkSy1QN00 it works flawlessly at any baud rate up to 115k.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 14, 2014, 01:09 pm
Hi sbeghers,

I have attached the sketch that you can test with on the Eastron SDM320M. It will read the line to neutral voltage on Serial and than print the float value on Serial1.

I think you said you were using a mega 2560...
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: cmcgonag on Jul 15, 2014, 03:56 am
Juan,

I would prefer to just see if I can get my shield to run. You said your sketch reflects this? I haven't been able to get the sketch to run with my shield. I will try again.

The link you sent gives me a server error.

Thanks again for helping me.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 15, 2014, 09:02 am
Hi Colin,

Do you have a multimeter at hand? Can you measure the supply voltage to the driver ic, pin 5 is ground and pin 8 is positive. I just want to verify if the supply voltage is 5V or 3.3V.

Connect the USB-RS485 converter D+(term 1) to X2-2 and D-(term 2) to X2-1. Bear in mind the converter produces 3.6V on its pins (between GND and D+). Since RS485 is a differential topology it actually does not matter what the voltage is across the differential inputs as long as it doesn't exceed -7V and 12V. The usual 5V allows for a greater noise margin on longer distances.

I also don't see any reference to pull ups or pull downs on the USB-RS485 converter. If it produces only 3.6V than try using values from 560 ohm to 680 ohm. Do not omit the pull ups and pull downs on these older tech ic's. The more modern ones from maxim are fail safe and do not require pull ups and pull downs. The pull up resistor should be tied from X2-2 to 5V Vcc and the pull down resistor should be tied from X2-1 to ground.

Connect a 10k pull up on the Rx line of the shield to 5V Vcc.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sbeghers on Jul 15, 2014, 09:25 am
Hi JuanB,
i'm using Mega2560.
I test your sketch (thank you very much for your time), but monitor show nothing.

To test power meter.
I had no doubt that the powermeter did not work well, so i connect it with usb-485 conveter with Simply Modbus Master 7.1
software. I contacted Eastron to know true communication settings.

These are:
baud: 9600
data bits: 8
stop bits: 1
parity: even
remove echo: yes (this is not written in the manual)

In attached you see the image of the software with the response of the powermeter.
It works well.

Some suggestions?

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 15, 2014, 09:55 am
Hi sbeghers,

Just a correction: Serial is used for pc communication and Serial1 for modbus communication.

This means you will need to connect pin18 (Tx) to DI, pin19 (Rx) to RO and pin 2 to RE/DE of the driver ic. Don't forget pull up and pull down resistors and the 10k pull up on Rx.

If all your connections are ok than and there is still no valid value than:

1. swap readRegs[1] and readRegs[0] around when shifting

still nothing.... change index values back

2. Change the starting address from 0 to 1 in modbus_construct()
still nothing...

3. swap readRegs[1] and readRegs[0] around when shifting

still nothing.... change index values back

4. I give up :(
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: cmcgonag on Jul 15, 2014, 06:17 pm
Juan, I have a MM; will check when I get home. When you say 560 to 680 ohm  are you referring to a termination resistor? I haven't been using a termination resistor or are you referring to the pull up for the D+ line?

For the RX line can I use the internal pull-ups in the arduino or should I just set it with an external?

Also, should  is it possible my TX/RX lines are set low or high from residual code?  Does it automatically remove all pull-ups when you recompile or no?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: cmcgonag on Jul 15, 2014, 06:19 pm
I also may buy a new shield.  This thing is ghetto. If I can understand what the issue is I will feel much better. I also am going to tie this thing to a modbus tcp/ip converter, may add problems down the line.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: CraigF on Jul 15, 2014, 11:41 pm
I recently got started with arduino and Modbus.

I'm working to connect a master and slave where a switch causes the sketches to react differently based on it's state.

I've gotten it to read the switch state,  but I can't seem to get the system to write to the slave a different state (on/off for an LED).

My biggest questions at the moment are....

What does the "A0" in...
Code: [Select]
writeRegs[0] = analogRead(A0);
come from and mean?  I think it might be important to my problem as at the moment regardless of the position of the switch they are both on, which makes me think it's wrong.

How, do I control where the PRESET_MULTIPLE_REGISTERS starts to adjust registers?

I got the example sketches to work, and have been altering them to bench-test for a future project.

Master
Code: [Select]
#include <SimpleModbusMaster.h>

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate

#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

#define LED 9

enum
{
  PACKET1,
  PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];


packetPointer packet1 = &packets[PACKET1];
packetPointer packet2 = &packets[PACKET2];

unsigned int readRegs[1];

// Data to be written to the arduino slave
unsigned int writeRegs[1];

void setup()
{
  /***************************************************************************
     MOVED TO LOOP() FOR UPDATING
  // read 1 register starting at address 0 
  //modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0, 1, readRegs);
 
  // write 1 register starting at address 1 
  modbus_construct(packet2, 1, PRESET_MULTIPLE_REGISTERS, 1, 1, writeRegs);
***********************************************************************************/

  modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
 
  pinMode(LED, OUTPUT);
  pinMode(12,INPUT);
  pinMode(13,INPUT);
}

//******************************************************************************************
void loop()
{
  modbus_update();
 
digitalWrite(LED, HIGH);

if (digitalRead(12 == HIGH))
{
//write 1 to register 0 on slave
   modbus_construct(packet1, 1, PRESET_MULTIPLE_REGISTERS, 0, 1, writeRegs);
}
else if (digitalRead(13 == HIGH))
{
  // write 1 to register 1 on slave
    modbus_construct(packet2, 1, PRESET_MULTIPLE_REGISTERS, 1, 1, writeRegs);
}
else
{
// write 0 to resgisters 0 and 1
   modbus_construct(packet1, 1, PRESET_MULTIPLE_REGISTERS, 0, 0, writeRegs);
   modbus_construct(packet2, 1, PRESET_MULTIPLE_REGISTERS, 1, 0, writeRegs);
}
}


Quick note that isn't in the code for the master, the LED pin goes to an ON/OFF/ON switch which diverts power to pin 12 and pin 13.

Slave
Code: [Select]
#include <SimpleModbusSlave.h>

#define  LEDONE 12
#define  LEDTWO 13



//////////////// registers of your slave ///////////////////
enum
{     
  LED1,     
  LED2,       
  HOLDING_REGS_SIZE
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array

//*******************************************************************************************************************************************************

void setup()
{
  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);

  modbus_update_comms(9600, SERIAL_8N2, 1);
 
  pinMode(LEDONE, OUTPUT);
  pinMode(LEDTWO, OUTPUT);
}

//******************************************************************************************************************************************************

void loop()
{
  modbus_update();
 
  holdingRegs[LED1] = analogRead(A0); // update data to be read by the master to adjust the PWM
 
  analogWrite(LEDONE, holdingRegs[LED1]>>2); // constrain adc value from the arduino master to 255
 
  holdingRegs[LED2] = analogRead(A0); // update data to be read by the master to adjust the PWM
 
  analogWrite(LEDTWO, holdingRegs[LED2]>>2); // constrain adc value from the arduino master to 255
}


Thanks for the help, in advance. I'll try to find a camera and get a shot of my setup incase that might need to change.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 16, 2014, 07:07 am
Hi Colin,

I'm sure you can get the shield to work all though fundamentally it is flawed. I.e. not industrial.

It is imperative to use 560 ohm pull up and pull down resistors with the older tech driver ic's. I always use 120 ohm termination resistors. Don't forget the external 10k pull up on the Rx pin.

Once you have wired everything test it again, i'm sure it will work.

Compiling the example sketch or any other sketch will re-compile all code in the sketch but not usually the library. If nothing has changed Arduino uses pre-compiled object code for the library.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 16, 2014, 07:41 am
Hi CraigF,

Welcome to Arduino!

Q1: A0 is the predefined constant for the analog channel 0. You can use only 0 - analogRead(0);

Q2: Use a packet with a different register array assigned to it if you want to write a different block of data to a slave.
Eg.
modbus_construct(packet3, 1, PRESET_MULTIPLE_REGISTERS, 1, 1, writeRegs2);

To write to a certain address of a slave you must alter the modbus_construct() function.
Eg.
modbus_construct(packet2, 1, PRESET_MULTIPLE_REGISTERS, 33, 1, writeRegs);

You cannot use modbus_construct() in loop. Only modbus_update() is used in loop. Use more packets and registers arrays to assign dynamic information.

pin 12 and 13 are not PWM outputs, pin 3, 5, 6, 9, 10 and 11 are. You can only use PWM outputs with analogWrite()
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: CraigF on Jul 16, 2014, 04:57 pm
Thanks for the quick response!

The A0 is not the problem. Good, one less thing to worry about.

Okay, I think I see what you're saying. I need another Register set to write to change more than one register on a slave.

I was under the impression from what I've picked up going thru the Arduino examples that the Loop was the only part of the sketch that would be run repeatedly.  Would I be able to move the switch state detection to Setup or into a new function?

I'll change those pins ASAP on the Slave.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 17, 2014, 06:53 am
Hi Craig,

You don't have to alter the library. The modbus library is a state machine. When modbus_update() is called it updates the state machine. Everything that is required for communication between master and slave runs in the back ground. The register arrays you assign to a packet using modbus_construct() is updated with new information every time the slave responded with a valid frame. You only need to access the register arrays (readRegs[] and writeRegs[] in the example sketch) to gain access to a slaves information. You don't have to worry about anything else. Take a look at the example sketch again. Add some more packets and match them to more register arrays. Change the slave code so that the address space contains more information (say, more adc channels or more pwm channels etc.).

Take a look at the first thread http://forum.arduino.cc/index.php?topic=176142.0 I explain a bit about the FSM.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: el_enano_rumbero on Jul 17, 2014, 05:04 pm
Good afternoon Juan,

I'm testing the communication putting an arduino 2560 as a slave and one as master plc. Everything works fine when the plc which reads a value from the arduino (function 3), but when I want to write a value to the arduino (function 16) the message never reaches the arduino, any ideas? I'm just using 120ohm resistors terminancion

Greetings and thanks for your work
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: CraigF on Jul 17, 2014, 06:28 pm
Thanks Juan!

With that, I managed to add a second LED to the example, and get it to light!  That's a lot easier than what I was trying to do, should be easier to get the system to update.

EDIT: Got the system running! The modbus update takes quite a while... I'm worried it may be too slow. Too many people are interested in instant gratification.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sbeghers on Jul 17, 2014, 11:16 pm
Hi JuanB,
I understand my situation.

I don't have problem to read Regs, but i have problems about conversion in floating point.

Let me explane.

When I launch the reading of the voltage:
modbus_construct(packet1, 1, READ_INPUT_REGISTERS, 0, 2, readRegs);

I read these data in the monitor:

readRegs[0] = 17238
readRegs[0] = 5107

number 17238 (decimal) = 4356(hex)
number 5107 (decimal) = 13F3(hex)

4356 13F3(hex) = 2,1407793E+02 = 214,07793

So i  need to convert what e receive in floating point.
any suggestions?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 18, 2014, 06:56 am
Hi sbeghers,

Take a look at the previous sketch I attached. It shifts readRegs[1] as MSB and readRegs[0] as LSB into a float.

I have attached another sketch that with swapped values.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 18, 2014, 07:03 am
Hi Craig,

Can you expand on what you mean by "The modbus update takes quite a while..."?

Is the values updating to slow?

Unfortunately if modbus senses an error of any kind it will slow down the update rate by the timeout value. This is the modbus protocol greatest flaw. But if the modbus slave is really quick in responding  and the distance is short than you can decrease the polling rate to say 100ms and the timeout value to say 300ms and increase the baud rate.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 18, 2014, 07:07 am
Hi el_enano_rumbero,

Is the master setup correctly? I.e. address you are writing to, amount of registers etc...

What RS485 driver ic are you using? You pretty much need 560 ohm pull up and pull down resistor all of the time unless you are using the true fail safe drivers from maxim.

Post your slave sketch and a picture of the PLC master modbus setup information.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: el_enano_rumbero on Jul 18, 2014, 12:51 pm
Good morning John, thanks for replying

I use an integrated ebay bought this

http://www.ebay.es/itm/1x-MAX485-RS-485-TTL-to-RS-485-Module-converter-For-Arduino-A893-/161341857356?pt=UK_Computing_CablesConnectors_RL&hash=item2590b95e4c&_uhb=1

and the only thing I've added is 120ohm termination resistors.
I tried to communicate with the master being plc plc AB1400 AB and I can read the arduino (function 3) but can not write (function 16). After I put the AB plc arduino slave and then as a teacher and I can write to the plc (function 16) but I can not read the plc (function 3). I later connected a screen Proface as modbus master and removed plc AB and I put the Arduino as a slave and me is exactly the same, I can read the arduino (function 3) but I can not write to the arduino (function 16).
The bottom line is that I can never change a value in the arduino, no matter as a slave or master. Starting from the base of your example, and try to write / read on the arduino one 16bit integer in the address 40001/40002, not really encounter the problem .....

Greetings and thanks
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: el_enano_rumbero on Jul 18, 2014, 01:09 pm
We attached a picture where you see the error and the code I'm using, which is the same as your example but with the modification of the rate at 19200

regards

Code: [Select]

#include <SimpleModbusSlave.h>
#define  LED 9 

enum
{     
  ADC_VAL,     
  PWM_VAL,       
  HOLDING_REGS_SIZE // leave this one
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array

void setup()
{
  modbus_configure(&Serial, 19200, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);
  modbus_update_comms(19200, SERIAL_8N2, 1);
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
  holdingRegs[ADC_VAL] = analogRead(A0); // update data to be read by the master to adjust the PWM
  analogWrite(LED, holdingRegs[PWM_VAL]>>2); // constrain adc value from the arduino master to 255 
}
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: CraigF on Jul 18, 2014, 05:02 pm

Hi Craig,

Can you expand on what you mean by "The modbus update takes quite a while..."?



The arduino was very slow to update the states of registers and follow thru on the LEDs I put on them.  taking about 4-8 seconds to alter the state of 2 registers.

I had added a delay into the loop and forgotten about it, after reducing it and lowering the polling rate it is running much quicker.  I'll have to see about playing around with those variables to see if I can make it a little faster to respond. 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sbeghers on Jul 18, 2014, 06:09 pm
Hi JuanB,
I don't find post about MSD LSD
i test your sketch
but it doesn't do floating conversion.

In monitor I show like this:

Low byte: 17233
High byte: 64529
Voltage: 64529
********
I attend
Low byte: 17233
High byte: 64529
Voltage: 209.98
********
I don't understand why it works so.
Logic is correct, informations inside registers are them
I don't find good documents about floating point.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 20, 2014, 11:18 am
Hi sbeghers,

Apologies, I did not pay attention or tested when posting the code. It would never of worked.

Try the attached sketch. In order for the float value to be correctly casted the compiler needs to be directed to cast the address (not value) of the unsigned long to a float and then de-reference the temp variable address (obtaining the value) and assign it to the float variable.

Easy....  :smiley-eek:
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 20, 2014, 07:24 pm
Hi Craig,

Any delay in your sketch will affect the state machine timing. That is why I use  polling delays of 200ms or more with large sketches and call modbus_update() more often in my sketches to update the FSM.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 20, 2014, 07:49 pm
Hi el_enano_rumbero,

It seems very strange that function 3 works and 16 doesn't.

Here are a few questions:

1. What value is displayed by the master when you read with function 3 from address 0? It should be a varying analog voltage value.
2. When the master does not detect a successful function 16 request does it produce an exception response or timeout error? The attachment you sent indicates error code 37 in hex. This is not a valid modbus exception or maybe there are more diagnostic you can see. Does error 37 indicate a timeout?
3. Are you writing to the correct address. Some masters include offset in the address.I.e. 40001 will automatically be sent as 0000. Some not which means 40001 will be sent as 0001.
4. What happens when you change the baud rate to 9600?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: el_enano_rumbero on Jul 21, 2014, 12:33 pm
Good morning Juan,

After going crazy for 3 days, check everything 50 times, just left me to try something and change the MAX485 module was purchased in ebay, and magic!!! worked perfectly, so I gently picked up the pcb and what thrown away with great joy.

I only doubt is resolved, I'm using a mega 2560 board and need to change the pin 1TX 0RX and use 19RX 18TX and pins, is this possible?

Thank you very much
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: CraigF on Jul 21, 2014, 09:21 pm
Thanks for all the help Juan!

I've gotten myself up and running.  My next big hurdle is senor input and up-scaling, so I should not have any problems with Modbus for the immediate future.

Good luck with your project everyone else!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sbeghers on Jul 22, 2014, 09:08 pm
Hi JuanB,
This is a big day, your sketch works fine and i see in monitor what i attend.
Thank you very much for your support.

I have to questions:
1. In your sketch you write &Serial1 but i don't see anything in monitor.
I remember you wrote to me that for &Serial1 pins in arduino are: Rx=pin19, Tx=pin18, RxTxEnable=pin2.
I done this but without progress. Are correct that pins?
I use &Serial wher pins are: Rx=pin0, Tx=pin1, RxTxEnable=pin2
So it works fine but i can't update arduino if these pin are connected to slave (i know why).

2. My next step of my project is to read all other info, these are:
- voltage, you know (address 0x0000);
- current,  (address 0x0006);
- power,  (address 0x000C);
- volt amphere,  (address 0x0012);
- volt amphere reactive,  (address 0x0018);
- power factor,  (address 0x001E);
- phase angle,  (address 0x0024);
- energy,  (address 0x0046);
- total current energy,  (address 0x0156);

I change your last sketch and insert others info; what i see in monitor is all of value are 0.00, than i change to read, calculate and monitor only voltage and current and i see in each loop: voltage =0.00, current is ok.
I attached my sketch and monitor image.
I think is a problem of timing.
Where i'm worng?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sidbin on Jul 23, 2014, 01:33 pm
This library works with DHT11/22 or BMP085?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: cmcgonag on Jul 24, 2014, 04:27 am
Juan,

Finally got around to checking my shield. It has 5V across pins 5 and 8. Do I still need to add the resistors? Also, any recommendations where I can get a more proper shield and USB converter?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sbeghers on Jul 26, 2014, 01:16 pm
I resolve all of problems.
JuanB thank you very much for your support and patience.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: miketedeschi on Jul 26, 2014, 04:22 pm

Juan,

Finally got around to checking my shield. It has 5V across pins 5 and 8. Do I still need to add the resistors? Also, any recommendations where I can get a more proper shield and USB converter?


I made an RS485 Arduino, which will also be available as a shield.  It might be what you are looking for, check it out.  The source files will be released after the kickstarter.

https://www.kickstarter.com/projects/1370454848/chainduino (https://www.kickstarter.com/projects/1370454848/chainduino)

(http://chainduino.com/media/chainduino2.jpg)

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jul 30, 2014, 12:46 pm
Hi Colin,

You still need to connect your circuit with referral to my previous post. Pullup = 560ohm, pulldown = 560ohm, Rx tie up = 10k and Termination resistor = 120ohm.

Good luck..
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tasosstr on Aug 01, 2014, 12:50 am
Hello Dear Juan,

First of all Well Done for you're nice work, it is Perfect ! ! ! Thank you ! ! !

I would like to ask you, for you're lights in some question i have.

1. There is any function  number i can use for read and write at the same address ?

2. What is the difference with e.g. F06 and F16 ?

3. If i have 4 packet e.g.
Code: [Select]
packetPointer packet1 = &packets[PACKET1]; // Read from Slave 0-3
packetPointer packet2 = &packets[PACKET2]; // Write to Slave 0-3

packetPointer packet3 = &packets[PACKET3]; // Read from Slave 4-7
packetPointer packet4 = &packets[PACKET4]; // Write to Slave 4-7

// if the array is initialized to the packet.
unsigned int readRegs[4];

// Data to be written to the arduino slave
unsigned int writeRegs[4];

// if the array is initialized to the packet.
unsigned int readRegs1[4];

// Data to be written to the arduino slave
unsigned int writeRegs1[4];

modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0, 4, readRegs); //READ_HOLDING_REGISTERS
modbus_construct(packet2, 1,PRESET_MULTIPLE_REGISTERS , 4,4, writeRegs);//PRESET_MULTIPLE_REGISTERS

modbus_construct(packet3, 1, READ_HOLDING_REGISTERS, 8, 4, readRegs1); //READ_HOLDING_REGISTERS
modbus_construct(packet4, 1,PRESET_MULTIPLE_REGISTERS , 12,4, writeRegs1);//PRESET_MULTIPLE_REGISTERS

modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);


Then on the receiver should i write :
Code: [Select]
enum{
  Send_To_Master_1, // 0 - 3
  Send_To_Master_2,
  Send_To_Master_3,
  Send_To_Master_4,
  Read_From_Master_1,
  Read_From_Master_2,
  Read_From_Master_3,
  Read_From_Master_4,
  Send_To_Master_11, //4 - 7
  Send_To_Master_12,
  Send_To_Master_13,
  Send_To_Master_14,
  Read_From_Master_11,
  Read_From_Master_12,
  Read_From_Master_13,
  Read_From_Master_14,  
  HOLDING_REGS_SIZE // leave this one
};


Or this is wrong ?

If you have some time i will be appreciate if you can make an example with two or more slave.

4. Can i do for e.g. if i press a button on slave 1 to toggle a relay on slave 5 ? if yes please an example


Thank you in Advance.

Best Regard,
Tasos
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 01, 2014, 04:23 pm
Hi Arduinists,

Concerning the DUE:

A user found a typo in the sendPacket() function. I used delay() instead of delayMicroseconds(). Instead of 1400 microseconds between polls it was 1400ms!!!
Thanks Hanno Kolvenbach.

Maybe this is what Craig was referring to; communications seems slow....
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 01, 2014, 05:18 pm
Hi tasosstr,

Attached is a master, slave1 and slave2 sketches. The master only facilitates message pass through.

F6 is "single register preset" and F16 is "multiple register preset". Use function 3 or 4 to read and function 16 to write. F16 can write single registers also but uses 3 extra bytes to do so. F6 is actually redundant as most of the time you would do  a block write on one go using F16.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tasosstr on Aug 01, 2014, 11:39 pm
Hello Dear Juan,

You Are A Star  :) :) :)  ! ! ! ! !

Thank you very very much for you're help and you're time ! ! ! ! !

I appreciate you're help ! ! ! ! !

Have a nice day and good programming ! ! ! !

Best Regards,
Tasos
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: skorpi080 on Aug 16, 2014, 06:52 pm
Hi, sorry for that i write in German, but i can Translate this with Translator.

I want to use this lib with openHAB.
This V3 (https://sites.google.com/site/jpmzometa/arduino-mbrt/arduino-modbus-slave) worked fine with Arduino Mega, however it does not work with the SimpleModbusSlaveV9.
Here is an example. (https://code.google.com/p/openhab/issues/detail?id=434)
On a Atmega8 the V3 does not work.

I also deleted "byte format" in .cpp and .h,  does not work.
SERIAL_8N2, SERIAL_8N1, SERIAL_8E1, SERIAL_8O1 tested, does not work.
I can change the LED State from Arduino with Pin 4 but not from openHAB Interface.

its would be fine use the Arduino IDE 1.0.5.
How can i fix that?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: cmcgonag on Aug 17, 2014, 02:45 am
Mike how do you connect your shield to a laptop for RS485 communication?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: cmcgonag on Aug 17, 2014, 03:23 am
My shield is dead. Cant seem to get it to work. Any other proper shields out there for use?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JLLL on Aug 19, 2014, 12:03 pm
Hi,

I would like to implement MODBUS in my project. I only need the slave on arduino and I have some MODBUS software like MTester, Modview, Modscan, Radzio modbus master simulator, etc.

I am testing this with Uno:
https://drive.google.com/folderview?id=0B0B286tJkafVYnBhNGo4N3poQ2c&usp=drive_web&tid=0B0B286tJkafVSENVcU1RQVBfSzg

I am testing this with Due:
http://forum.arduino.cc/index.php?action=dlattach;topic=176142.0;attach=84184

I have some questions: Should I power the arduino with another power source? If I use the USB power, the RX0 and TX0 are in use right? How can I change the code to use other serial port like TX1 and RX1 on pin 16 and 17?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: skorpi080 on Aug 19, 2014, 03:40 pm
https://code.google.com/p/simple-modbus/issues/detail?id=18&sort=-modified&colspec=ID%20Type%20Status%20Priority%20Milestone%20Owner%20Summary%20Modified

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JLLL on Aug 20, 2014, 04:05 am
Hi,

Simple Modbus v10 is only for Master, how about Slave?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 25, 2014, 04:00 pm
Dear skorpi08,

The library you are referring to is made by jpmzometa and is not affiliated to the SimpleModbus libraries. The SimpleModbus libraries can be downloaded from my drive at https://drive.google.com/folderview?id=0B0B286tJkafVSENVcU1RQVBfSzg&usp=drive_web. For more info check out https://code.google.com/p/simple-modbus/ and read this thread from the start.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Aug 25, 2014, 04:13 pm
Dear JLLL,

Use &Serial1, $Serial2 etc... in the modbus_configure() function of the SimpleModbus libraries. The library you are using on the DUE in the mentioned thread is not mine. Use the one on my drive.

Using the 5V of the USB has got nothing to do with the RX0 and TX0 pins (Serial object- note Serial and not Serial0). You can use the 5V of teh USB and transmit/receive from another slave. Bear in mind that the 0V return of the master and slave will be tied together. Use a 100ohm resistor between devices return lines.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: skorpi080 on Aug 25, 2014, 04:41 pm
I already read the thread several times and found nothing that could fix the problem.
openHAB not support the function 16 and the library does not have the function 6.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JLLL on Aug 27, 2014, 05:41 am
Dear Juan8,

Thank you for your reply. I am using your library now. I am using Arduino Due as slave and PC with FTDI converter as the master.

As discussed in the very beginning of this tread, I deleted all the byteFormat in the library because it is not supported by Due.

My testing result is as the picture below, I can see that the packets sent from arduino matches the packets received [01 03 04 01 F9 00 00 2B FE] however I tested with different software (ModView, MTester) and they show CRC error.

(http://i535.photobucket.com/albums/ee358/joshualai/ModbusCRCerror.png) (http://s535.photobucket.com/user/joshualai/media/ModbusCRCerror.png.html)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JLLL on Sep 02, 2014, 04:21 am
I tried with Modbus Tester and the result is as below, there are two extra bytes of [00] [00] at the end of the received packets, why is it so? Is this causing the software to show CRC error?

(http://i535.photobucket.com/albums/ee358/joshualai/ModbusTester.png) (http://s535.photobucket.com/user/joshualai/media/ModbusTester.png.html)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Sep 08, 2014, 08:24 am
Hi JLL,

I have uploaded the slave library for the DUE. Please downloaded it and give it a try?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: joad on Sep 11, 2014, 08:14 pm
Hi, I have implemented FC6. Go back a few pages and you'll find my example.  It works fine.

Regarding the extra bytes [00], try adding  a resistor (200ohm) between +5V -- rs485+  and GND -- rs485- . 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: skorpi080 on Sep 11, 2014, 08:31 pm
Can you upload the complete File?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: haxan on Sep 13, 2014, 07:37 am
Hi All.

My first post here :)

I have been able to run the example code for the SimpleModbusLibrary successfully. I am now trying to put it to use. I need some help with that. Please kindly help help.

Here is what i am trying to achieve:

I want to transmit a "command" from master to slave. Command can be different each time. Some command examples are "return_status", "update_status", "read_eeprom", "write_eeprom" etc etc.

With each command the number of data can vary. So for example in case of "return_status", i want to read from slave 3 bytes.
In case of "update_status" i want to write 5 bytes to slave. Same is the case with the other two commands.

Now what i am able to do so far is transmit a single data byte (like command) from master on to slave. I can check it went through because the packet->successful_requests increment and the slave gets the value.

So basically at this point i have two questions:
1) How to send multiple bytes with different commands?
2) How to send entire packet as one, command + bytes (so that if it says successful_request, i know both bytes went successfully, not just one or the other)?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: haxan on Sep 13, 2014, 12:49 pm
I want to keep modbus_update() in my main loop but want to control when to send which packet and when to read.

When i keep modbus_update() in my main loop, it keeps sending packets over and over again which i dont want.

I want to send a packet only when i press a button or when a logic is met. Can someone please help me?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: joad on Sep 13, 2014, 09:04 pm
You can find the entire file here if you want to test FC6.

https://drive.google.com/folderview?id=0B2wEEwjjx85tUUIwVk9GdTlsZFU&usp=sharing (https://drive.google.com/folderview?id=0B2wEEwjjx85tUUIwVk9GdTlsZFU&usp=sharing)

I have only done minor testing with products from Schneider Electric up to 38400 baud, but everything works fine.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: skorpi080 on Sep 13, 2014, 09:11 pm
Can you add a Funktion 1 and 5?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: AlexNester on Sep 14, 2014, 06:55 pm
Hi All

a very important topic

Have a problem

Arduino DUE - as master

if Im use pinMode for Digit inputs or turn pullup resistor on

master do not send signals :smiley-sad-blue:

With this code problem
Code: [Select]
pinMode(encoderPin1[9], INPUT);
pinMode(encoderPin2[9], INPUT);

digitalWrite(encoderPin1[9], HIGH); //turn pullup resistor on
digitalWrite(encoderPin2[9], HIGH); //turn pullup resistor on
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: AnkitPatel on Sep 15, 2014, 01:14 pm
Hello Juan and Modbus mates,

I have recently started work on Arduino and MODBUS.
I understand arduino but not MODBUS.

My problem is that I want to communicate PLC with MODBUS and read and write registers on PLC.
My PLC can support RS232, 485 and TCP.

What should be my connections?
If I go for 232 then
Uno(master) RxTx -> TxRx of PLC and Ground directly?

What will be the modification?

If I also get connections for TCP then it will be great help I have Ethernet Shield also.

Thanking you in Advance.
Ankit Patel
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Sep 15, 2014, 03:53 pm
Dear Modbus users ;-)

I have updated the master library so that it uses one address space set by the user and I have added function 5 & 6. I have also created an extensive manual that will help get you started. (my head hurts after that  :smiley-eek: )

I am busy implementing function 1, 2, 4, 5, 6 and 15 on the slave library....

I have also shared a link on my drive with a wealth of information on Modbus, RS485 and CAN.

https://drive.google.com/folderview?id=0B0B286tJkafVY18xYVhmWG1qbkk&usp=sharing

AnkitPatel:

You cannot connect the PLC directly to the arduino. It will blow. The arduino levels are TTL232 (0v & 5V) while RS232 is +-15V. You need a translator IC like the MAX232A or something similar. Look at the manual, there are various circuits, one of them is a translator circuit I used on my PC to communicate with the arduino using just RS232.

AlexNester:

I don't understand your question? Please post the whole sketch?

haxan:

Concerning the read functions 1, 2, 3 and 4 this is standard Modbus implementation where these functions continually run in the back ground. Concerning the write functions 5, 6, 15 & 16; I agree most master software creates events and links them to the specific block you want to execute, a sort of one shot implementation. This is not implemented in my library but it is easy to alter. It will affect how the library is used in its entirety. I will have to think about implementing it. In the mean time you can use the polling variable to extend the time between requests and you can use the "connection" attribute of each packet to start and stop communication of a specific packet. This works well.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: AlexNester on Sep 16, 2014, 08:30 pm
Quote
I don't understand your question? Please post the whole sketch?

Ok
When Im delete this part of my code
Code: [Select]
[code]pinMode(encoderPin1[9], INPUT);
pinMode(encoderPin2[9], INPUT);

digitalWrite(encoderPin1[9], HIGH); //turn pullup resistor on
digitalWrite(encoderPin2[9], HIGH); //turn pullup resistor on
[/code]

communication establish,

but with this code - not work, master not send and slave not answer

my scheme:
PC#1 -> arduino due(master) -> Rs485 -> interface ?onverter485/USB ->PC#2 (modbus slave)

are you sure, if configure digital ports, communication will be establish between master and slave?

see my attach
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Sep 16, 2014, 10:39 pm
Hi AlexNester,

Referring to the code snippet below:
Code: [Select]

int encoderPin1[9] = {51,22,24,26,28,30,32,34};


When initializing arrays in C you don't have to define the size as the compiler will do this for you. E.g.
Code: [Select]

int encoderPin1[] = {51,22,24,26,28,30,32,34};


Referring to the code snippet below:
Code: [Select]

pinMode(encoderPin1[9], INPUT);
pinMode(encoderPin2[9], INPUT);

digitalWrite(encoderPin1[9], HIGH); //turn pullup resistor on
digitalWrite(encoderPin2[9], HIGH); //turn pullup resistor on


This will not work as you are indexing the arrays out of bounds. This will result in some weird operation in your program and might very well be the cause of your communication failure as you are writing to some memory area that is not defined.

If you want to turn on all the pull-ups on your inputs using digitalWrite() you must sequence the array with a loop. The same goes for pinMode().

Good luck..
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: haxan on Sep 17, 2014, 05:23 am
Thank JuanB for your reply and updating the library. The manual looks amazing and explains alot.

I am able to achieve non-polled data pulling using the "connection" attribute as you said so. All is working good now!  :)

Currently i have two Arduino Megas (one as master and the other as slave). They communicate well and send a command when i press a button on the master. Similarly send another command when i send the other button.

My question now is: Will it be possible to port the code for the master side on to Raspberry PI ?

I want to install a webserver on Raspberry Pi and send the command from browser. Any pointers?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Sep 17, 2014, 08:14 am
Hi haxan,

I'm glad it works!

Porting is not trivial. The Raspberry runs a form of Linux OS. You will have to interface a native serial C library with the SMM code. I know libmodbus has been ported and tested on Linux OS's so if you are developing in C this will maybe be easier to master. If however you are developing in Java it is quite easy to port the library as their are various abstracted serial libraries for windows and Linux. You will probably find abstracted serial libraries for Python to.

It boils down to in what software are you developing in and does it have an abstracted serial library you can incorporate into SMM.

Since you are developing in a browser already have a look at chrome plugins. There are various serial and usb driver plugins so you can develop right in the browser and use JS, CSS and HTML.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Sep 18, 2014, 02:45 pm
Hi Haxan,
You ask:
Quote
My question now is: Will it be possible to port the code for the master side on to Raspberry PI ?
I want to install a webserver on Raspberry Pi and send the command from browser. Any pointers?


I would suggest you take a look at libmodbus which you should be able to install and use right away.

I have done this myself recently and am actively developing an application that is developed in C and runs on Linux.
Some details that might interest you, my system  consists of:
Debian GNU/Linux runing on small DELL D420 laptop, soon to be migrated my CubieBoard II (ARM CPU).


Where my intention is leading is to continue to develop this into somewhat of a ModBus data concentrator, able to talk to multiple device on both RTU and TCP at the same time.

In RTU mode it can talk via USB, or RS-485 and handle a multi-drop network of devices.
All device ports operate in separate threads within the application to allow for smooth and un-interrupted communications across all channels.

I've had it working now for the past months and more needs to be done, but if there is interest in this appication I'll make it available. My plan was to have it available for open source. I'm in the proces of doing some documentation.

My hope is that it will be a SCADA system that allows your web browser to be the GUI.

I would be interested in any thoughts any people have.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: AnkitPatel on Sep 25, 2014, 11:03 am
Hello Juan,

Thanks for the reply,
As per ur schematic https://code.google.com/p/simple-modbus/downloads/detail?name=RS485%20Connection%20Schematic.pdf&can=2&q= (https://code.google.com/p/simple-modbus/downloads/detail?name=RS485%20Connection%20Schematic.pdf&can=2&q=)
i have made circuit on bread board.

I want to communicate with DELTA Temperature Controller (DTB4848) which has RS485 port and able to communicate on Modbus protocol. http://www.delta.com.tw/product/em/control/temp_control/control_temp_control_product.asp?pid=3&cid=4&itid=2 (http://www.delta.com.tw/product/em/control/temp_control/control_temp_control_product.asp?pid=3&cid=4&itid=2)

Code: [Select]

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate

#define retry_count 10

#define TxEnablePin 2

#define LED 9
enum
{
  PACKET1,
//  PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
unsigned int readRegs[1];
unsigned int writeRegs[1];

void setup()
{
modbus_construct(packet1, 2, READ_HOLDING_REGISTERS, 4096, 1, readRegs);

modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);

pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();

  Serial.print("requests: ");   
  Serial.println(packet1->requests);
  Serial.print("successful_requests: "); 
  Serial.println(packet1->successful_requests);
  Serial.print("failed_requests: "); 
  Serial.println(packet1->failed_requests); 
  Serial.print("exception_errors: "); 
  Serial.println(packet1->exception_errors);
  Serial.print("Active energy: "); 
  Serial.println(readRegs[0]);
}


I have attached output below.
Can you tell me whats wrong?

Thanks,
Ankit Patel
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: AnkitPatel on Sep 29, 2014, 07:58 am
Hello Juan,

I got the o/p as I was using Arduino Uno with one UART.
So I have changed the board to Arduino Mega with four UARTs.

For RS485(MODBUS) in/out 1 UART and for serial in/out with PC different UART.

Thanks,
Ankit Patel
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: UgoMazzali on Oct 31, 2014, 03:27 pm
Dear all,
a very quick question to understand if I can continue on this way.

I have this set up:

- Arduino UNO v3
- MAX 485
- Energy Meter with a Modbus RTU output by Bticino

Did anyone try a Modbus communication with Arduino Uno? I mean, Arduino Uno has only one serial port. So, how can communicate data with the PC? It can't.(Right?)

So I tired this way: install the incredibly useful libraries of JuanB with an ethernet shield.

Then, I programmed ArduUno, I disconnected the USB cable to let the data go through pin 1(RX) and 0(TX) and arrive to an internet cloud by means of the ethernet shield.

Do you think it could work?Actually a value of 0.00 constantly arrives to the cloud.

I'm sorry for the trivial question, and If I missed post with similar problems.

Thank you to the community.

Nice day to all!
Ugo

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Nov 03, 2014, 09:07 am
Hi Ugo,

Did you manage to communicate to the power meter using the master library?

The code you mailed me indicates two packets but you are only using one. This is not good. You also use delay() in there which is also not good.

Use the latest master library SMM2rev2 and try to have a read through the manual. The manual is still a work in progress but there is a lot of information in it.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: UgoMazzali on Nov 06, 2014, 10:13 am
Hi Juan,
thank you a lot for you suggestions. I'll try them all.

A general question still remain:
Arduino UNO has only one serial. Is it possibile to read energy values from the meter on the computer (via USB) if the serial is occupied for the ModBus communication? Is the Ethernet Shield a way of possibile solution (Read data from the filed via Modbus and send them to an internet cloud by means of the TCP/IP on the ethernet shield)

Thank you again!
Nice day
Ugo
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 06, 2014, 10:30 am
UgoMazzali wrote:
Quote
Is it possibile to read energy values from the meter on the computer (via USB) if the serial is occupied for the ModBus communication?
If I understand you correctly where you wish to communicate Modbus from your computer, then, yes it is, by using the libmodbus (http://libmodbus.org/documentation/) library.

It can work with TCP or RTU, so you can select what you wish to connect with your devices.

I have tried both and they work very well, but of course this is not on Arduino, but on a Intel or ARM based computer. I use it with Intel and ARM under GNU/Linux, with an application I am developing.

With this method you can do as you wish with the data, send it onwards to a fluffy cloud or deal with it on your own system as I do with my own system, by storing it and making it available via HTTP for web clients.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: haxan on Nov 09, 2014, 11:11 am
Hi again.

I have again tried to patch a different circuit and cant seem to get the communication running.

I am using Mega as my master and DUE as slave. (both are R3)

I cant seem to get any communication up. I have attached the code for both and the Transceiver circuit i am using.

Can anyone please let me know what i am doing wrong? (the code is little modifed from the example of SimpleModbus because i didnt have POT at hand).

Libraries:
SimpleModbusSlaveV9_DUE
SimpleModbusMasterV12

Master (MEGA) code:
Code: [Select]
#include <SimpleModbusMaster.h>


#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate

#define retry_count 1000

#define TxEnablePin 8

enum
{
  PACKET1,
  PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

packetPointer packet1 = &packets[PACKET1];
packetPointer packet2 = &packets[PACKET2];

unsigned int readRegs[3];
unsigned int writeRegs[3];

void setup()
{
  
  // read 1 register starting at address 0  
  modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0, 1, readRegs);
  
  // write 1 register starting at address 1  
  modbus_construct(packet2, 1, PRESET_MULTIPLE_REGISTERS, 1, 3, writeRegs);
  
 
  modbus_configure(&Serial1, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
  
  pinMode(TxEnablePin, OUTPUT);
  pinMode(53, INPUT);
  pinMode(51, INPUT);
  pinMode(49, INPUT);
}

void loop()
{
  modbus_update();
  
  writeRegs[0] = digitalRead(53); // update data to be written to arduino slave
  writeRegs[1] = digitalRead(51); // update data to be written to arduino slave
  writeRegs[2] = digitalRead(49); // update data to be written to arduino slave
  
}



Slave (DUE) code:
Code: [Select]
#include <SimpleModbusSlave_DUE.h>
enum
{    
 
  ADC_VAL,    
  PWM_VAL1,        
  PWM_VAL2,        
  PWM_VAL3,        
  HOLDING_REGS_SIZE // leave this one
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array

void setup()
{


  modbus_configure(&Serial1, 9600, 1, 22, HOLDING_REGS_SIZE, holdingRegs);

  modbus_update_comms(9600, 1);
}

void loop()
{

  modbus_update();
 
  Serial.println(holdingRegs[PWM_VAL1] + '0'); // constrain adc value from the arduino master to 255
  Serial.println(holdingRegs[PWM_VAL2] + '0'); // constrain adc value from the arduino master to 255
  Serial.println(holdingRegs[PWM_VAL3] + '0'); // constrain adc value from the arduino master to 255

  
}



P.S: Both DUE and MEGA grounds are common.

Edit: Can it be an issue with MAX487 voltages because DUE works on 3.3V and the transceiver is 5V based? - If yes then which other variation should i use?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Nov 10, 2014, 09:07 am
Hi Ugo,

Using TCP/IP with a suitable shield will most likely work so long as the UART interrupt is not interfered with. You could even use SoftwareSerial with a suitable level translator to interface to the PC. Just check out the timing routines.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Nov 10, 2014, 09:29 am
Hi haxan,

First off the driver IC voltage difference should not be a problem. Check this link: http://e2e.ti.com/support/interface/industrial_interface/f/142/t/93260.aspx

I have also simulated this scenario with no adverse effects.

Secondly, you can use the latest SMMV2rev2 library. I have also written a manual for it.

Then try to get the example sketches going.

Good luck.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: haxan on Nov 11, 2014, 05:39 am
Thanks JuanB.

I cant seem to find the SMMV2rev2 you are referring to. This is the link i have for your libraries ( https://drive.google.com/folderview?id=0B0B286tJkafVYnBhNGo4N3poQ2c&usp=drive_web&tid=0B0B286tJkafVSENVcU1RQVBfSzg )

If you are referring to SimpleModbusSlaveV10_DUE.zip then i will most certainly try it out.

Regarding the IC voltage issues, I have read the post from the link you shared. It explains that the 5v transceiver will work with 3.3v -- but what about DUE pins? Wont the RX and TX pins get fried if they receive more than 3.3V (sorry for being a newbie but i thought it is an important question)

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: UgoMazzali on Nov 12, 2014, 12:14 pm
Hi Ugo,

Using TCP/IP with a suitable shield will most likely work so long as the UART interrupt is not interfered with. You could even use SoftwareSerial with a suitable level translator to interface to the PC. Just check out the timing routines.
Thanks Juan,
As soon as I have time to try all your suggestions I'll let you know the results.

Thanks a lot for the support
Nice day
Ugo
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: UgoMazzali on Nov 13, 2014, 04:31 pm
Hi Juan,
I'm trying to implement the new code using SimpleModbusMasterV2rev2 and your recent suggestions.

Two issues:

1. The register from my energy meter's size is 2 word. So I need 2 registers and 1 packet. Is this correct? I post a piece of the code for the modbus_construct function:
Code: [Select]


[..]

#define TOTAL_NO_OF_REGISTERS 2

[..]

  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 50536, 1, 0);
[..]
  
  long energy = (long)regs[0] << 16 | regs[1];

}


2. I tried your suggestion for SoftwareSerial. I didn't know about it. How can I change the Modbus_configure first parameter according to my software serial on pins 10 and 11? I post the code:
Code: [Select]

#include <SoftwareSerial.h>

[..]

SoftwareSerial OtherSerial(10, 11); // RX, TX

[..]

{
  OtherSerial.begin(9600);
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 50536, 1, 0);
  modbus_configure(&OtherSerial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
}

void loop()
{
  modbus_update();
 
  long energy = (long)regs[0] << 16 | regs[1];
  Serial.print(energy);
}


And finally the complete code if useful:
Code: [Select]
#include <SoftwareSerial.h>

#include <SimpleModbusMaster.h>

#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 10

#define TOTAL_NO_OF_REGISTERS 2

#define TxEnablePin 2

SoftwareSerial OtherSerial(10, 11); // RX, TX

enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS
};

Packet packets[TOTAL_NO_OF_PACKETS];

unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
  OtherSerial.begin(9600);
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 50536, 1, 0);
  modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
}

void loop()
{
  modbus_update();
 
  long energy = (long)regs[0] << 16 | regs[1];
  Serial.print(energy);
}


Thanks as always.
Nice day
Ugo


 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: haxan on Nov 15, 2014, 12:26 pm
Hi Everyone. My communication is now working again on DUEs (Master and Slave Both).

I can see that the latest libraries have been changed. The modbus_construct in Master no long takes the registerArray as its last parameter. Had to change code to get it to working.

However the weird thing was, I couldn't add a resistor between MAX-487 pin 6 and 7 (A and B). As soon as i add a resistor there, the communication stops. I have tried with 330 ohms, 2 x 330 ohms in parallel, 3 x 330 ohms in parallel.

Does anyone have insight in the matter?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Nov 18, 2014, 09:39 am
Hi haxan,

Are you also using a 510ohm tie up and 510ohm tie down resistors? Without these on the non fail safe transceivers the data bus is undefined when both are idle.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Nov 18, 2014, 09:49 am
Hi Ugo,

You are correct, you need 2 registers and one packet.

You cannot use SoftwareSerial in the modbus library directly as the library is written around the hardwareSerial library and it expects this as an object in configure().

Porting the modbus library to accept SoftwareSerial is trivial though.

Once again you cannot use the Serial object once assigned to the modbus FSM. To use SoftwareSerial separately will require a TTL232 to USB conversion on your selected pins.

Keep in mind that the SoftwareSerial routine makes use of interrupts and will most likely have an effect on the hardware serial receive routine affecting the modbus library negatively.

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: haxan on Nov 20, 2014, 02:33 am
Are you also using a 510ohm tie up and 510ohm tie down resistors? Without these on the non fail safe transceivers the data bus is undefined when both are idle.
I am using a 10K pull up resistor with RX pin on the Arduino DUE and the transceiver. But no pull down with the TX. (I hope that is what you meant with tie up and down resistors)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Nov 25, 2014, 09:15 am
Hi haxan,

No this is not what I meant. The 510 ohm pull up and pull down is on the A and B lines. With out it the bus is undefined and may pickup noise which results in arbitrary switching and fills the buffer with crap which creates a time out.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tasosstr on Nov 26, 2014, 02:21 pm
Hello Dear Juan,

I was download the last verion of you're nice library and on Master if i use the code
Code: [Select]
if(packets[PACKET1].connection == 0) packets[PACKET1].connection = true; the master, in case if loose the bus and reconnected, freeze, in past this was working, how can i fix this, please ?

On
Code: [Select]
modbus_construct(Slave Address, Function mode,? ,?, ?); I am not really sure if i have understand the ?, the first ? it is the address like 4xxx on holding register ? the other ?

Also can you please do an example with the Function 2 ?

And the final question, the function 23 you can use it to read or to write in the same address ? if not is any function can do this ?

Thank you in advance.

Best Regards,
Tasos   
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: emb_nkonnect on Dec 02, 2014, 08:42 am
Hi everyone,

I m using UNO to communicate with Delta PLC. For start up i want to read 1 register from plc through RS485. I downloded Jaun's Simple Modbus masterV10 library and burned it in arduino. My connection is from arduino rx(pin0) tx(pin1) to rx tx of max485 and A,B and gnd to rs485 connection of PLC.
Here is my code
Code: [Select]
#include <SimpleModbusMaster.h>

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 10

#define TxEnablePin 2
enum
{
  PACKET1,
//  PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
unsigned int readRegs[1];

void setup()
{//reading value of 4099 register
  modbus_construct(packet1, 2, READ_HOLDING_REGISTERS, 4099, 1, readRegs);
 
  modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);

}

void loop()
{
  char i;
 
  modbus_update();
  if(Serial.available() >0);
  {
    Serial.print("requests: ");   
    Serial.println(packet1->requests);
    Serial.print("successful_requests: "); 
    Serial.println(packet1->successful_requests);
    Serial.print("failed_requests: "); 
    Serial.println(packet1->failed_requests); 
    Serial.print("exception_errors: "); 
    Serial.println(packet1->exception_errors);
    Serial.print(readRegs[0]);
    Serial.println("");
    delay(2000);
  }
}


and output response is attached. one more question i don't understand why i m getting 2 responses for 1 request i.e
 pùrequests: 7
successful_requests: 0
failed_requests: 6
exception_errors: 0
0
requests: 7
successful_requests: 0
failed_requests: 7
exception_errors: 0
0


Also the second image is the schematic for RS232 to RS485 conversion and vice versa.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Dec 10, 2014, 11:45 am
Hi Tasos,

I have tested SMMV2r2 with the free modbus slave simulator MOD_RSSIM from http://www.plcsimulator.org/

I am reading and writing 27 registers using F3 & F16. I am using one of the regsiters to set and clear the packet connection attribute of PACKET2. Everything is working perfectly with no faults after 1000+ requests.

Code: [Select]

#include <SimpleModbusMaster.h>

/*
   The example will use packet1 to read 27 registers from address 0 from the slave using F3.
   The 27 registers are then written back to the slave from address 28.
   One of the registers, regs[26] is then used to enable, disable the connection of packet2.
   The connection status of packet2 can also be sen on LED13.
*/

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

#define LED 13

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 27

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
  // Initialize each packet
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, TOTAL_NO_OF_REGISTERS, 0);
  modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 28, TOTAL_NO_OF_REGISTERS, 0);
 
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
 
  if (regs[26] == 1)
  {
    packets[PACKET2].connection = 1;
    digitalWrite(LED, HIGH);
  }
  else
  {
    packets[PACKET2].connection = 0;
    digitalWrite(LED, LOW);
  }
}


With regards to your second question, the manual contains all the information to setup the library.

F23 is not implemented. You can use F3 to read and F16 or F6 to write.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Dec 10, 2014, 11:51 am
Hi emb_nkonnect,

The manual for SMMV2r2 contains all the information you need with regards to setting up the software and hardware connections between the arduino and slave.

You cannot use the Serial object ones assigned to the modbus state machine.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: emb_nkonnect on Dec 11, 2014, 06:49 am
hey jaun,

thanks for the reply
my problem is solved

Thank u
ratna
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: K_SERG_V on Dec 11, 2014, 06:52 am
Good afternoon.

Prompt, whether use of function of reading/record of bit (coil) (F01, F05) in SimpleModbusSlave is possible?
Whether finishing of libraries is planned?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tasosstr on Dec 11, 2014, 09:28 pm
Hello Dear JuanB,

Thank you very much for the reply ! ! !

I use an Arduino Mega 2560 as Master and an Arduino uno as Slave (ID1),
On Master I have  
- 8 buttons (4 control Local relays and the other 4 will control the other 4 relays from Slave)
- 4 Relays
- I want to connect two Arduino Mini Pro (to control with serial communication the 8 button like above)

on Slave i Have
- 8 buttons (4 control Local relays and the other 4 will control the other 4 relays from Master)
- 4 Relays
- I want to connect one Arduino Mini Pro (to control with serial communication the 8 button like above)

On all buttons i want to connect a led for to know what is the status (On of OFF)

With the bellow codes on master i can control the local but not the slave relays :-(
On slave all the buttons works as should be.
The commands i send from miniPro it is not working at all :-(, the commands from miniPro going well i checked with Serial (usb to Serial) cable.

The manual you told me SMMV2r2 is this (https://drive.google.com/folderview?id=0B0B286tJkafVYnBhNGo4N3poQ2c&usp=drive_web&tid=0B0B286tJkafVSENVcU1RQVBfSzg)  ?

Master Code
Code: [Select]
#include "C:/arduino-1.5.8/libraries/SimpleModbusMaster/SimpleModbusMaster.h"
//#include "C:/arduino-1.5.8/libraries/SoftwareSerial/SoftwareSerial.h"
//SoftwareSerial rs (3,4);  // Rx,Tx for comun. with buttons

#define baud 115200 //57600  //9600
#define timeout 60 //100 //1000 200
#define polling 20 //60 //200 // the scan rate
#define retry_count 10

#define TxEnablePin 2

byte Buttons[8] = {22,23,24,25,26,27,28,29};
byte Relays[4] = {30,31,32,33};

#define Led 13      // Working led flasher

#define ON LOW      // Set the state on of relay logic
#define OFF HIGH    // Set the state off of relay logic

String inputString = "";  // a string to hold incoming data

boolean stringComplete = false;  // whether the string is complete

unsigned long pass;  // Time to compare for flash led
String codeButton[] = {"$110>","$120>","$130>","$140>","$150>","$160>","$170>","$180>"};
String codeRF[] = {"$201>","$202>","$203>","$204>","$205>","$206>","$207>","$208>"};

enum{
 GetSlaveID1, // Get from Slave PACKET1
 SendSlaveID1, // Send to Slave PACKET2
 TOTAL_NO_OF_PACKETS // leave this last entry
};

Packet packets[TOTAL_NO_OF_PACKETS];

#define TOTAL_NO_OF_REGISTERS 16  // 8 for send and 8 for get = 16
unsigned int regs[TOTAL_NO_OF_REGISTERS];

boolean SlaveBut[8];
boolean flag[8];

void setup(){
 modbus_construct(&packets[GetSlaveID1], 1, READ_HOLDING_REGISTERS, 0, 8, 0);
 modbus_construct(&packets[SendSlaveID1], 1, PRESET_SINGLE_REGISTER, 9, 8, 1);
 modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);

 inputString.reserve(60); // for serial data

 for (byte i = 0; i < 8; i++){            // Setup INPUTS
 pinMode(Buttons[i],INPUT_PULLUP);
 if (i < 4){
 pinMode(Relays[i],OUTPUT); // Define OUTPUTS
 digitalWrite(Relays[i],OFF); // Turn off relays at startup
 SlaveBut[i] = 1; // Make sure will hold off relays
 }
 }

 pinMode(TxEnablePin,OUTPUT);

 Serial1.begin(9600);
 Serial2.begin(9600);

 pinMode(17,INPUT_PULLUP);    // Pull up resistor for Rx1 - Ground Floor
 pinMode(19,INPUT_PULLUP);    // Pull up resistor for Rx2 - First Floor
 pinMode(12,OUTPUT);          // Arduino Mega2560
}

void GetModbusStatus(byte but,unsigned int read,unsigned int write,byte flagid,byte modbusReadID,byte modbusSendID){
 if (digitalRead(but) == LOW) {
 SlaveBut[flagid] = !SlaveBut[flagid];
 regs[modbusSendID] = SlaveBut[flagid]; //Send it to slave
 flag[flagid] = true;
 while (digitalRead(but) == LOW){delay(100);}
 }

 if (regs[modbusReadID] != SlaveBut[flagid] && flag[flagid] == false){
 SlaveBut[flagid] = regs[modbusReadID];
 regs[modbusSendID] = SlaveBut[flagid];
 }

 //while (flag[flagid] == true && SlaveBut[flagid] != regs[modbusReadID]){modbus_update();}

 if (flag[flagid] == true && SlaveBut[flagid] == regs[modbusReadID]){
 flag[flagid] = false;
 }
}

// Check message form Serial port (Button Control Arduino Board)
// Not Working the bellow code :-(
void CheckButtonController(){
 // Check for buttons on Button Controller
 for (byte i = 0; i < 4; i++ ){
 byte val = inputString.indexOf(codeButton[i]);
 if (val > -1){
 SlaveBut[i] = !SlaveBut[i];
 }
 }

 delay(400); //put a delay before re'check, new code for msg block
 // Check for RF buttons on Button Controller
 for (byte i = 0; i < 4; i++ ){
 byte val = inputString.indexOf(codeRF[i]);
 if (val > -1){
 SlaveBut[i] = !SlaveBut[i];
 }
 }
 inputString = "";
}

void serialEvent1(){
 while(Serial1.available()){
 char inChar = Serial1.read();
 inputString += inChar;
 if (inChar == '\n'){
 CheckButtonController();
 }
 }
}

void serialEvent2(){
 while(Serial2.available()){
 char inChar = Serial2.read();
 inputString += inChar;
 if (inChar == '\n'){
 CheckButtonController();
 }
 }
}

void loop()
{
 // flash led for show operation
 if ((unsigned long)millis() - pass > 800) digitalWrite(Led ,HIGH);

 // flash led for show operation
 if ((unsigned long)millis() - pass > 1000 ){
 digitalWrite(Led,LOW);
 pass  = millis();
 }

 if (packets[SendSlaveID1].connection == 0 || packets[GetSlaveID1].connection == 0){
 packets[SendSlaveID1].connection = 1;
 packets[GetSlaveID1].connection = 1;
 }

 modbus_update();

// GetModbusStatus(but, read value, write value, button count, read id, write id); // First button
 GetModbusStatus(Buttons[0],regs[0],regs[8], 0,0, 8); // Request Slave First button
 GetModbusStatus(Buttons[1],regs[1],regs[9], 1,1, 9); // Request Slave Second button
 GetModbusStatus(Buttons[2],regs[2],regs[10],2,2,10); // Request Slave Third button
 GetModbusStatus(Buttons[3],regs[3],regs[11],3,3,11); // Request Slave Forth button

 GetModbusStatus(Buttons[4],regs[4],regs[12],4,4,12); // Local Master First button
 GetModbusStatus(Buttons[5],regs[5],regs[13],5,5,13); // Local Master Second button
 GetModbusStatus(Buttons[6],regs[6],regs[14],6,6,14); // Local Master Third button
 GetModbusStatus(Buttons[7],regs[7],regs[15],7,7,15); // Local Master Forth button

 digitalWrite(Relays[0], SlaveBut[4]);  // Master Relay 1
 digitalWrite(Relays[1], SlaveBut[5]);  // Master Relay 2
 digitalWrite(Relays[2], SlaveBut[6]);  // Master Relay 3
 digitalWrite(Relays[3], SlaveBut[7]);  // Master Relay 4

}



Message exceeds the maximum allowed length ....
 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tasosstr on Dec 11, 2014, 09:28 pm

Slave Code
Code: [Select]
//#include <SimpleModbusSlave.h>
#include "C:/arduino-1.5.8/libraries/SimpleModbusSlave/SimpleModbusSlave.h"
#include "C:/arduino-1.5.8/libraries/SoftwareSerial/SoftwareSerial.h"

SoftwareSerial rs(3,4); //Rx,Tx

#define Led 13      // Working led flasher
#define ON LOW      // Set the state on of relay logic
#define OFF HIGH    // Set the state off of relay logic

byte Buttons[8] = {5,6,7,8,14,15,16,17};
byte Relays[4] = {9,10,11,12};

String codeButton[] = {"$110>","$120>","$130>","$140>","$150>","$160>","$170>","$180>"};
String codeRF[] = {"$201>","$202>","$203>","$204>","$205>","$206>","$207>","$208>"};
String inputString = "";  // string for incoming data

enum {
 SendMyStatus,   //Send to Master
 SendMyStatus2,
 SendMyStatus3,
 SendMyStatus4,
 SendMyStatus5,
 SendMyStatus6,
 SendMyStatus7,
 SendMyStatus8,
 RequesChange,   //Get from Master
 RequesChange2,
 RequesChange3,
 RequesChange4,
 RequesChange5,
 RequesChange6,
 RequesChange7,
 RequesChange8,
 HOLDING_REGS_SIZE // leave this one
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array

boolean SlaveBut[8];
boolean flag[8];

void GetModbusStatus(byte but,unsigned int read,unsigned int write,byte flagid,byte modbusReadID,byte modbusSendID){

 if (digitalRead(but) == LOW) {
 SlaveBut[flagid] = !SlaveBut[flagid];
 holdingRegs[modbusSendID] = SlaveBut[flagid]; //Send it to Master
 flag[flagid] = true;
 while (digitalRead(but) == LOW){delay(100);}
 }

 if (holdingRegs[modbusReadID] != SlaveBut[flagid] && flag[flagid] == false){
 SlaveBut[flagid] = holdingRegs[modbusReadID];
 holdingRegs[modbusSendID] = SlaveBut[flagid];
 }

 //while (flag[flagid] == true && SlaveBut[flagid] != holdingRegs[modbusReadID]){modbus_update();}

 if (flag[flagid] == true && SlaveBut[flagid] == holdingRegs[modbusReadID]){
 flag[flagid] = false;
 }
}

// Check message form Serial port (Button Control Arduino Board)
// Not working my logic here :-(
void CheckButtonController(){
 // Check for buttons on Button Controller
 for (byte i = 0; i < 8; i++ ){
 int val = inputString.indexOf(codeButton[i]);
 if (val > -1){
 rs.println(i);
 SlaveBut[i] = !SlaveBut[i];
 switch (val) {
 case 0:
 holdingRegs[0] = SlaveBut[i]; //Send it to slave
 break;
 case 1:
 holdingRegs[2] = SlaveBut[i]; //Send it to slave
 break;
 case 2:
 holdingRegs[4] = SlaveBut[i]; //Send it to slave
 break;
 case 3:
 holdingRegs[6] = SlaveBut[i]; //Send it to slave
 break;
 case 4:
 holdingRegs[8] = SlaveBut[i]; //Send it to slave
 break;
 case 5:
 holdingRegs[10] = SlaveBut[i]; //Send it to slave
 break;
 case 6:
 holdingRegs[12] = SlaveBut[i]; //Send it to slave
 break;
 case 7:
 holdingRegs[14] = SlaveBut[i]; //Send it to slave
 break;

 }

 flag[i] = true;
 modbus_update();
 }
 }

 inputString = "";
}

void setup(){
 rs.begin(9600);
 inputString.reserve(60); // for serial data

 modbus_configure(&Serial, 115200, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs); //9600
 modbus_update_comms(115200, SERIAL_8N2, 1);

 // Setup INPUTS for local buttons
 for (byte i = 0; i < 8; i++){
 pinMode(Buttons[i],INPUT_PULLUP);
 if (i < 4){
 pinMode(Relays[i],OUTPUT);    // Define OUTPUTS
 digitalWrite(Relays[i],OFF);  // Turn off relays at startup
 SlaveBut[i] = 1;   // Invert button at begin to hold off relays
 }
 }
 pinMode(Led,OUTPUT);
}

void loop(){
 modbus_update();
 GetModbusStatus(Buttons[0],holdingRegs[8],holdingRegs[0],0,8,0); // First button
 GetModbusStatus(Buttons[1],holdingRegs[9],holdingRegs[1],1,9,1); // Second button
 GetModbusStatus(Buttons[2],holdingRegs[10],holdingRegs[2],2,10,2); // Second button
 GetModbusStatus(Buttons[3],holdingRegs[11],holdingRegs[3],3,11,3); // Second button

 GetModbusStatus(Buttons[4],holdingRegs[12],holdingRegs[4],4,12,4); // First button
 GetModbusStatus(Buttons[5],holdingRegs[13],holdingRegs[5],5,13,5); // Second button
 GetModbusStatus(Buttons[6],holdingRegs[14],holdingRegs[6],6,14,6); // Second button
 GetModbusStatus(Buttons[7],holdingRegs[15],holdingRegs[7],7,15,7); // Second button

 digitalWrite(Relays[0], SlaveBut[0]);
 digitalWrite(Relays[1], SlaveBut[1]);
 digitalWrite(Relays[2], SlaveBut[2]);
 digitalWrite(Relays[3], SlaveBut[3]);

 // Check Software receive data
 if (rs.available()){
 while(rs.available()){
 char inChar = rs.read();
 inputString += inChar;

 if (inChar == '\n'){
 CheckButtonController();
 }
 }
 }

}



Can you please help me ?

If i want to use FORCE_SINGLE_COIL on master, on slave i do the same you have as an example for the READ_HOLDING_REGISTERS ?

PS. If loose the bus cable and connected it is reconnected without problem

Thank you in Advance.

Best Regards,
Tasos
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Dec 17, 2014, 09:59 am
Hi emb_nkonnect,

Please provide us with your solution for knowledge sharing. Thanks.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Dec 17, 2014, 10:00 am
Hi K_SERG_V,

I'm working on it. Finish date approx 31/12/2014....  :smiley-lol:
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Dec 17, 2014, 10:08 am
Hi tasosstr,

I'm looking at your code, give me a day or so...
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tasosstr on Dec 17, 2014, 10:09 pm
Hi tasosstr,

I'm looking at your code, give me a day or so...
Hello Dear JuanB,

Yes sure my friend  :)

Best Regards,
Tasos
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Mubiki on Dec 28, 2014, 10:46 pm
Hi Juan B

i'm new here but i've been messing about with your code for Arduino Due slave and i've noticed that for some reason altering this line;

  if (!broadcastFlag && (function == 3))

to something like;


  if (!broadcastFlag && (function == 1))

doesn't really affect how the code is executed in that if you send an F3 request it will still be successfully processed as a function 3 even though the code actually states function. Do you by any chance happen to know why.

Regards
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sytex on Dec 29, 2014, 02:29 pm
Hello Everyone!

My problems are hardware related maybe, but I post it here if someone knows the solution.
I use these type of Serial - RS485 converters, which uses MAX485 chips:
(http://bartanet.hu/rumli/link/arduinoforum/modul.jpg)

It has this schematics:
(http://bartanet.hu/rumli/link/arduinoforum/schematic.jpg)

My network:
Mega2560, MasterV2rev2 (I think this is the latest)
Nano, SlaveV10, modified to use software serial, so i can ddebug on HW serial.

My Packets:
Code: [Select]
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 8, 0);      //001 GET SOLAR CELL CURRENTS
  modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 8, 8, 8);   //001 SET SOLAR CELL DIODES
  modbus_construct(&packets[PACKET3], 1, READ_HOLDING_REGISTERS, 16, 5, 16);    //001 GET COMM ERRORS


This is what I RECEIVE on SLAVE side:
(http://bartanet.hu/rumli/link/arduinoforum/slavereceive.jpg)

As you can se, the slave receives a zero, after it transmits anything, and at every received packet end there is a trailing/closing zero too.
For this reason Function16, Write registers, my PACKET[2] never runs because this statement never gets true:
Code: [Select]
if (frame[6] == (buffer - 9))
Because my buffer is longer with one character (the last zero)

I took my logic analyzer, and attached to the serial buses:
(http://bartanet.hu/rumli/link/arduinoforum/logic1.jpg)

Lets zoom in a bit:
(http://bartanet.hu/rumli/link/arduinoforum/logic2.jpg)
As you can see while the Master transmits (TXEnable is enabled), the Master's RX Pin is high, and the Slave's RX pin stays high, after the data, and this causes the trailing zeros.

Let's see the response:
(http://bartanet.hu/rumli/link/arduinoforum/logic3.jpg)
Here you can see, that the Slave start to transmit, his RX pin goes high too, it get to RX buffer as a Zero, and causes the received single zeroes after each transmit.


The examples shows this is not related on that I modified the Slave libary to use SW serial, because this fault exists on both sides. And think I have to achieve, that MAX485 should not pull up the RX pins while there is some traffic on the bus.

All I would be grateful for any help!!

Thanks for reading it!

If you need more code, measurements, outputs, please ask!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: pvggroup1 on Dec 29, 2014, 02:54 pm
hey sytex how do you got the expressions ?? can you give the full arduino code??
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sytex on Dec 29, 2014, 03:03 pm
Which expression?

Which full code do you need? The Master or the Slave?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: pvggroup1 on Dec 29, 2014, 03:52 pm
the Master
and i am using the same converter and not getting the output.
can you also upload the schematic?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: pvggroup1 on Dec 29, 2014, 04:02 pm
Also I am getting this error on compiling

sketch_dec29a:40: error: 'packetPointer' does not name a type

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: pvggroup1 on Dec 29, 2014, 04:26 pm
Hi!! Can anyone suggest me anything about the error of packetPointer?

sketch_dec29a:40: error: 'packetPointer' does not name a type
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: emb_nkonnect on Dec 30, 2014, 06:57 am
hey JaunB

Sorry for late reply, was busy with some other work, mine is a simple code to read/write from rs485 device.
here is the code Hope it helps someone
Code: [Select]
#include<SPI.h>
#include<Ethernet.h>

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};              //declare mac address of Uno + Ethernet shield
byte ip[] = {192,168,0,102};                                   //declare ip address of Uno + Ethernet shield
byte gateway[] = {192,168,0,252};
byte subnet[] = {255,255,255,0};
EthernetServer server(502);                                     //declare server port

// **********Function for CRC calculation**********//
word calculate_crc(byte data[], byte len)
{
  boolean lsb_bit;
  byte i,j;
  word crc = 0xFFFF, POLY = 0xA001;
 
  for (i = 0; i <len; i++)
  {
    crc = crc ^ data[i]; //Xoring 1st data byte with crc
    for(j=0; j<8; j++)
    {
      lsb_bit = crc & 0x0001; //Checking LSB of crc
      if(lsb_bit ==1) //Compare lsb
      {
        crc = crc >> 1;         //If lsb_bit =1 shift right
crc = crc  ^ POLY;         //and xor with poly=A001
      }
      else if(lsb_bit == 0)
      {
        crc = crc>>1;         //If lsb_bit =0 only shift right
      }
    }
 }
 return crc;
}
//**************************************************//

void setup()

  Serial.begin(9600, 0x0E);                    //hex code for SERIAL_8N2
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();

 
void loop()
{
  byte Query[40] = {}, rd_qry[8], rd_resp[] = {}, wr_qry[] = {}, wr_resp[8] , len, len1, len2, i, j;
  word crc_16;
     
  EthernetClient client = server.available();
  if(client)
  {
    server.write("New Client");
    while(client.connected())
    {
      if(client.available() > 0)
      {
        for(i=0; i<40; i++)
        {
          Query[i] = client.read();                          //receiving data from client i.e pc
        } 
          if(Query[1] == 03)                                 //Checking for the function code
          {                                                  //Holding register read 03H
            for(i=0; i<6; i++)                                   
            {
              rd_qry[i] = Query[i];
              Serial.write(rd_qry[i]);                            //Writes read query to transmit buffer
            }
            len = 6;
            crc_16 = calculate_crc(rd_qry, len);                  //Calls crc calculation function
            rd_qry[6] = lowByte(crc_16);   //Split low byte of crc
            rd_qry[7] = highByte(crc_16);                         //Split high byte of crc
       
            Serial.write(rd_qry[6]);                              //Writes low byte of crc to transmit buffer
            Serial.write(rd_qry[7]);                              //Writes high byte of crc to transmit buffer
            delay(500);
       
            len1 = (rd_qry[5] * 2) + 5;                          //calculating length of read response bytes
            for(j = 0; j < len1; j++)
            {
              rd_resp[j] = Serial.read();                        //receive read response from slave
              server.write(rd_resp[j]);                          //server writes read response to connected client
            }
            delay(500);
          }
          else if(Query[1] == 16)                                //Checking for the function code
          {                                                      //Multiple Holding register write 10H(16)
            len2 = Query[6] + 7;                                 //calculating length of write query bytes                       
            for(i = 0; i < len2; i++)
            {
              wr_qry[i] = Query[i];
              Serial.write(wr_qry[i]);                          //Writes write query to transmit buffer
            }
            crc_16 = calculate_crc(wr_qry, len2);               //Calls crc calculation function
            wr_qry[i] = lowByte(crc_16); //Split low byte of crc
            Serial.write(wr_qry[i]);                            //Writes low byte of crc to transmit buffer
            wr_qry[i+1] = highByte(crc_16);                     //Split high byte of crc
            Serial.write(wr_qry[i+1]);                          //Writes high byte of crc to transmit buffer
            delay(1000);
           
            for(j = 0; j < 8; j++)
            {
              wr_resp[j] = Serial.read();                        //receive write response from slave
              server.write(wr_resp[j]);                          //server writes write response to connected client
            }
            delay(500);
          }
          else if(Query[1] == 06)                                //Checking for function code 
          {                                                      //Single Holding register write 06H
            for(i = 0; i < 6; i++)
            {
              wr_qry[i] = Query[i];
              Serial.write(wr_qry[i]);                           //Writes write query to transmit buffer
            }
            len = 6;
            crc_16 = calculate_crc(wr_qry, len);                 //Calls crc calculation function
            wr_qry[6] = lowByte(crc_16); //Split low byte of crc
            wr_qry[7] = highByte(crc_16);                        //Split high byte of crc
           
            Serial.write(wr_qry[6]);                             //Writes low byte of crc to transmit buffer
            Serial.write(wr_qry[7]);                             //Writes high byte of crc to transmit buffer
            delay(500);
           
            for(j = 0; j < 8; j++)
            {
              wr_resp[j] = Serial.read();                        //receive write response from slave
              server.write(wr_resp[j]);                          //server writes write response to connected client
            }
            delay(500);
          }
      }
    }
  }
}

thanks
ratna
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: AlexNester on Jan 04, 2015, 12:58 pm
Hi AlexNester,

Referring to the code snippet below:
Code: [Select]

int encoderPin1[9] = {51,22,24,26,28,30,32,34};


When initializing arrays in C you don't have to define the size as the compiler will do this for you. E.g.
Code: [Select]

int encoderPin1[] = {51,22,24,26,28,30,32,34};


Referring to the code snippet below:
Code: [Select]

pinMode(encoderPin1[9], INPUT);
pinMode(encoderPin2[9], INPUT);

digitalWrite(encoderPin1[9], HIGH); //turn pullup resistor on
digitalWrite(encoderPin2[9], HIGH); //turn pullup resistor on


This will not work as you are indexing the arrays out of bounds. This will result in some weird operation in your program and might very well be the cause of your communication failure as you are writing to some memory area that is not defined.

If you want to turn on all the pull-ups on your inputs using digitalWrite() you must sequence the array with a loop. The same goes for pinMode().

Good luck..

Thank JuanB, you right, it's was problem of array. I just not use array encoderPin1[9] and problem was solved
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tasosstr on Jan 04, 2015, 02:09 pm
@AlexNester
For the code
Code: [Select]
int encoderPin1[9] = {51,22,24,26,28,30,32,34};

The correct one is
Code: [Select]
int encoderPin1[8] = {51,22,24,26,28,30,32,34};
this start from 0....7 the 8 it is the termination.

Then you can use
Code: [Select]
pinMode(encoderPin1[7], INPUT); // This is for last number

Try this and let us know  ;)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: brancooo on Jan 10, 2015, 08:51 pm
Hi,
I am doing project with three Arduinos. One master device and two slave devices. Here is my problem. I was testing this library for 1 master and 1 slave, without changes how I have downloaded it...it works! (hardware is OK)

Now I am testing it only with one slave and one master:
I need send 5 numbers(informations) from slave to master and then sleep Arduinos.
How will looks the code for master an slave? I have read every forum but no idea for me. I need only simple explain. Thank you

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jan 10, 2015, 10:26 pm
brancooo wrote:
Quote
from slave to master and then sleep Arduinos
Which Arduino will sleep?

If you mean you wish to put the slave or slaves to sleep, then you can not do this, or it will not be awake for when the master calls it for information.

Or do you mean you wish the master to sleep?

When you say sleep, do you actually mean go into low power mode or just wait mode?

You need to be a lot more clear and specific with how you detail your needs and questions.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: brancooo on Jan 10, 2015, 10:42 pm
Thank you for reply.

Master Arduino goes sleep (to low power mode)

I am testing it only with one slave and one master for a beginning:
I need send 5 numbers(informations) from slave to master.



code for slave:
Code: [Select]

#include <SimpleModbusSlave.h>

enum
{    
  PARAM1,    // registers for my 5 numbers
  PARAM2,
  PARAM3,
  PARAM4,
  PARAM5,        
  HOLDING_REGS_SIZE
};

unsigned int holdingRegs[HOLDING_REGS_SIZE];


void setup()
{
  modbus_configure(&Serial, 9600, SERIAL_8N2, 2, 2, HOLDING_REGS_SIZE, holdingRegs);    
}

void loop()
{
   modbus_update();
  
   holdingRegs[PARAM1] = 100;   // number only for simlicity, later here will be some input
   holdingRegs[PARAM2] = 200;
   holdingRegs[PARAM3] = 300;
   holdingRegs[PARAM4] = 400;
   holdingRegs[PARAM5] = 500;


   // *** how now send data to master?


}


code for master:
Code: [Select]

#include <SimpleModbusMaster.h>

#define baud 9600
#define timeout 1000
#define polling 200

#define retry_count 10
#define TxEnablePin 2
#define LED 13


enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS
};
Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
unsigned int readRegs[5];

void setup()
{
  modbus_construct(packet1, 2, READ_HOLDING_REGISTERS, 0, 1, readRegs);
  modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
}
void loop()
{
  // here will be something another(not necessary now)


  modbus_update();    //for what is this??? Is it necessary?

  // ***** how will looks code?

  unsigned int info1 = readRegs[0];
  unsigned int info2 = readRegs[1];
  unsigned int info3 = readRegs[2];
  unsigned int info4 = readRegs[3];
  unsigned int info5 = readRegs[4];




  //something else e.g. sleep,  so it cant repeat loop() more times
}
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jan 10, 2015, 11:05 pm
brancooo wrote:
Quote
how now send data to master?
The line of code 'modbus_update();' will do this when called by the master.

Rememeber that the master will call the slave and ask for data.
The slave will not send data any other time.

Quote
modbus_update();    //for what is this??? Is it necessary?
Yes, or it would not be in the example would it. It is the call to the function to do the Modbus call.

For testing purposes, in your master code, put in a small delay in the main loop to slow down the requesting of data from the slave, say around 1 or 2 seconds delay.

Did you read the documentation provided by SimpleModbus?

What type of Arduino are you using, more detail?
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: brancooo on Jan 10, 2015, 11:31 pm
I am doing this with two Arduinos UNO rev3.
Yes I have read documentation when I was started with it :(  

OK, for beginning, I will try ask only for PARAM1 with master and signalize it to LED.

Code: [Select]

//code in master loop()
void loop()
{
   modbus_update();
 if (readRegs[0] == 100)
    digitalWrite(LED, HIGH);
}


...it works


when I am asking for PARAM2 from slave
Code: [Select]

//code in master loop()
void loop()
{
   modbus_update();
 if (readRegs[1] == 200)
    digitalWrite(LED, HIGH);
}

...it doesnt work


I have connected schema without any resistor(small distances, 5cm cable), can it be problem? I think no, when it works with readRegs[0].... ?



EDIT:
Quote
The line of code 'modbus_update();' will do this when called by the master.
...so when I want information from slave, I must call method modbus_update(); in slave and also in master ?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jan 11, 2015, 12:06 am
Look at how you configure your modbus construct and look at each parameter you set.
Compare this to what you see in reply #246.

It will be worth your while to sit down and read this whole thread from the start to gain better understanding of how to use this Modbus library and to be able to help your self better.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: brancooo on Jan 11, 2015, 12:35 am
I have read whole Thread dont worry.
Thank you. This Topic#246 I didnt see. But now it works! Thank you again  ;)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jan 11, 2015, 12:43 am
You are welcome  :D
So just to clarify with me, tell us, what did you see that was different, that you had set wrong in your construct?
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: brancooo on Jan 11, 2015, 01:03 am
generally:
modbus_construct(packet, id, function, address, data, register array)

looks in my case thus:
modbus_construct(&packets[PACKET1], 2, READ_HOLDING_REGISTERS, 0, 2, readRegs);

soo, parameter "data" tells how many registers do you use.


(Hey rockwallaby, I sent you a message)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jan 11, 2015, 01:15 am
Yes, that is correct, so if you set that parameter to 1, as you did, then the Modbuss function will only transfer 1 register.

So when you tried a few more registers, it still was only told to do 1.

Set this value as Juan does at reply #246 so it is easily viewable for you as you develop the code.
Yes, I sent you a reply back.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jan 11, 2015, 01:25 am
Brancooo pm:
Quote
You know, I am doing datalogger, It will sleep, wake up every 2 hours, store informations from slaves to SD card and again sleep(and waiting for interrupt-for again go around loop() ).

That program what I sent to you is it only "simulating" (not at all, but its not necessary now, it make what I want)

For  now, I want exactly that what that program is doing. I only need reliably know that when I use once method modbus_update() I will recieve data from slave in master. (No more times in a row)
Ok, letting us know what you are trying to acheive really helps us understand and is important to give clear details.

So, the task you need to have in your loop() function is to read all data from slaves using the modbus_update() function.
Then do something with the data you have received that resides in the holding register array.
Then, as you say, you want to wait 2 hours, (120 minues) before next time around the loop.

My suggestion is do your timing from the loop() function and put the rest of your code in another function that will get called every 120 minutes.

Doing a while(1) {} will keep the Arduino busy going around the while loop and will not put the Arduino in to low power mode, you will need to search and learn how to do that correctly.

What is your reason for wanting to put the Arduino into low power mode, is it operating on solar?
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: brancooo on Jan 11, 2015, 01:48 am
Please, I know that while(1){} isnt low power sleep.
We dont understand us..again
As I wrote, now I am testing only communication(others is not important for me now,problem is only communication).

Yes you right, I will read data from slaves using modbus_update() function.

Now it works only when modbus_update() is called many times(again and again in loop function)
Code: [Select]
void loop(){
  modbus_update();
  if (readRegs[1] == 200)
    digitalWrite(13, HIGH);
}


I need that. (Its only example)
Code: [Select]
void loop(){
  digitalWrite(13, HIGH);   // some action before asking
  delay(1000);    
  digitalWrite(13, LOW);
  delay(1000);


  modbus_update();          // here I need get to know values of readRegs
  if (readRegs[1] == 200)
    digitalWrite(13, HIGH);
  delay(5000);


    digitalWrite(13, LOW);   // simulation some action after asking
  delay(1000);    
  digitalWrite(13, HIGH);       // saving to SD card etc......
  delay(1000);

    //and here will be sleep power down and wait to interrupt from RTC alarm(not necessary now) I used while(1){} only for simulate as i said, to stop(sleep) loop() function
  

}

 I hope that I said it more understandable
...it doesnt work for me. Why ? How to do that, when I call function modbus_update() once from master? Why when I am calling function modbus_update() only once, it doesnt work?


Thank you for your time
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: brancooo on Jan 11, 2015, 02:19 am
Okay,
I think, I solved that

Code: [Select]
void loop(){
  digitalWrite(13, HIGH);   // some action before asking
  delay(1000);    
  digitalWrite(13, LOW);
  delay(1000);

  
  while(!packets[PACKET1].successful_requests){    
  modbus_update();
  }

  if (readRegs[1] == 200)
    digitalWrite(13, HIGH);
  delay(5000);


    digitalWrite(13, LOW);   // simulation some action after asking
  delay(1000);    
  digitalWrite(13, HIGH);       // saving to SD card etc......
  delay(1000);

    //and here will be sleep power down and wait to interrupt from RTC alarm(not necessary now) I used while(1){} only for simulate as i said, to stop(sleep) loop() function
  

}


while(!packets[PACKET1].successful_requests){    
  modbus_update();
  }


..now it works perfectly! It makes sense we must wait until packet will requested succesfully.

Is there some smarter option?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jan 11, 2015, 03:08 am
I don't beleive that is the correct method to do it, with checking if packet was not succesful to then loop continuously doing modbus_updates.

The modbus library is a finite state machine and will return when completed.
Unlike javascript, Arduino code runs synchronously from statement to statement, so you don't need to continuously check.

I haven't seen any code like how you have it in any recent posts, have you?
It's hard to know what code you haev as you don't show it all, and you may have changed something else that we can only assume is correct.

Please show all code for both slave and master.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: brancooo on Jan 11, 2015, 11:31 am
Quote
The modbus library is a finite state machine and will return when completed.
Exactly, I was thinking also that, But why than doesnt work that code, what is in second part of #277 ?

I havent changed anything else, this is working code for asking and recieving more registers from slave.

Code for master
Code: [Select]
#include <SimpleModbusMaster.h>

#define baud 9600
#define timeout 1000
#define polling 200

#define retry_count 10
#define TxEnablePin 2
#define LED 13


enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS
};
Packet packets[TOTAL_NO_OF_PACKETS];
unsigned int readRegs[5];

void setup()
{
// modbus_construct(packet, id, function, address, data, register array)
  modbus_construct(&packets[PACKET1], 2, READ_HOLDING_REGISTERS, 0, 5, readRegs);   //here must be parameter data- number of registers, address is starting address so 0
  modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
pinMode(LED, OUTPUT);
}
void loop()
{
  void loop(){
  digitalWrite(LED, HIGH);   // simulating some action before asking
  delay(1000);   
  digitalWrite(LED, LOW);
  delay(1000);
  digitalWrite(LED, HIGH);
  delay(1000);   
  digitalWrite(LED, LOW);
  delay(3000);


  while(!packets[PACKET1].successful_requests){
  modbus_update();
  }
  if (readRegs[0] == 100)            //testing if recieved register is equal
    digitalWrite(LED, HIGH);
  delay(3000);



  while(1){}   //and here will be sleep power down and wait to interrupt from RTC alarm(not necessary now) I used while(1){} only for simulate as i said, to stoping loop() function(simulate sleeping). To continue use Reset button on Arduino

}
}

code for slave:
Code: [Select]
#include <SimpleModbusSlave.h>

enum
{     
  PARAM1,    // registers for my 5 numbers
  PARAM2,
  PARAM3,
  PARAM4,
  PARAM5,         
  HOLDING_REGS_SIZE
};

unsigned int holdingRegs[HOLDING_REGS_SIZE];


void setup()
{
  modbus_configure(&Serial, 9600, SERIAL_8N2, 2, 2, HOLDING_REGS_SIZE, holdingRegs);   
}

void loop()
{
   modbus_update();
   
   holdingRegs[PARAM1] = 100;   // we set simple numbers only for simlicity, (can be some input from ATmega)
   holdingRegs[PARAM2] = 200;
   holdingRegs[PARAM3] = 300;
   holdingRegs[PARAM4] = 400;
   holdingRegs[PARAM5] = 500;
}


We must even wait for opinion from someone else..

I have question, so when will be used more slaves, will be this slave code doing colisions?(Or is this function so smart that will wait for ask from master device?)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: KarmaProd on Jan 12, 2015, 07:40 pm
Hello, I am new to Modbus and I'm trying to develop a simple single master/slave circuit, using a couple Arduino Uno, each provided with a RS485 shield. Currently, I could successfully run examples for SimpleModbusMasterV2rev2 and SimpleModbusSlaveV10.

I need just one clarification: what modbus_update() function does?

My guess:
- in the Master sketch, it requests a packet from the slave, and write it to regs[0]?
- in the Slave sketch, it sends a packet to the master? But both holdingRegs[0] and holdingRegs[1] or just one of them? And if both, how can Master Arduino save these data into its ONLY register?

Of course, any help is appreciated, thanks!  ;)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: kakiknya83 on Jan 15, 2015, 10:12 am
hey anyone, I'm newbie on arduino, could you help me!!! i want to connect arduino uno r3 to max485 transceiver and lantronix modbus rs485. how should i wire up for communicating modbus rs485?. i want to monitor temperature and humidity using DHT11 sensor.

thanks
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jan 15, 2015, 12:32 pm
kakiknya83, please look into how to connect up the RS-485 modules you have, either from the product datasheets or online. Once you have done this, then you can make a start to use the modbus protocol.

Remember RS-485 is only an electrical specification, nothing to do with Modbus, except that Modbus can use RS-485, along with other communication specifications, such as TTL async, USB, TCP, RS-232, an dso on.

With the little information you have provided us, do you really expect us to be able to give you precise and exact guidelines? By doing some online research yourself, you will get more information a lot more quickly.

When you mention brand names, which I am assuming 'lantronix' to be, you really should be giving us more details, a link to the exact device you are talking about. The only Lantronix I know of is an inverter made here in Australia, but I don't know what that has to do with temperature and humidity.

If you ask vague questions, you will get vague answers, leaving everyone guessing and assuming.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: brancooo on Jan 15, 2015, 11:51 pm
Hi,
How to read data from more than one slave device, for example from two slave devices?
I have no idea how to do that in master device.
How can looks code in master?

Which way is correct? Create new packet for every slave device, or use only one packet and use function modbus_construct() and change only id?



modbus_construct(packet, id, function, address, data, register array)
Title: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: kakiknya83 on Jan 16, 2015, 02:20 am
dear paul, thanks for your answer. i already fix up about wiring. and now my question is how to read data (temperature and humidity from dht sensor(arduino unoR3 D4) and sending it to lantronix transciever using modbus RS485 protocol.and i use arduino 1.0 series.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Jan 16, 2015, 01:54 pm
Doesn't anyone read the documentation?  :smiley-confuse:
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: brancooo on Jan 16, 2015, 02:08 pm
 Hi JuanB, what do you think about solution for master in #280 (http://forum.arduino.cc/index.php?topic=176142.msg2037885#msg2037885)  ?

Quote
while(!packets[PACKET1].successful_requests){
  modbus_update();
}
Its not nice solution, because it can stack on it..
When I was trying to use only once function modbus_update() it doesnt work for me. I was trying also changing parameters timeout, polling, retry_count and nothing. Only in while loop works..

EDIT:
I try count how many times it will be called until is successful. Its around 254 times. When I change parameters: timeout, polling, retry_count,  it has no effect on it. Any help? Please
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: KarmaProd on Jan 16, 2015, 06:21 pm
Hi JuanB, I hope you can help me. I expressed my difficulties in message #281 (http://forum.arduino.cc/index.php?topic=176142.msg2039922#msg2039922), however I can summarize it through a simple question:

What modbus_update() function does?

My question, apparently trivial, arise because I read the pdf documentation "SimpleModbusMasterManual.pdf" but I couldn't fully understand when and how registers are assigned a value. I believe this part could be improved in the doc, and this might be the chance to write down a couple lines about it.

Below, my full "problem":
Hello, I am new to Modbus and I'm trying to develop a simple single master/slave circuit, using a couple Arduino Uno, each provided with a RS485 shield. Currently, I could successfully run examples for SimpleModbusMasterV2rev2 and SimpleModbusSlaveV10.

I need just one clarification: what modbus_update() function does?

My guess:
- in the Master sketch, it requests a packet from the slave, and write it to regs[0]?
- in the Slave sketch, it sends a packet to the master? But both holdingRegs[0] and holdingRegs[1] or just one of them? And if both, how can Master Arduino save these data into its ONLY register?

Of course, any help is appreciated, thanks!  ;)
Thank you for your contibution.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: RazLobo on Jan 17, 2015, 09:23 pm
Hello all,

I'm having troubles testing example code (A0 potentiometer read and control led on master and slave) with SMM 2V2 library, however same circuit without changes, works succesfully with SMMV12.

In slave side I have SMSV10.

I see that Haxan have troubles with this version too (#239 post, I read all thread) but I don't have luck removing 120 Ohm resistor beetween D+ and D- lines.

I testing this example with a Leonardo (serial1), Mega 2560 (serial1) and a Seeeduino ethernet (Specs here (http://www.seeedstudio.com/wiki/Seeeduino_Ethernet), based on a 328 and programmed by IDE how Duemilanove w/ ATmega328). All of these are tested act as slave or master in order to avoid hardware problems.

Currently I had connected Seeeduino as Slave and Leonardo how master. If I load SMMV12 on Leo, circuit runs well, If I load SMM2V2, don't run.

I add a led in enable rcx/tcx line (pin 2) in order to see comm, apparently there are no change beetween library version, leds blink but don't run well.

Leonardo can control led in Seeeduino but potentiometer on Seeeduino don't alter led in Leonardo (master). There are another issue that I can see, with 2V2 vary potentiometer on master (Leo) vary led on slave and on master.

I have 10kOhm pullup resistor on transceiver (SN75176AP), 120 Ohm between D+ and D- in both sides (slaves and master), 510 Ohm between D+ and GND and 580 Ohm between D- and Vcc (I don't have a 560 Ohm) only on master side. But, I'd comment circuit goes well with SMMV12.

My IDE is 1.0.5 under Debian GNU/Linux, sid version.

Currently my plan is using a Beaglebone black how master, then I don't struggling with this, but I lost most time testing arduino comm in a previous phase and I'm drop in the obligation to ask for solve it. Furthermore, is possible that I need to use Arduino as a master in others projects.

Anyone helps?

Another question, I attach a LCD to seeeduino (slave), is there any method to obtain modbus command received and send and print to LCD? I try with Serial.read() but obtain nothing. (I recently come to Arduino world.)

Sorry for my awfull english.

Salud y Revolución.

Lobo.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tasosstr on Jan 20, 2015, 10:44 pm
Dear JuanB,

Doesn't anyone read the documentation?  :smiley-confuse:
Maybe we loose the logic, if you can make some examples it will be more clear i believe, because you are a master on write code and many of as we are poor on coding  :(

The SMMV2r2  help where it is is ?

I found a pdf manual with this
Code: [Select]
SimpleModbusMaster


SimpleModbusMaster is a Modbus master library that allows Modbus/RTU communication via RS232 or
RS485.
The library has 3 functions namely:
modbus_configure()
modbus_construct()


modbus_update()
To communicate with a slave you first need to create what's called a packet. In commercial PLC software
terms this is usually called a block.


A packet is a struct that contains the relevant information linked to that specific packet. The Finite State
Machine (FSM) running in the background scans each packet in a sequential manner continuously. All
the information needed for the FSM is contained in a specific packet.

Each packet contains the following information:
unsigned char id;
unsigned char function;
unsigned int address;
unsigned int data;
unsigned int local_start_address;
unsigned int requests;
unsigned int successful_requests;
unsigned int failed_requests;
unsigned int exception_errors;
unsigned int retries;
unsigned char connection;



Using the modbus_construct() function you can initialize the packet.

E.g.
modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 6, 0);

The modbus_construct() function accepts the following parameters:

Packet *_packet,
unsigned char id,
unsigned char function,
unsigned int address,
unsigned int data,
unsigned _local_start_address


The first parameter is the packet pointer and points to the address of the packet in the created array of


packets.
The second parameter is the slaved device id range from 0-247 (247 is the standard but can go to 255). 0
is the broadcasting address for function 5, 6, 15 and 16.


The third parameter is the function code. Constants are provided for:


Function 1 -READ_COIL_STATUS 1 // Reads the ON/OFF status of discrete outputs (0X references, coils)
in the slave.
Function 2 -READ_INPUT_STATUS 2 // Reads the ON/OFF status of discrete inputs (1X references) in the


slave.


Function 3 -READ_HOLDING_REGISTERS 3 // Reads the binary contents of holding registers (4X
references) in the slave.
Function 4 -READ_INPUT_REGISTERS 4 // Reads the binary contents of input registers (3X references) in


the slave. Not writable.


Function 5 -FORCE_SINGLE_COIL 5 // Forces a single coil (0X reference) to either ON (0xFF00) or OFF
(0x0000).
Function 6 -PRESET_SINGLE_REGISTER 6 // Presets a value into a single holding register (4X reference).
Function 15 -FORCE_MULTIPLE_COILS 15 // Forces each coil (0X reference) in a sequence of coils to


either ON or OFF.
Function 16 -PRESET_MULTIPLE_REGISTERS 16 // Presets values into a sequence of holding registers (4X
references).



Function 5 uses a whole unsigned int register to write a boolean value.
COIL_OFF 0x0000 // Function 5 OFF request is 0x0000
COIL_ON 0xFF00 // Function 5 ON request is 0xFF00
The fourth parameter is the address to read from or write to.
The fifth parameter is the index of the masters register map. More on this later...
The address, data and local_start_address parameter needs some further clarification.
The address parameter for function 1, 2, 5 and 15 is the number of boolean points. The address


parameter for functions 3, 4, 6 and 16 is an unsigned int index from 0 - 65535. It must be noted
however that some slaves accept the function as explicit or implicit which affects the address range. I.e.
using function 3 as an example, READ_HOLDING_REGISTERS starts at address 40000 which is within the
limits of an unsigned int so referring to address 40000 implicitly refers to function 3 and an address
range of 0 - 9999, but when a slave refers to the function explicitly than the address can range from 0 -
65535.

 
// Create an array of Packets to be configured


Packet packets[TOTAL_NO_OF_PACKETS];

2. Define the TOTAL_NO_OF_REGISTERS to initialize the size of your masters register map.
#define TOTAL_NO_OF_REGISTERS 10
// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];


3. Initialize the packet with the correct information:
E.g.
modbus_construct(&packets[PACKET1], 1, READ_COIL_STATUS, 0, 100, 3);
modbus_construct(&packets[PACKET1], 1, READ_INPUT_STATUS, 0, 1, 0);
modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 6, 0);
modbus_construct(&packets[PACKET1], 1, READ_INPUT_REGISTERS, 0, 6, 0);
modbus_construct(&packets[PACKET1], 1, FORCE_SINGLE_COIL, 0, 1, 0);
modbus_construct(&packets[PACKET2], 1, PRESET_SINGLE_REGISTER, 1, 1, 9);
modbus_construct(&packets[PACKET2], 1, FORCE_MULTIPLE_COILS, 0, 16, 0);
modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 6, 6, 0);

4. Initialize the Modbus FSM:
E.g.
modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets,
TOTAL_NO_OF_PACKETS, regs);

5. Call modbus_update() in loop at least once.

Here is a pictorial view relating to the masters address space, modbus communication and the slaves
address space:

Masters Packet Array
Packet1 - address 0
Packet2 - address 1
Etc...
Masters Register Array
regs[0] - index 0
regs[1] - index 1
Etc...
Slaves Register Array (ID)
F1: Read Coils - 0xxxx
F2: Read Inputs - 1xxxx
F3: Read Holding Registers - 4xxxx
F4: Read Input Registers - 3xxxx
F5: Force Single Coil - 0xxxx
F6: Preset Single Register - 4xxxx
F15: Force Multiple Coils - 0xxxx
F16: Preset Multiple Registers - 4xxxx

modbus_construct(&packets[PACKET1], 1, READ_COIL_STATUS, 0, 100, 0);

Attributes


A single Packet
unsigned char id
unsigned char function
unsigned int address
unsigned int data
unsigned int local_start_address
unsigned int requests
unsigned int successful_requests
unsigned int failed_requests
unsigned int exception_errors
unsigned int retries
unsigned char connection


 
I cut some because of size limit ....

Is this the manual for the last version ?

If yes, personal it is hard to me to understand what for example means the last 0 from this
Code: [Select]
modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 6, 0);
 

In previous version the last 0 was a variable and i can understand better but this i lost it, sorry  :(

If you can do a more complex example it will be better for many people .....

Thank you.  :)  
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: kakiknya83 on Jan 25, 2015, 06:37 am
dear everyone, i'm newbie on modbus arduino. could you help me. i want to read dht11 data from arduino uno r3 and sending it via lantronix. i setup arduino as slave 9600,8N1 and for lantronix as same setup but i can't get the data from dht11. i use modscan software to read it and my question is how to configure dht11 data so it can be read by modscan?

this is my code:
#include <SimpleModbusMaster.h>
//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate

// If the packets internal retry register matches
// the set retry count then communication is stopped
// on that packet. To re-enable the packet you must
// set the "connection" variable to true.
#define retry_count 5

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

//#define LED 9

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  PACKET2,
  // leave this last entry
  TOTAL_NO_OF_PACKETS
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Create a packetPointer to access each packet
// individually. This is not required you can access
// the array explicitly. E.g. packets[PACKET1].id = 2;
// This does become tedious though...
packetPointer packet1 = &packets[PACKET1];
packetPointer packet2 = &packets[PACKET2];

// Data read from the arduino slave will be stored in this array
// if the array is initialized to the packet.
unsigned int readRegs[1];

// Data to be written to the arduino slave
unsigned int writeRegs[1];

void setup()
{
  // The modbus packet constructor function will initialize
  // the individual packet with the assigned parameters. You can always do this
  // explicitly by using struct pointers. The first parameter is the address of the
  // packet in question. It is effectively the "this" parameter in Java that points to
  // the address of the passed object. It has the following form:
  // modbus_construct(packet, id, function, address, number of registers, register array)
 
  // read 1 register starting at address 0 
  modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0, 1, readRegs);
 
  // write 1 register starting at address 1 
  modbus_construct(packet2, 1, PRESET_MULTIPLE_REGISTERS, 1, 1, writeRegs);
 
  // P.S. the register array entries above can be different arrays
 
  /* Initialize communication settings:
     parameters(long baudrate,
      unsigned char byteFormat,
                unsigned char ID,
                unsigned char transmit enable pin,
                unsigned int holding registers size,
                unsigned int* holding register array)

     Valid modbus byte formats are:
     SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
     SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
     SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
     These are already defined in the Arduino global naming space.
  */
  modbus_configure(baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
 
 // pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
 
  writeRegs[0] = digitalRead(4); // update dht11 data to be written to arduino slave
 
  //analogWrite(LED, readRegs[0]/4); // constrain adc value from the arduino slave to 255 by 1023/4
 
  /* You can check or alter the internal counters of a specific packet like this:
     packet1->requests;
     packet1->successful_requests;
     packet1->failed_requests;
     packet1->exception_errors;
     packet2->requests;
     packet2->successful_requests;
     packet2->failed_requests;
     packet2->exception_errors;
  */
}
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Jan 27, 2015, 07:07 pm
Dear JuanB,

Maybe we loose the logic, if you can make some examples it will be more clear i believe, because you are a master on write code and many of as we are poor on coding  :(

The SMMV2r2  help where it is is ?

I found a pdf manual with this
Code: [Select]
SimpleModbusMaster


SimpleModbusMaster is a Modbus master library that allows Modbus/RTU communication via RS232 or
RS485.
The library has 3 functions namely:
modbus_configure()
modbus_construct()


modbus_update()
To communicate with a slave you first need to create what's called a packet. In commercial PLC software
terms this is usually called a block.


A packet is a struct that contains the relevant information linked to that specific packet. The Finite State
Machine (FSM) running in the background scans each packet in a sequential manner continuously. All
the information needed for the FSM is contained in a specific packet.

Each packet contains the following information:
unsigned char id;
unsigned char function;
unsigned int address;
unsigned int data;
unsigned int local_start_address;
unsigned int requests;
unsigned int successful_requests;
unsigned int failed_requests;
unsigned int exception_errors;
unsigned int retries;
unsigned char connection;



Using the modbus_construct() function you can initialize the packet.

E.g.
modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 6, 0);

The modbus_construct() function accepts the following parameters:

Packet *_packet,
unsigned char id,
unsigned char function,
unsigned int address,
unsigned int data,
unsigned _local_start_address


The first parameter is the packet pointer and points to the address of the packet in the created array of


packets.
The second parameter is the slaved device id range from 0-247 (247 is the standard but can go to 255). 0
is the broadcasting address for function 5, 6, 15 and 16.


The third parameter is the function code. Constants are provided for:


Function 1 -READ_COIL_STATUS 1 // Reads the ON/OFF status of discrete outputs (0X references, coils)
in the slave.
Function 2 -READ_INPUT_STATUS 2 // Reads the ON/OFF status of discrete inputs (1X references) in the


slave.


Function 3 -READ_HOLDING_REGISTERS 3 // Reads the binary contents of holding registers (4X
references) in the slave.
Function 4 -READ_INPUT_REGISTERS 4 // Reads the binary contents of input registers (3X references) in


the slave. Not writable.


Function 5 -FORCE_SINGLE_COIL 5 // Forces a single coil (0X reference) to either ON (0xFF00) or OFF
(0x0000).
Function 6 -PRESET_SINGLE_REGISTER 6 // Presets a value into a single holding register (4X reference).
Function 15 -FORCE_MULTIPLE_COILS 15 // Forces each coil (0X reference) in a sequence of coils to


either ON or OFF.
Function 16 -PRESET_MULTIPLE_REGISTERS 16 // Presets values into a sequence of holding registers (4X
references).



Function 5 uses a whole unsigned int register to write a boolean value.
COIL_OFF 0x0000 // Function 5 OFF request is 0x0000
COIL_ON 0xFF00 // Function 5 ON request is 0xFF00
The fourth parameter is the address to read from or write to.
The fifth parameter is the index of the masters register map. More on this later...
The address, data and local_start_address parameter needs some further clarification.
The address parameter for function 1, 2, 5 and 15 is the number of boolean points. The address


parameter for functions 3, 4, 6 and 16 is an unsigned int index from 0 - 65535. It must be noted
however that some slaves accept the function as explicit or implicit which affects the address range. I.e.
using function 3 as an example, READ_HOLDING_REGISTERS starts at address 40000 which is within the
limits of an unsigned int so referring to address 40000 implicitly refers to function 3 and an address
range of 0 - 9999, but when a slave refers to the function explicitly than the address can range from 0 -
65535.

 
// Create an array of Packets to be configured


Packet packets[TOTAL_NO_OF_PACKETS];

2. Define the TOTAL_NO_OF_REGISTERS to initialize the size of your masters register map.
#define TOTAL_NO_OF_REGISTERS 10
// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];


3. Initialize the packet with the correct information:
E.g.
modbus_construct(&packets[PACKET1], 1, READ_COIL_STATUS, 0, 100, 3);
modbus_construct(&packets[PACKET1], 1, READ_INPUT_STATUS, 0, 1, 0);
modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 6, 0);
modbus_construct(&packets[PACKET1], 1, READ_INPUT_REGISTERS, 0, 6, 0);
modbus_construct(&packets[PACKET1], 1, FORCE_SINGLE_COIL, 0, 1, 0);
modbus_construct(&packets[PACKET2], 1, PRESET_SINGLE_REGISTER, 1, 1, 9);
modbus_construct(&packets[PACKET2], 1, FORCE_MULTIPLE_COILS, 0, 16, 0);
modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 6, 6, 0);

4. Initialize the Modbus FSM:
E.g.
modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets,
TOTAL_NO_OF_PACKETS, regs);

5. Call modbus_update() in loop at least once.

Here is a pictorial view relating to the masters address space, modbus communication and the slaves
address space:

Masters Packet Array
Packet1 - address 0
Packet2 - address 1
Etc...
Masters Register Array
regs[0] - index 0
regs[1] - index 1
Etc...
Slaves Register Array (ID)
F1: Read Coils - 0xxxx
F2: Read Inputs - 1xxxx
F3: Read Holding Registers - 4xxxx
F4: Read Input Registers - 3xxxx
F5: Force Single Coil - 0xxxx
F6: Preset Single Register - 4xxxx
F15: Force Multiple Coils - 0xxxx
F16: Preset Multiple Registers - 4xxxx

modbus_construct(&packets[PACKET1], 1, READ_COIL_STATUS, 0, 100, 0);

Attributes


A single Packet
unsigned char id
unsigned char function
unsigned int address
unsigned int data
unsigned int local_start_address
unsigned int requests
unsigned int successful_requests
unsigned int failed_requests
unsigned int exception_errors
unsigned int retries
unsigned char connection


 
I cut some because of size limit ....

Is this the manual for the last version ?

If yes, personal it is hard to me to understand what for example means the last 0 from this
Code: [Select]
modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 6, 0);
 

In previous version the last 0 was a variable and i can understand better but this i lost it, sorry  :(

If you can do a more complex example it will be better for many people .....

Thank you.  :) 
Last digit means corresponding packet:
Code: [Select]
packets[x] where x is number from 0 to TOTAL_NO_OF_PACKETS - 1.

And guys, really read all documentation. JuanB did extraordinaly job here with this library. I know it's not easy for beginner, but try to go trough every example and make some changes, so you will understand.

Regards,
Jakob
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: KarmaProd on Jan 27, 2015, 09:13 pm
And guys, really read all documentation. JuanB did extraordinaly job here with this library. I know it's not easy for beginner, but try to go trough every example and make some changes, so you will understand.

Regards,
Jakob
I found the documentation a little incomplete, especially in the part regarding the modbus_update function. Can you help with my question?

Hi JuanB, I hope you can help me. I expressed my difficulties in message #281 (http://forum.arduino.cc/index.php?topic=176142.msg2039922#msg2039922), however I can summarize it through a simple question:

What modbus_update() function does?

My question, apparently trivial, arise because I read the pdf documentation "SimpleModbusMasterManual.pdf" but I couldn't fully understand when and how registers are assigned a value. I believe this part could be improved in the doc, and this might be the chance to write down a couple lines about it.

[...]

I could successfully run examples for SimpleModbusMasterV2rev2 and SimpleModbusSlaveV10.

[...]

My guess:
- in the Master sketch, it requests a packet from the slave, and write it to regs[0]?
- in the Slave sketch, it sends a packet to the master? But both holdingRegs[0] and holdingRegs[1] or just one of them? And if both, how can Master Arduino save these data into its ONLY register?

Of course, any help is appreciated, thanks!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Jan 28, 2015, 03:56 pm
I think you need to learn few topics about modbus. Master device in modbus network is the boss. Slave devices do what the master device tell them.

So with modbus_update() in the master, you send array of data to all slave devices. Data that you are sending with modbus_update() function depends on modbus_construct() function.

This might not be complete or totaly correct explanation, but I will try to write this just to understand basics of this library.

Let's start with the basic example:
1st requirements


2nd requirements


Now lets take a closer look on 2nd requirements list. Every line starts with "Master wants". Ok so lets start here in the master sketch:

Imagine master device as a postman
(https://dl.dropboxusercontent.com/u/16262939/Datoteke/ForumArduino/Donald_duck.PNG)

1st we need to create some packets to send data from or write data to that packets.

Imagine packets as letters that postman holds
(https://dl.dropboxusercontent.com/u/16262939/Datoteke/ForumArduino/Pisma.PNG)

Code: [Select]
enum
{
   READ_FROM_SLAVE_1,       // Letter 0
   READ_FROM_SLAVE_2,       // Letter 1
   WRITE_TO_BOTH_SLAVES,  // Letter 2
   TOTAL_NO_OF_PACKETS
};

Packet packets[TOTAL_NO_OF_PACKETS];


Be careful! We have only letters without content or address, just blank letters!

We have to create content for these letters (packets). Content is sheet of paper with some informations on it
(https://dl.dropboxusercontent.com/u/16262939/Datoteke/ForumArduino/Prazen_papir.PNG)

Be careful! These sheets of paper are blank!

Code: [Select]
unsigned int regs[3];

Now that we have box of paper with 3 sheets in the box. And we will say that regs[0] is sheet of paper that we send to slave device 1 and this paper will return to us with some informations that slave device wrote on it, regs[1] is same as first, only data will be written on from second slave device and the last sheet of paper - regs[2] we want to send to both of the slaves.

So what do we do now? Well lets try to write addresses on letters and assign different sheets of paper with different letters. Notice, we have to do this for every letter separately.

Code: [Select]
modbus_construct(&packets[READ_FROM_SLAVE_1], 1 - address of the first slave, READ_HOLDING_REGISTERS, 0, 1, 0 - sheet of paper nr. 0);
modbus_construct(&packets[READ_FROM_SLAVE_2], 2- address of the second slave, READ_HOLDING_REGISTERS, 0, 1, 1 - sheet of paper nr. 1);
modbus_construct(&packets[WRITE_TO_BOTH_SLAVES], 0 - broadcast address, PRESET_MULTIPLE_REGISTERS, 1, 1, 2 - sheet of paper nr. 2);


See what we did there? We put first sheet of paper with number 0 (regs[0]) in the first letter (READ_FROM_SLAVE_1) and write an address of first slave device on this letter (1).

We did the same with the second letter.

But what we did in third row with the address 0??? Well address 0 is like if you are sending advertising mail to every one. You know advertising mail from local stores or big markets right? Ok, so with address 0 we want to send some informations to all slave devices connected in the network.

Now we just need to configure our master device
Code: [Select]
modbus_configure(&Serial, baud, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);

See the last value - regs? This is box with our sheets of paper that we just put in the right letters. Leave this and everything will be ok :D

What else do we need? Well, thats pretty much it. In the loop, we must add modbus_update() function, which is just an order for our Donald Duck to go to the first slave, give him a blank sheet of paper, and return it back home with some data on it. Next we send postman to the second slave with blank sheet of paper, so second slave can write information on it. Remember, these two sheets of paper are regs[0] and regs[1]. And if we want send something to the both slaves, we just write that information on the last sheet of paper, regs[2].

Code: [Select]
int slave_one_value = regs[0];   // save value from slave 1 (regs[0]) to slave_one_value
int slave_two_value = regs[1];   // save value from slave 2 (regs[1]) to slave_two_value
regs[2] = 123;   // value 123 will be sent to all slave devices


That was easy right?

Now one more catch here. In the modbus_construct() function right after READ_HOLDING_REGISTERS or PRESET_MULTIPLE_REGISTERS we have 2 numbers. Lets take a closer look at the slave device, and we will explain this later.

Slave device:

Code: [Select]
enum
{
   SEND_DATA_TO_MASTER,
   RECEIVE_DATA_FROM_MASTER,
   HOLDING_REGS_SIZE
};

unsigned int holdingRegs[HOLDING_REGS_SIZE];


This looks one hell similar to the master side, hmm...

Add modbus_configure()

Code: [Select]
modbus_configure(&Serial, 9600, SERIAL_8N2, address 1 or 2, 2, HOLDING_REGS_SIZE, holdingRegs);

This looks partialy similar too..

Now we have everything to establish connection. Check first modbus_configure() function in the master part. We mention earlier that master will try to send letter to first slave. Ok, so master will send sheet regs[0] to the slave 1 (because of the corresponding address on letter right). And now we are at the numbers, that are listed after READ_HOLDING_REGISTERS. First number 0 means on the slave side zero array, so in this case means holdingRegs[0] or if you like holdingRegs[SEND_DATA_TO_MASTER]. Second number means how many data it would like to read. We have 1, so it will read just holding Regs[0]. If this number would be 2, it would read holdingRegs[0] and also holdingRegs[1], but for now we will read just one.

Exactly the same is with second modbus_construct() function. It will read from second slave the same information (holdingRegs[0]).

And the third function, where we said we want to PRESET_MULTIPLE_REGISTER (write to slave), the data will be writen on the array with index 1 (holdingRegs[1] or if you prefer holdingRegs[RECEIVE_DATA_FROM_MASTER]).

In the loop you can modify holdingRegs[0] so master device will get different data like:
Code: [Select]
holdingRegs[0] = analogRead[A0];   // master device will get the data from slave device analog input

You can also read value from the holdingRegs[1] that master already sended to you.

I hope I simplify your work, and you at least partialy understand what I wrote.

TO ALL USERS OF THIS LIBRARY: if you don't know anything about modbus protocol, first search google. There are also few hyperlinks on the first page of this topic I pasted.

Regards,
Jakob
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: KarmaProd on Jan 28, 2015, 08:33 pm
@JUGmobile, thank you very much for this "description for dummies" of the modbus protocol. Even if I don't feel like a noob, I must admit my ignorance in matter of modbus communication. I had read something about it, but your explanation is really helpful.
I will be back on the modbus topic in a few days, I believe I will get a working set up soon then.

Again, thank you,
Karma
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JUGmobile on Jan 28, 2015, 09:33 pm
You're welcome :) this is for all that don't realy understand this library. You know, it was very hard for me when I start, so I know how hard is to understand, I didn't meant to assault you  ;)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jan 28, 2015, 10:21 pm
JUGmobile wrote:
Quote
So with modbus_update() in the master, you send array of data to all slave devices
To clarify this more accurately, when you call from a Modbus master node the function modbus_update() it will perform what is asked in terms of defined packets containing slave address and function codes with pointers to any data to send.

This means, each packet or block will request the addressed slave with a function code which may request or send defined data.

Each packet or block will only address one slave at a time, thus, this is a 'one to many' network topology.

Data may be defined as one of a number of data types as defined by the Modbus protocol, but typical data types used are bits, that represent input switches or relay coils in slave devices as well as 16 bit words which represent registers in the slave device containing data values.

When you call from a Modbus slave device the function modbus_update(), it will check if a Modbus master has called it with a function code request. If so, it will try to complete the request, either by receiving the data or supplying data with the master node.

In a slave device, the call to modbus_update() needs to be at a regular rate from the main loop() with no blocking code that produces lengthy delays, or the master will produce a timeout error for that specific slave addressed.

The above is simply the implementation of the Modbus protocol in Arduino environment, and the implementation will be similar on other hardware platforms with operating systems such as GNU/Linux.

For those who wish to better understand the Modbus protocol in greater detail, you can find excellent documentation at the modbus.org website, specifically http://modbus.org/tech.php (http://modbus.org/tech.php)
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: ashrafh on Jan 31, 2015, 06:19 pm
i am new in modbus rtu what i need is to make a communication between an arduino mega and a protection relay called micom p122 from Schneider the relay can be communicate throught rs485 and have a modbus map can be shown in this pdf ( http://mt.schneider-electric.be/OP_MAIN/Micom/P12x_EN_Da6.pdf) plz i need any help to make the ardunio master code and the hardware circuit
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: nhuythuy on Feb 03, 2015, 04:36 pm
Many thanks JuanB for this easy lib.

I have tested Modbus Slave using Modbus Poll for days :). it works perfectly without any error after two first "Timeout error".

This two first Timeout errors happened to me any time I test. Then it works fine after these first errors.

I tested with Duemilanove board + RS232 communication (using on board USB/Serial adapter)

Could you please explain me this error?

Thank you

Thuy
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: jmj1 on Feb 03, 2015, 07:14 pm
At first: Thank you very much for coding the Simple Modbus Librarys!

I am trying to read a Hamilton Sensor with Modbus RTU over RS-485. I used the V12 of your Library because the debug-info (requests, successful_requests, ...) didn't work for me in 2rev2.

Should I get an answer with this code, or is there a software bug?

Code: [Select]
#include <SimpleModbusMaster.h>
#include <Wire.h>                     //für LCD I2C Library
#include <LiquidCrystal_I2C.h>        //LCD Library

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 100 // the scan rate

#define retry_count 10

#define TxEnablePin 2

enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

Packet packets[TOTAL_NO_OF_PACKETS];

packetPointer packet1 = &packets[PACKET1];

unsigned int readRegs[10];

unsigned int writeRegs[1];

//Variablen für Pausen:
long previousMillis = 0;
unsigned long currentMillis = 0;
long interval1s = 1000;    // 1 Sekunde Interval
long interval3s = 3000;    // 3 Sekunden Interval

void setup()
{
 
  modbus_construct(packet1, 5, READ_HOLDING_REGISTERS, 42090, 10, readRegs);
 
 
  modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
 
  lcd.begin(20,4);         // initialize the lcd for 20 chars 4 lines, turn on backlight
 
}

void loop()
{
  modbus_update();
  unsigned long currentMillis = millis(); // pause
  if(currentMillis - previousMillis >= interval1s) {
    previousMillis = currentMillis;
 
  unsigned int regs[6];
  regs[0] = packet1->connection;
  regs[1] = packet1->retries;
  regs[2] = packet1->requests;
  regs[3] = packet1->successful_requests;
  regs[4] = packet1->failed_requests;
  regs[5] = packet1->exception_errors;
 
  lcd.setCursor(10,0);
  lcd.print(regs[1]);
 
  lcd.setCursor(0,0);
  lcd.print(regs[2]);
 
  lcd.setCursor(0,1);
  lcd.print(regs[3]);
 
  lcd.setCursor(0,2);
  lcd.print(regs[4]);
 
  lcd.setCursor(0,3);
  lcd.print(regs[5]);
 
  lcd.setCursor(10,1);
  lcd.print(readRegs[3]);
 
  lcd.setCursor(10,2);
  lcd.print(regs[0]);
  }
 else
    {
     modbus_update();
    }
}


I tried to use the RS-485 module for Arduino (MAX485 ) from yourduino between the sensor and the arduino, but I don't get a proper answer. I think I baked it  :smiley-red:

Next, I will buy a few MAX48* ICs and try to wire them myself.

Should the code above be working?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: RichardG on Feb 12, 2015, 12:33 am
Hello all

I'd like to first off say I think this is a very well written library, and some very patient folks trying to help all the others out. We Thank you.

I'm also trying to use a shield with the max 485 chip with no luck. I have the slave sketch loaded into a rev 3 mega, everything works as it should when I use a master simulator program (QModMaster). At this point I have a usb cable connected from the computer to the mega usb port. I don't think rs485 is coming into play with this setup. I believe in this setup the connection is acting like a rs232 setup.

When I attach the DFRobot rs485 shield to the mega and connect it to the network, I can see the transmit led blink on the master (Redlion Data Station) and the receive led blink on the mega, but no reply from the mega.

The rs485 shield has a auto/manual switch that is supposed to handle the driver enable. I'm not sure if this is working, or if I need code in the sketch to manually handle it. I didn't see anything in the slave sketch like there is in the master sketch to handle the driver enable.

If anyone has any ideals I would really appreciate it

Regards
RichardG
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Feb 12, 2015, 01:23 am
Quote
We Thank you.
Who is 'We'?

Quote
I don't think rs485 is coming into play with this setup. I believe in this setup the connection is acting like a rs232 setup.
Are you saying this because you have a USB cable between Arduino and computer?
If so, USB has nothing to do with RS-485 or RS-232, so I don't understand what you are trying to say.

Quote
When I attach the DFRobot rs485 shield to the mega and connect it to the network
Describe your network to help us from guessing what you have.

Can you confirm the settings of the RedLion display matches what you expect?
Is it using RS-485 half duplex or full duplex?

You can look in the library documentation for driving the Tx enable and I would suggest it is a preferred method over an automatic switch over from Rx to Tx.

I haven't checked, but I believe the Tx enable will work in Modbus slave mode, and you can check this yourself by looking at the library code.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Feb 12, 2015, 07:40 am
Holy smoke, you guys are busy on the forum!!  :smiley-lol:

I will try to catch up on all the posts...

Firstly:

1. What does modbus_update() do?

Analogy: When you enter your house/apartment the first thing you do is open the front door to enter. (unless you have an 7 month old baby  ;) . The front door allows you to access your house. This is what modbus_update() does. So once you are in you can only do three things or "states" in FSM jargon. The three states are IDLE, WAITING_FOR_REPLY and WAITING_FOR_TURNAROUND.

So blocking modbus_update() in any form of logic in your code is not a good idea. If you want to implement sleep mode or something similar then another function will have to be implemented to monitor when all the packets have been successfully polled. I mentioned sleep mode because users often think they can inhibit modbus_update() and that this will suffice for sleep mode.

2. What does the last zero in modbus_consrtuct() mean?

The last zero refers to the start address of the masters memory block. This memory block is where all the data is stored from the slaves and is also the access point to write data to slaves. The memory block concept should be familiar to you if you program with PLC's.

This local start address variable and its data block representation is implemented in SMM2rev2 and is the only difference between SMM12. In SMM12 you had to assign a register array to each packet. In SMM2rev2 there is only one master memory block and you must assign where the data has to be stored when valid data is received from a slave.

On page 9 you can see a pictorial representation of the address space and communication access between master and slave.

I must confess that the changes in SMM2rev2 although simpler in abstraction has caused much confusion.
I have ported SMM2rev2 to PC C++ as I am busy designing a SCADA system with openframeworks that will communicate with a digital and analogue alarm panel we designed in house for my company. The SCADA source code will unfortunately not be open source but I will keep SMM12 and SMM2rev2 GPL. No future development will be done on these libraries but they are pretty robust already as I have used the SMSv9 code in our alarm panels which will be installed on vessels and industrial equipment. A long story short...
I have realized that the new abstraction in SMM2rev2 has actually made it a bit more difficult to sequentially auto assign my tags to the received data. I am actually considering changing back to individual arrays for each packet but keeping function 5 and 6. This will be the last changes to SimpleModbusMaster.

I will still check in from time to time  ;)
Juan out...
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Eimathew on Feb 21, 2015, 10:30 am
Hey guys,I am interfacing delta HMI with arduino 2560(serial 3 for modbus) implementing your modbus master  library and alas it is working  fine(read holding registers and  working fine).So now I  tweaked the code to implement function 1  to read 16 points or coils.I am using modbus slave simulator(interfaced arduino using USB TO RS232) to observe the packets.Heres the problem observed.

1]master arduino sends the desired request (checked)

2]slave software processes the request and sends the correct reply(checked) (you might be guessing then whats left)

3]master doesnt recieve the repy  :smiley-eek:   :smiley-eek:

4]also the master request lasts for about 1 second only and during this period the slave responds too (observed by RX and TX led blinking on the USB TO RS232 cable)I   have attached the log of this exchange below

Ok so now I went through all post one solution I tried was connected 10k resistor from serial3 RX to VCC but didn't work.I am absolutely clueless what to do next.

And I commend the efforts you put in the document and writing the library
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: mapchen on Feb 21, 2015, 11:51 am
Hi,

thanks for the work done so far. I went through this thread from the beginning. I found that people use Mega and Due but nobody has been talking about using a master slave connection between two nanos.

I have set up the hardware like described. I use two of those to connect the nanos without any additional resistors.

http://www.banggood.com/5V-MAX485-TTL-To-RS485-Converter-Module-Board-For-Arduino-p-912674.html

I tried to use hardware serial with pin 0 and 1. I deployed sketches on nanos then disconnected nanos from PC. Restarted but LED on PIN 9 was not reacting based on changes of voltagelevel which i did on the others analog input A0.

No I am a little stuck because I have not understood how I can best do debugging.

Initially I thought that this would work also with software serial but I have not found a good example on that. Is it only that I need to create a software serial object and in the configurate function I should change the serial object to that?

Can anyone help?

br
Mapchen
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Serentaius on Feb 24, 2015, 03:57 pm
Hi all,

I'm trying to use an Arduino Mega to read the registers off of a device that uses Modbus and then print those registers to the serial monitor or at least be able to read them so I can record them using a SD card shield. For example, I need to read the temperature from a device and record that using modbus on the arduino.

I am using a LC electronics RS-485 converter with the MAX485 chip on it.

I tried to use an Arduino Uno, but I believe that because they only have one serial connection this cannot be done (I tried software serial to no avail). Just wondering where to start? I have read through things and am not the best with Arduino programming so any little bit of advice might help.

Thanks!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: timk__ on Mar 02, 2015, 11:44 am
Hi,

Can someone please post the "trivial changes" required to get this library to work with SoftwareSerial?

Cheers
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: djlimjr on Mar 08, 2015, 02:30 pm
Hi Juan,

I have been trying to something simple and just read information from an RTD modbus module.  I managed to read some information successfully except the data itself.  I think it needs casting but i tried almost everything and it has not worked so far, including the sample you presented on page 12.  Had been stuck for several days already,  could you help?

Here is my code:


#include <SimpleModbusMaster.h>



//////////////////// Port information ///////////////////
#define baud 19200
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 2

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{

 // Initialize each packet
  modbus_construct(&packets[PACKET1], 254, READ_HOLDING_REGISTERS, 100, 2, 0);
 
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
}

void loop()
{

  modbus_update();

Serial.print("reg0:");
Serial.println(regs[0]);
Serial.print("reg1:");
Serial.println(regs[1]);

double temp = (regs[1]<<16)|regs[0];

Serial.println(temp);
  }



The address of the input data is adress 100 and 2 bytes long.


Could you point me in the right direction?

Thanks,

David

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Mar 08, 2015, 03:04 pm
David, is it correct that the slave ID is 254, as I believe 247 is the top limit for modbus?

Also, could you place your code in code brackets, not doing so can give all sorts of smilies.
The code brackets are there in the editor, top row, 7th from the right.

Have a look at this other post where I just posted some code, it might help.
http://forum.arduino.cc/index.php?topic=305248.msg2129761#msg2129761 (http://forum.arduino.cc/index.php?topic=305248.msg2129761#msg2129761)

Code: [Select]
double temp = (regs[1]<<16)|regs[0];
From the documentation on page 7 you will see the following;
Code: [Select]
float num;
unsigned long temp = (unsigned long)regs[0] << 16 | regs[1];
num = *(float*)&temp;

____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: djlimjr on Mar 08, 2015, 03:52 pm
Paul,

Yes,  the slave ID is 254. I tried your suggestions and still does not work...

here is the link for the module....http://www.shjelectronic.com/FTP/Technical_S3600.zip

Am I missing something?

David

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Mar 08, 2015, 10:58 pm
David,

Can you change the address on the device, I read from the technical document it defaults to 254, but like I mentioned, the Modbus specification only allows an unique address range of 1 to 247.

Setting slave addresses is typically started from 1.

Read section 'Limitation'
http://en.wikipedia.org/wiki/Modbus (http://en.wikipedia.org/wiki/Modbus)

Also, while you are trying to test, increase your poll time to say 1000mSec rather than 200mSec, to be sure that enough time is given for the complete request response cycle.

Those units look very similar to the traditional ADAM-4000 models that have been popular over the years.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Mar 08, 2015, 11:34 pm
David,

From the technical document, it is not clear at all how the data is represented, so I can only make an assumption. I don't believe the device is formatting the data to floating point type, there just is not mention of this in the technical spec.

My assumption is that the device maps a temperature range of -200ºC to 600ºC to the raw 16 bit ADC value.
If this is correct, then to understand the data coming back from the device, you need to map it to this range.

The data for the four input channels is such:
Address 100 - channel 1 value
Address 101 - channel 2 value
Address 102 - channel 3 value
Address 103 - channel 4 value

Each channel value would be the 16 bit unsigned integer representation of the temperature range mentioned above.

Change your code so that you only use one register for each input channel, rather then the two you current have. Then, do the mapping with your result being float data type.
____
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: TheKPAXian on Mar 09, 2015, 12:04 am
Hi everybody,

I have read this topic, and learned alot about ModBus. Thank you for that.

Now I have a little (by little I mean HUGE) problem.

I have an Schneider iEM3150 power meter that has ModBus over RS485.
I am trying to read data from the meter using Arduino (I have an Arduino ETHERNET and an Arduino DUE).
Using SimpleModbusMaster_DUE and SimpleModbusMaster (V2rev2) all I get is "failed_requests".

this is the Sketch for DUE
Code: [Select]
#include <SimpleModbusMaster_DUE.h>

// Fineco

#define baud 9600
#define timeout 1000
#define polling 200   
#define retry_count 50

#define TxEnablePin 2
#define LED 8

enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS,
};

Packet packets[TOTAL_NO_OF_PACKETS];
long previousMillis = 0;
long interval = 1000;           // interval at which to blink (milliseconds)

unsigned int readRegs[1];

void setup()
{
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 1637, 1, 0);
  ///// Starting serial for Leonardo
  Serial.begin(115200);
  while (!Serial) { ; }
 
  modbus_configure(&Serial1, baud, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, readRegs);
  pinMode(LED, OUTPUT);
}

void loop()
{
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > 50)
    modbus_update();
  if(currentMillis - previousMillis > interval) {
    //packets[PACKET1].connection=1;
    // save the last time you blinked the LED
    previousMillis = currentMillis;   
    digitalWrite(LED, HIGH);
    Serial.print(";requests: ");   
    Serial.print(packets[PACKET1].requests);
    Serial.print(";successful_requests: "); 
    Serial.print(packets[PACKET1].successful_requests);
    Serial.print(";failed_requests: "); 
    Serial.print(packets[PACKET1].failed_requests); 
    Serial.print(";exception_errors: "); 
    Serial.print(packets[PACKET1].exception_errors);
    int i;
    for(i=0;i<10;++i)
    {
      Serial.print(";Val"+String(i)+": "); 
      Serial.print(readRegs[i]);                         
    }     
    Serial.println();
    digitalWrite(LED, LOW);
  }
}

now all I get in Serial Monitor is:
Code: [Select]
;requests: 5;successful_requests: 0;failed_requests: 5;exception_errors: 0;Val0: 0;Val1: 1001;Val2: 769;Val3: 1637;Val4: 1;Val5: 0;Val6: 5;Val7: 0;Val8: 5;Val9: 0
;requests: 9;successful_requests: 0;failed_requests: 9;exception_errors: 0;Val0: 0;Val1: 2002;Val2: 769;Val3: 1637;Val4: 1;Val5: 0;Val6: 9;Val7: 0;Val8: 9;Val9: 0
;requests: 14;successful_requests: 0;failed_requests: 14;exception_errors: 0;Val0: 0;Val1: 3003;Val2: 769;Val3: 1637;Val4: 1;Val5: 0;Val6: 14;Val7: 0;Val8: 14;Val9: 0
;requests: 18;successful_requests: 0;failed_requests: 18;exception_errors: 0;Val0: 0;Val1: 4004;Val2: 769;Val3: 1637;Val4: 1;Val5: 0;Val6: 18;Val7: 0;Val8: 18;Val9: 0
;

Note: I am using for() loop on readRegs just to try to understand it, to no avail.

I am using an RS485 Breakout with an SP3485 RS-485 Treceiver from SparkFun (SP3485 (https://www.sparkfun.com/products/10124)).
I have also tried with an MAX485CPA+ IC connected according to JuanB's Manual.
Same output with Arduino ETHERNET.
I'm at the end of powers.
Any help/pointing in the right direction will be rewarded with me being able to get some sleep. :)

Thanks you so very much, and sorry for my spelling errors, it Monday, 1 AM and spent the entire weekend finding 1001+ ways to fail at this.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: whitefang027 on Mar 09, 2015, 01:09 am
Hi,
I'm trying to do simple communication between 2 arduino YUN in modbus (just to understand how it works before using it for more complex programs).

I have one configure as a slave storing 1 register with 1 value.
Here the code
Code: [Select]

#include <SimpleModbusSlave.h>

enum
{     
  ADC_VAL,           
  HOLDING_REGS_SIZE
};

unsigned int holdingRegs[HOLDING_REGS_SIZE];

void setup()
{
   modbus_configure(&Serial1, 9600, SERIAL_8N2, 1, 5, HOLDING_REGS_SIZE, holdingRegs);

  modbus_update_comms(9600, SERIAL_8N2, 1);
 
}

void loop()
{
 
  modbus_update();
 
  holdingRegs[ADC_VAL] = 15; // update data to be read by the master to adjust the P
 
}



and one arduino YUN as master who read the value from the slave
The code:
Code: [Select]


#include <SimpleModbusMaster.h>

#define RS485TxEnable 5                     // RS485 modbus direction control pin:
#define baud 9600                           // modbus port speed:
#define timeout 1000                        // modbus timeout in mSec:
#define polling 500                         // modbus scan rate in mSec:
#define retry_count 10

#define TOTAL_NO_OF_REGISTERS 1             // number of registers to poll for:

enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS                       // leave this last entry
};

Packet packets[TOTAL_NO_OF_PACKETS];        // array of Packets to be configured
unsigned int regs[TOTAL_NO_OF_REGISTERS];   // master register array
long previousMillis = 0;
long interval = 1200;
unsigned long currentMillis;
int good_count = 0;

void setup() {
  Serial.begin(9600);                       // start the serial port
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 1, 1, 0);  // initialize packet 1:
  modbus_configure(&Serial1, baud, SERIAL_8N2, timeout, polling, retry_count, RS485TxEnable, packets, TOTAL_NO_OF_PACKETS, regs);
}

void loop() {
  modbus_update();
  currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  {
    previousMillis = currentMillis;
    Serial.print("Exception errors: ");
    Serial.println(packets[PACKET1].exception_errors);

    Serial.print("Failed requests: ");
    Serial.println(packets[PACKET1].failed_requests);

    Serial.print("Successful requests: ");
    Serial.println(packets[PACKET1].successful_requests);
    for(int i = 0; i < TOTAL_NO_OF_REGISTERS; i++)
    {
      Serial.print("Successful Count: ");
      Serial.println(good_count++);
      Serial.print("Reg: ");
      Serial.print(i);
      Serial.print(" Value: ");
      Serial.println(regs[i]);
    }
  }
}


I use RS485 modules from LC electronics, R0 connected to pin0, DI connected to pin1, DE&RE connected to pin D5.

I don't have any result.
I can read the value from the slave using a USB/RS485 adaptator and a modbus librairy
Is there something wrong in my code or is it an issue with the YUN (Serial1 might be different on the YUN?)

Thanks

Tristan
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Mar 09, 2015, 01:27 am
David,

You don't mention what type of Arduino you have, but if you only have an UNO, then it only has the one serial port available.

If this is the case, that you are doing this on a UNO style device then you will need to use the software serial library as well, but this may have problems also if you use it for the Modbus communications, as it may not function higher than 9600 baud reliably.

If you have an Arduino Mega, then you have an additional 3 serial hardware ports to use.
You will setup standard serial comms for printing your results to your computer on the normal serial0 port that is connected to the USB.

For Modbus, you will then use serial1 port and connect that to the EIA-485 module and then to the RTD module.

In your code, you also have not initialised the serial port either, not that you can, as I just mentioned, you can't have both the Modbus and the serial comms to your computer on the same serial port on the Arduino UNO.


If in fact you are using an Arduino Mega, then try the code below which I hope will work for the S3600.
I have included scaling so you should see the 4 channels being printed with both raw data and engineering data as temperature between -200ºC and +600ºC.

Code: [Select]
#include <SimpleModbusMaster.h>

#define RS485TxEnable 2                     // RS485 modbus direction control pin:
#define baud 19200                          // modbus port speed:
#define timeout 1000                        // modbus timeout in mSec:
#define polling 500                         // modbus scan rate in mSec:
#define retry_count 5                       // Modbus retry count limit:

#define P1_REGISTERS 4                      // number of registers to poll for:

enum
{
  PACKET1,
//  PACKET2,
  TOTAL_NO_OF_PACKETS                       // leave this last entry:
};

Packet packets[TOTAL_NO_OF_PACKETS];        // array of Packets to be configured:
unsigned int regs[P1_REGISTERS];            // master register array:
uint32_t previousMillis = 0;
uint32_t interval = 1000;                   // rate of loop():
uint32_t currentMillis;
int16_t good_count = 0;
float RTD_value[3];                         // array of floats to hold 4 RTD values:

void setup() {
  Serial.begin(9600);                       // start the serial port for connection to computer:
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 100, P1_REGISTERS, 0);  // initialize packet 1:
  modbus_configure(&Serial1, baud, SERIAL_8N2, timeout, polling, retry_count, RS485TxEnable, packets, TOTAL_NO_OF_PACKETS, regs);
}

void loop() {
  modbus_update();
  currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  {
    previousMillis = currentMillis;
    Serial.print("Exception errors: ");
    Serial.println(packets[PACKET1].exception_errors);

    Serial.print("Failed requests: ");
    Serial.println(packets[PACKET1].failed_requests);

    Serial.print("Successful requests: ");
    Serial.println(packets[PACKET1].successful_requests);

    for(int i = 0; i < 3; i++)
    {
//      Serial.print("Successful Count: ");
//      Serial.println(good_count++);
      Serial.print("Register: ");
      Serial.print(100 + i);
      Serial.print(" Raw Value: ");
      Serial.print(regs[i]);
      Serial.print(" RTD Value: ");
      RTD_value[i] = (float)(regs[i] * 0.012207) - 200; // equals: (REGISTER * (600 - -200) / (65535 - 0))) - 200;
      Serial.println(RTD_value[i]);
    }
  }
}

____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: TheKPAXian on Mar 09, 2015, 01:22 pm
Hi,

I've got myself an USB to RS485 Converter. Using QModBus querying the Schneider iEM3150 I get "Slave threw exception 'Invalid CRC' or function not implemented."
Using Modbus Poll I get:
Code: [Select]
000000-Tx:01 03 0F B1 00 01 D7 39
000001-Rx:7F 7E 7C 27 FD
000002-Tx:01 03 0F B1 00 01 D7 39
000003-Rx:7F 7E 7C 27 FD
000004-Tx:01 03 0F B1 00 01 D7 39
000005-Rx:7F 7E 7C 27 FD 51 63
000006-Tx:01 03 0F B1 00 01 D7 39
000007-Rx:7F 7E 7C 27 FD 51 63
000008-Tx:01 03 0F B1 00 01 D7 39
000009-Rx:7F 7E 7C 27 FD 51 63
000010-Tx:01 03 0F B1 00 01 D7 39
000011-Rx:7F 7E 7C 27 FD 51 63
000012-Tx:01 03 0F B1 00 01 D7 39
000013-Rx:7F 7E 7C 27 FD 51 63
000014-Tx:01 03 0F B1 00 01 D7 39
000015-Rx:7F 7E 7C 27 FD 51 63

Checksum error or Framing error.

Going nuts...
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Mar 09, 2015, 01:52 pm
TheKPAXian,

In your code you have;

Code: [Select]
unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > 50)
    modbus_update();

Take the modbus_update() function out of the delay loop, put it above, such as;

Code: [Select]
unsigned long currentMillis = millis();
modbus_update();
if(currentMillis - previousMillis > 50)


Also, if you are using a DUE, then remove that part for Leonardo, why have you got that there?
Code: [Select]
///// Starting serial for Leonardo
  Serial.begin(115200);
  while (!Serial) { ; }

Just
Code: [Select]
Serial.begin(115200);

Also, for the DUE, only use the board 'SP3485 RS-485 Treceiver' Transceiver as it is 3.3V and will interface to your DUE. Don't use standard EIA-485 boards that are 5Volt on your DUE.

____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: TheKPAXian on Mar 09, 2015, 02:20 pm
Paul,

I've removed
Code: [Select]
while (!Serial) { ; } and moved the
Code: [Select]
modbus_update(); outside of the condition (last night, by mistake, I've copied the code from an older version of the sketch). Still same results. Also please read my previous post. I've tried querying the meter using QModBus and an USB/RS485 adapter, getting CRC errors....

PS: Is it possible that I have broken the DUE using MAX485 chip at 5V ? It's working, and doesn't seem to be broken.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Nazar on Mar 09, 2015, 08:37 pm
Hello.
Im newbie.
I use Mega 2560 as a Master, RS-485 shield http://www.dfrobot.com/index.php?route=product/product&product_id=1024&search=rs485&description=true
and ELECTRICITY CONSUMPTION METER as a slave http://www.fif.com.pl/pub/File/download/INSTRUKCJE%20[manuals]/ENG/022%20meters/elFF%20WSK%20LE-01MP%20inst%20D131028%20EN.pdf

I want to see parameters over serial monitor on my computer.
Use sample code, but it doesnt work.

Please help with one parameter, others I'll do by myself.
P.S. Sorry for my english.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: whitefang027 on Mar 10, 2015, 05:01 am
Hi,

I've sorted my problem with the following code:
Code: [Select]

#include <SimpleModbusMaster.h>


//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 50

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 4

unsigned int firstRegister(33);
unsigned int nbRegisters(2);
long previousMillis = 0;
long interval = 1200;
unsigned long currentMillis;

enum
{
  PACKET1,
  //PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
// Initialize each packet  function,first register, nb register
modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, firstRegister, nbRegisters, 0);
//modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
 
// Initialize the Modbus Finite State Machine
modbus_configure(&Serial1, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
Serial.begin(115200);
}

void loop()
{
modbus_update();
 
currentMillis = millis();

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;
Serial.println("++++++++++++++++++++++++++++");
Serial.print("Exception errors: ");
Serial.println(packets[PACKET1].exception_errors);
Serial.print("Failed requests: ");
Serial.println(packets[PACKET1].failed_requests);
Serial.print("Successful requests: ");
Serial.println(packets[PACKET1].successful_requests);

for(int i = 0; i < TOTAL_NO_OF_REGISTERS; i++) {
Serial.print("Reg: ");
Serial.print(i);
Serial.print(" Value: ");
Serial.println(regs[i]);
}

float temp;

union u_tag {
   byte b[2];
   float fval;
} u;

u.b[0] = regs[0];
u.b[1] = regs[1];


temp = u.fval;

Serial.print("TEMP => ");
Serial.println(temp);

}
}



I changed the serial baudrate and now it is working.

A new problem arise for me.
I'm reading the temperature from my slave (register 32 & 33) and I got the reply.
The reply is formatted in REAL4.
How can I convert this to float?
I've tried the following
Code: [Select]
float temp;

union u_tag {
   byte b[2];
   float fval;
} u;

u.b[0] = regs[0];
u.b[1] = regs[1];


temp = u.fval;

but it doesn't work

Anyone have a suggestion?

Thanks in advance

Tristan
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Mar 10, 2015, 05:57 am
whitefang027,
Look back up at my post #309
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: whitefang027 on Mar 11, 2015, 11:23 am
whitefang027,
Look back up at my post #309
Thaks so much it worked using:
Code: [Select]

float temp;
unsigned long tmp = (unsigned long)regs[0] << 16 | regs[1];
temp = *(float*)&tmp;
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: whitefang027 on Mar 12, 2015, 03:26 am
Hi everybody

Just a little update to let you know that if you using a YUN, you can't use the modbus on Searil1 and the bridge library at the same time (or at least I didn't figure a way to do that).
I think it is because the bridge between the arduino and linux IC is using the Serial lines as well.
So now I will try to use software serial instead for modbus (knowing that I will be limitted to 9600 bds).

If anyone has more info on this topic, I'm keen to know more.

Cheers

Tristan.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: theodorews on Mar 12, 2015, 09:13 am
Hi everyone!

Im a newbie here, and also new to modbus and arduino.
I am trying to communicate with Irradiance sensor IMT Si-RS485 over rs485 modbus rtu, using arduino uno.
Using the example code of Simple Modbus, I manage to send a request correctly to the slave.
However, there are some problems identifying the slave's response.

Code: [Select]

void waiting_for_turnaround()
{
  if ((millis() - delayStart) > polling)
state = IDLE;
}

// get the serial data from the buffer
void waiting_for_reply()
{
if ((*ModbusPort).available()) // is there something to check?
{
unsigned char overflowFlag = 0;
buffer = 0;
while ((*ModbusPort).available())
{
// The maximum number of bytes is limited to the serial buffer size
      // of BUFFER_SIZE. If more bytes is received than the BUFFER_SIZE the
      // overflow flag will be set and the serial buffer will be read until
      // all the data is cleared from the receive buffer, while the slave is
      // still responding.
if (overflowFlag)
(*ModbusPort).read();
else
{
if (buffer == BUFFER_SIZE)
overflowFlag = 1;

frame[buffer] = (*ModbusPort).read();
/////////////////////// debug
Serial.print(frame[buffer], HEX);
Serial.print("\n");
//////////////////////
buffer++;
}
// This is not 100% correct but it will suffice.



This is to check the data received by the master from the slave, and I got the output that I put as attachment here.

Anyone got this problem before? And could advice what did I do wrong here?

I am using 9600 baud rate and the correct slave response should be: 1 4 2 0 8 B8 F6.

Thanks so much!

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yopicuo on Mar 12, 2015, 02:50 pm
Hello,

One question, Is it possible to change the modbus_configure() function (on librery) to use a softserial port?


Thank you
regards,
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: theodorews on Mar 13, 2015, 06:49 am
Hey everyone!

Just want to update you all,
I figured out the problems: arduino uno only has 1 UART. so I cant use it for both serial monitor and rs-485.
I changed my arduino to mega, using serial0 and serial1. now I can use the serial monitor correctly :)

However, I still have one question:
How do I extract the "slave response" to the sketch?
Is the register_array or regs[size] the array where I store my received frame?

I have read the documentation, but I am still confused.
Any help would be very much appreciated!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Mar 13, 2015, 10:24 am
theodorews wrote :
Quote
I figured out the problems: arduino uno only has 1 UART. so I cant use it for both serial monitor and rs-485.
Might it be that you read more of this post where myself and others keep highlighting this fact to people using the UNO that there is only one hardware UART?

But good that you now have an Arduino Mega and should be able to proceed do what you need to do.

Your next question is not clear;
When you say 'slave response' do you mean the the control data coming back in acknowledgement to the request given by the master? Or do you mean process data that is requested by the master? The two are different.

When you say 'how do I extract', do you mean how to get any returned acknowledgement or requested data for further processing?

You have read the documentation, and say you are still confused, can you be more specifc about what your confussion is with exactly?

What is your code doing correctly and not doing correctly?
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: freman13 on Mar 13, 2015, 12:35 pm
Hi,

I read almost all of the previous posts but still couldn't solve my problem. I am trying to connect MODBUS slave device - Carel uC2 SE (small HVAC controller) to my Arduino UNO (328) with Simplemodbusmaster library, that is connected to MAX485 TTL module. And to read at least single value from it for start.

To summerize it looks like this:

Carel uC2 SE (slave) -> own RS485 converter -> MAX485 TTL module -> Arduino UNO

Here is the MAX485 TTL module i use:
http://yourduino.com/sunshop2/index.php?l=product_detail&p=323


As far as I see, it already have all necessary resistors connected to DI, between bus line, pull-up and pull-down.

And here is the code i used:

Code: [Select]
#include <SimpleModbusMaster.h>

/*
   The example will use packet1 to read a register from address 0 (the adc ch0 value)
   from the arduino slave (id=1). It will then use this value to adjust the brightness
   of an led on pin 9 using PWM.
   It will then use packet2 to write a register (its own adc ch0 value) to address 1
   on the arduino slave (id=1) adjusting the brightness of an led on pin 9 using PWM.
*/

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 2000
#define polling 200 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

#define LED 9

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 1

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

unsigned long previousMillis = 0; // last time update
long interval = 4000; // interval at which to do something (milliseconds)


void setup()
{
  // Initialize each packet
  modbus_construct(&packets[PACKET1], 1, READ_COIL_STATUS, 274, 1, 1);

 
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
 
 
  unsigned long currentMillis = millis();

    Serial.println(regs[0]);

 
}





I managed to connect it and get it to communicate... somehow. I found out that slave's address is 1, and tried to read various random paramaters, data-points, but with no luck.
Arduino's TX and RX LEDs are blinking in 0.5-1s intervals, and when I change slave's address it doesn't blink anymore, so I figure there is some sort of communication.

What I get on my serial are random symbols (when i dont print regs[0]), or various symbols + 0 value when printing regs[0].

I tried changing type of called function as well (READ_COIL_STATUS, READ_INPUT_STATUS...) but with no luck again. For now I am trying to read only digital types of data (ON/OFF). In Carel's manual they are definied with Modbus address and type (Integer, Analog or Digital).

Not sure if I am using library wrong but any help would be appriciated :)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Mar 13, 2015, 01:40 pm
freman13 wrote :
Quote
I read almost all of the previous posts but still couldn't solve my problem.
Best you go back and read them again, yes?

I even mentioned the situation I see you are having in my post just prior to yours.

To give you a hint via a question, how many serial ports has a UNO got?
And then how many serial devices are you trying to connect to this UNO of yours?

Then your code:
Code: [Select]
unsigned long currentMillis = millis()
By itself as you have it, it does nothing.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: freman13 on Mar 13, 2015, 07:46 pm
Hi Paul,

thanks for the response. I was reading all 22 pages but i decided to post my problem anyway, and even now I haven't found solution to it. The closest thing is the one you mention in posts just before my post - where problem was with single serial on UNO. I will try to put MEGA instead and see how it goes.

This...
Quote
unsigned long currentMillis = millis()
...was just remnant of old code that i used for timed event, sorry.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: freman13 on Mar 17, 2015, 09:26 am
So i tried to use MEGA with more serials but still with no luck. I was using this code from whitefang027 (post #320). I just get text on serial0, and can't be sure what is going through bus line to device and back as i don't have oscilloscope. All I can see that 0 packages is received back on screen.

Any ideas what I can do next? Any help is appreciated.

Code: [Select]

#include <SimpleModbusMaster.h>


//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 50

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 4

unsigned int firstRegister(33);
unsigned int nbRegisters(2);
long previousMillis = 0;
long interval = 1200;
unsigned long currentMillis;

enum
{
  PACKET1,
  //PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
// Initialize each packet  function,first register, nb register
modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, firstRegister, nbRegisters, 0);
//modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
 
// Initialize the Modbus Finite State Machine
modbus_configure(&Serial1, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
Serial.begin(115200);
}

void loop()
{
modbus_update();
 
currentMillis = millis();

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;
Serial.println("++++++++++++++++++++++++++++");
Serial.print("Exception errors: ");
Serial.println(packets[PACKET1].exception_errors);
Serial.print("Failed requests: ");
Serial.println(packets[PACKET1].failed_requests);
Serial.print("Successful requests: ");
Serial.println(packets[PACKET1].successful_requests);

for(int i = 0; i < TOTAL_NO_OF_REGISTERS; i++) {
Serial.print("Reg: ");
Serial.print(i);
Serial.print(" Value: ");
Serial.println(regs[i]);
}

float temp;

union u_tag {
   byte b[2];
   float fval;
} u;

u.b[0] = regs[0];
u.b[1] = regs[1];


temp = u.fval;

Serial.print("TEMP => ");
Serial.println(temp);

}
}
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Mar 17, 2015, 12:04 pm
freman13 has this code:
Code: [Select]
unsigned int firstRegister(33);
unsigned int nbRegisters(2);

What is this doing, what are those numbers in brackets doing?

Then:
Code: [Select]
 union u_tag {
    byte b[2];
    float fval;
  } u;

  u.b[0] = regs[0];
  u.b[1] = regs[1];

You define a byte, which is 8 bits and then try to squash a holding register into it, which is 16, that isn't going to work is it. This is not zipping data, it is zapping data.  :)

____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sebus504 on Mar 17, 2015, 03:40 pm
Hello everyone. I'm fresh in the arduino and do not know how to share DS18B20 for Modbus rtu slave (rs485) for the plc.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: copytco on Mar 17, 2015, 06:51 pm
Hi there, I posted a new thread about my problem with this library, but now I find it a better place to ask here, since I have not seen this thread before.

I used old ModbusSlave library since it has function 6 implemented, but since SimpleModbusSlave also has it for a couple of months I decided to test it. Also, ModbusSlave is compatible with compilator version only below 1.0, while SimpleModbusSlave works with the new ones.

Part of the code needed for interpretation can be found below (I use ~50 registers, but left only one to not to make the code too long).

Code: [Select]

#include <EEPROM.h>
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <PID_v1.h>
#include <SimpleModbusSlave.h>
OneWire ds(7);
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

PID myPID(&Input, &Output, &Setpoint,100,20,5, DIRECT);

enum
{     
#include <EEPROM.h>
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <PID_v1.h>
#include <SimpleModbusSlave.h>
OneWire ds(7);
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

PID myPID(&Input, &Output, &Setpoint,100,20,5, DIRECT);

enum
{     
  MAINMENU_MB,
  HOLDING_REGS_SIZE
};

unsigned int holdingRegs[HOLDING_REGS_SIZE];

void setup()
{
modbus_configure(&Serial, 9600, SERIAL_8N1, 1, 1, HOLDING_REGS_SIZE, holdingRegs);
modbus_update_comms(9600, SERIAL_8N1, 1);
}

void loop()
{
  modbus_update();
  switch(holdingRegs[MAINMENU_MB]){
    case (1):
    display_lcd(0,0,"    Manual Mode     ");
    display_lcd(0,1,"                    ");
    delay (1000);
    update_eeprom();
    lcd.clear();
    manual_mode();
    holdingRegs[MAINMENU_MB] = 0;

    break;

    case (2):

    display_lcd(0,0,"     Auto Mode      ");
    display_lcd(0,1,"                    ");
    delay (1000);
    update_eeprom();
    lcd.clear();
    auto_mode();
    holdingRegs[MAINMENU_MB] = 0; 

    break;

    case (3):   

    display_lcd(0,0,"     Setup Mode     ");
    display_lcd(0,1,"                    ");
    delay (1000);
    update_eeprom();
    //lcd.clear();
    setup_mode();
    holdingRegs[MAINMENU_MB] = 0;   

    break;

  default:     
    heat_off();
    pump_off();
}



I use ScadaBR and with an old library there were no problems, but here I can see the slave and ask for values for couple of registers (testing connection via data source in ScadaBR), but when I try to get an individual value of a register as a data point there seems to be no data transfer. Also, I can see TX is not sending any signal then. What can be a problem here?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Mar 18, 2015, 02:13 am
copytco,
It will be very worthwhile if you read the documentation and this thread all the way through to understand what you can and can not do.
There are plenty of examples where you are told not to use what you have in your main loop()
Code: [Select]
delay (1000);
Get rid of them, get rid of all of them, making sure you have NO delay(x) anywhere.

Also, understand how many registers you can transfer with an Arduino based on its limited serial buffer size. If you say you need to use 50 registers, then work out how to do that over several packets.

Code: [Select]
enum
{     
#include <EEPROM.h>
#include <LiquidCrystal.h>
What is that 'enum { doing there ?
You need to carefully look at your code and see that it is in order, mistakes like above are not going to help you at all.

sebus504, welcome to the forum. With so little effort spent on your part to clearly describe what you have and what you want, I won't care to help you.  :P
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: sebus504 on Mar 18, 2015, 07:45 am
Thanks for your interest. This equipment arduino uno with MAX485 on pin 2 and the rx / tx. When I make a example sketch


Code: [Select]
/**
 *  Modbus slave example 3:
 *  The purpose of this example is to link a data array
 *  from the Arduino to an external device through RS485.
 *
 *  Recommended Modbus Master: QModbus
 *  http://qmodbus.sourceforge.net/
 */

#include <ModbusRtu.h>

// assign the Arduino pin that must be connected to RE-DE RS485 transceiver
#define TXEN 2

// data array for modbus network sharing
uint16_t au16data[16] = {
  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, -1 };

/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  u8serno : serial port (use 0 for Serial)
 *  u8txenpin : 0 for RS-232 and USB-FTDI
 *               or any pin number > 1 for RS-485
 */
Modbus slave(1,0,TXEN); // this is slave @1 and RS-485

void setup() {
  slave.begin( 19200 ); // baud-rate at 19200
}

void loop() {
  slave.poll( au16data, 16 );
}


Qmodbus works.
How to set e.g. dallas 18b20 or dht22 to work on modbus rtu

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: copytco on Mar 18, 2015, 08:28 am
rockwallaby, thanks for your answer.

As you see, delay is used only when switched using MAINMENU_MB variable, which is set by default to 0, so it is not executing any delay right now, but this is a good point towards optimization in communication and I will change it into a while loop.

Old library (ModbusSlave) did not produce any errors in communication while buffering all registers, but I will look into the problem.

The part with enum appeared here while I was removing parts of the code that are irrelevant to analyze this problem (I use only one enum, to clarify).

Below, I enumerate changes that I commited when moving from old library to a new one.

1. #include <ModbusSlave.h> -> #include <SimpleModbusSlave.h>
2. ModbusSlave mbs; -> Nothing
3. int holdingRegs[HOLDING_REGS_SIZE]; -> unsigned int holdingRegs[HOLDING_REGS_SIZE];
4. mbs.configure(1,9600,'n',6); -> modbus_configure(&Serial, 9600, SERIAL_8N1, 1, 1, HOLDING_REGS_SIZE, holdingRegs);
5. Nothing -> modbus_update_comms(9600, SERIAL_8N1, 1);
6. mbs.update(holdingRegs, HOLDING_REGS_SIZE); -> modbus_update();

Points 1, 2 and 3 are in library/variable definition part, 4 and 5 in void setup() loop and 6 in void loop().

You can see I changed the enable pin from 6 to 1, since otherwise the slave was not even found by the master when it was set on 6. This pin is not connected to anything.

Surely I will skim through the thread, but I also hope all explanation above may be helpful to catch what is not working here. Thanks again for your time.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: copytco on Mar 19, 2015, 08:18 am
Sorry for double posting, but I made a small step forward towards making it work properly.

All I did was setting enable pin to 99 (as someone suggested many pages before in this thread) while calling modbus_configure(). Now I can get as much as 30 registers "in a batch" when setting 3000 ms timeout. Is there any way to group registers in packets, as it was previously suggested by rockwallaby?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Mar 19, 2015, 10:32 am
copytco wrote asked:
Quote
s there any way to group registers in packets, as it was previously suggested
I recall you can only transfer around 28 registers in one packet, because each register is one word, being 16 bits, being 2 bytes. The Arduino hardware serial buffer is only 64 bytes deep, and by the time you take Modbus overhead into accound, you are left with 56 bytes, being 28 registers. Again, check the docs to be certain. My memory is not always correct.  ::)

What you need to do if you want 50 registers is to set up two separate packets with the second packet following off where the first packet ends so you will get all your regsisters.

Make sure your maximum register count does not exceed this number or you will surely have problems.

I haven't got an example at hand, but I think you will be able to code that up without too much brain-strain.  :)
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: copytco on Mar 19, 2015, 10:45 am
Thanks for your response, rockwallaby!

I will test is in the afternoon, now theoretically thinking I need 2 arrays, each having maximally 28 registers called e.g. holdingRegs1 and holdingRegs2. To make it work should I "double configure" modbus? I mean to do it like this:

Code: [Select]

modbus_configure(&Serial, 9600, SERIAL_8N1, 1, 99, HOLDING_REGS_SIZE1, holdingRegs1);
modbus_configure(&Serial, 9600, SERIAL_8N1, 1, 99, HOLDING_REGS_SIZE2, holdingRegs2);
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Mar 19, 2015, 02:02 pm
Copytco, the answer to your question is on page 4 of the SimpleModbusMasterManual.pdf (https://drive.google.com/folderview?id=0B0B286tJkafVYnBhNGo4N3poQ2c&usp=drive_web&tid=0B0B286tJkafVSENVcU1RQVBfSzg#list).

I was out one register with my previous comment, with only 27 holding registers being able to be set up in any one packet.

No, you only configure a modbus communications channel once, what you have there with two 'modbus_configue(..) is not what you ned to do.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: theodorews on Mar 19, 2015, 02:32 pm
Hi Paul!

theodorews wrote : Might it be that you read more of this post where myself and others keep highlighting this fact to people using the UNO that there is only one hardware UART?

But good that you now have an Arduino Mega and should be able to proceed do what you need to do.

Your next question is not clear;
When you say 'slave response' do you mean the the control data coming back in acknowledgement to the request given by the master? Or do you mean process data that is requested by the master? The two are different.

____
Paul
Thanks for the concern and sorry for disappeared for quite some time!
During that some time though, I managed to sort out my confusion and everything runs perfectly!
I am sorry for not making myself clear though :(

The simplemodbus library is really great! And once I understand the code, it is not as complicated as it seemed! :)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: copytco on Mar 19, 2015, 04:46 pm
Copytco, the answer to your question is on page 4 of the SimpleModbusMasterManual.pdf (https://drive.google.com/folderview?id=0B0B286tJkafVYnBhNGo4N3poQ2c&usp=drive_web&tid=0B0B286tJkafVSENVcU1RQVBfSzg#list).

I was out one register with my previous comment, with only 27 holding registers being able to be set up in any one packet.

No, you only configure a modbus communications channel once, what you have there with two 'modbus_configue(..) is not what you ned to do.
____
Paul
Thanks, this clarified me that the change is needed to be commited on the master side, which is ScadaBR in my case. Changing "Max read register count" and "Max write register count" to =< 28 helped.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: timk__ on Mar 23, 2015, 02:16 pm
EDIT: It was a problem on the slave, my code below works as intended!

Hi there,

I read on post #294 that you can have multiple packets write to the same master register array.  I have tried to do this below, but it seems that only data from the first packet makes it to the array; regs[21] and onward seems to be empty.

On the slave side I can see the correct registers being requested.

Code: [Select]
#define TOTAL_NO_OF_REGISTERS 29

enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
  PACKET5,
  PACKET6,
  TOTAL_NO_OF_PACKETS
};

Packet packets[TOTAL_NO_OF_PACKETS];

unsigned int regs[TOTAL_NO_OF_REGISTERS];

modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 4096, 21, 0);
modbus_construct(&packets[PACKET2], 1, READ_HOLDING_REGISTERS, 4141, 1, 21);
modbus_construct(&packets[PACKET3], 1, READ_HOLDING_REGISTERS, 4152, 1, 22);
modbus_construct(&packets[PACKET4], 1, READ_HOLDING_REGISTERS, 4185, 1, 23);
modbus_construct(&packets[PACKET5], 1, READ_HOLDING_REGISTERS, 4196, 4, 24);
modbus_construct(&packets[PACKET6], 1, READ_HOLDING_REGISTERS, 4203, 1, 28);

modbus_configure(&Serial, BAUD, SERIAL_8N1, TIMEOUT, POLLING, RETRY_COUNT, TX_ENABLE_PIN, packets, TOTAL_NO_OF_PACKETS, regs);


Not sure what I am doing wrong!

Cheers
Title: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: les_well on Mar 27, 2015, 07:41 pm
Hi, Great work with the modbus, it looks just what i need.
I'm new to programming and arduino.
I have the the modbus sample sketch working great.
My setup Master mega2560, with 1 slave Uno r3. Connection is by two max485  shields
like this

max485 shield (http://imall.iteadstudio.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/i/m/im13071001_6.jpg)

I have been struggling with the code for over a week going back and forth over this post. I need some help.

I would like to READ 1-5 digital inputs (button press) on the slave and output on the master via digital output to LEDs

Master to WRITE its own digital input 1-5 (button press) to the slave to light leds.


Your kind help would be much appreciated as i am keen to get this running.

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Mar 27, 2015, 09:57 pm
les well wrote :
Quote
I have been struggling with the code for over a week
Right, and do you believe it is now possible we are able to help you then if you didn't think to include the code in your post? (I fail to understand how in general, people continue to not think to do this).

From what you say:
Quote
I have the the modbus sample sketch working great.
I can only assume that means working great between the two Arduino's with the sample code, right, but not your modifications, correct?

(I'll be away for a few days camping, so others will possibly come to help you)
____
Paul
Title: Help with ModBus RTU Master-Slave: SimpleModbus
Post by: les_well on Mar 28, 2015, 07:15 pm
opps. Here is the code.
 I have chopped and changed it and now i am lost.

This is as far as i am at the moment.

I can send a button press (D5) on slave and display on Master LCD (this works)
Button on Master (D3) should light Slave LED on D13 (this will not work)

Code as follows:
Master:
Code: [Select]
//master mega
#include <SimpleModbusMaster.h>
#include <LiquidCrystal.h>
 
LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );

/*
   Read digital inputs on slave (button presses for now) to the master and light an led on the master.
   then do the same back to the slave.
*/

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

#define LED 13
//#define LED 9

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 1

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
//unsigned int regs1[1]; //added for test0
//unsigned int regs2[1];//added for test1
//unsigned int regs3[1];//added for test2
unsigned int regs[TOTAL_NO_OF_REGISTERS];
int led_value_to_slave1 (1); //Value to store and to be sent to slave1
void setup()
{
  // modbus_construct(packet, id, function, address, data, register array)
  // Initialize each packet
 
  //read data from slave 1 in reg slot 2 and store in regs[0]
 

  //modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 2, 2, 0); //test this line read input 1 to regs0 and 2 to regs1 slave 1 i.e read both reg on slave?
    modbus_construct(&packets[PACKET2], 1, READ_HOLDING_REGISTERS, 2, 2, 0); //test this line read input 1 to regs0 and 2 to regs1 slave 1 i.e read both reg on slave?
    modbus_construct(&packets[PACKET3], 1, PRESET_MULTIPLE_REGISTERS, 3, 2, 3); // send master regs3 to slave1 in address 3 (center value last 3 digits =data?)

   //// modbus_construct(&packets[PACKET3], 1, PRESET_MULTIPLE_REGISTERS, 3, 1, 0); // test send reg[3] data back to slave 1 to control led on slave1
   
    //modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 2, 1, 0);
  //modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 1, 0);
 // modbus_construct(&packets[PACKET3], 1, PRESET_MULTIPLE_REGISTERS, 3, 3, 0);
 
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
  pinMode(LED, OUTPUT);
  lcd.begin(16, 2);
}

void loop()
{
  modbus_update();
 
  led_value_to_slave1 = digitalRead(3); // update data to be written to arduino slave
  regs[3] = led_value_to_slave1;
 
 if (regs[0] ==HIGH){
 digitalWrite(LED, HIGH);
  // LCD
 
 lcd.setCursor( 0, 0 );   //top left
  lcd.print("Slave1 Buttton1 ON");
 //Serial.println("LED is ON");
 }
 else {
 digitalWrite(LED, LOW);
  lcd.setCursor( 0, 0 );   //top left
  lcd.print("                ");
 //Serial.println("LED is OFF");

 }
 
 if (regs[1] ==HIGH){
 //digitalWrite(LED, HIGH);
  // LCD
 
 lcd.setCursor( 0, 1 );   //top left
  lcd.print("Reg[1] on");
 //Serial.println("LED is ON");
 }
 else {
 digitalWrite(LED, LOW);
  lcd.setCursor( 0, 1 );   //top left
  lcd.print("                ");
 //Serial.println("LED is OFF");

 }
 
 if (regs[3] ==HIGH){
 digitalWrite(LED, HIGH);
  // LCD
 
 lcd.setCursor( 0, 0 );   //top left
  lcd.print("Master 1 Button");
 //Serial.println("LED is ON");
 }
 else {
 digitalWrite(LED, LOW);
  lcd.setCursor( 0, 0 );   //top left
  lcd.print("                ");
 //Serial.println("LED is OFF");

 }
 
 
/* lcd.setCursor( 0, 1 );   //bottom left
   //print content of reg x
   lcd.print( regs[0] );
      lcd.setCursor( 5, 1 );   //bottom left
   //print content of reg x
      lcd.print( regs[1]   );
  */
 
  //analogWrite(LED, regs[0]>>2); // constrain adc value from the arduino slave to 255
 // Serial.print("regs[0]");
 // Serial.println(0);
 // LCD
 //lcd.begin(16, 2);
 // lcd.print("hello, world!");
}


Slave:
Code: [Select]
#include <SimpleModbusSlave.h>

/* This example code
*/

#define  LED 13
const int button1Pin = 5; //button1 is on pin D5
const int button2Pin = 6; //button1 is on pin D6

// Using the enum instruction allows for an easy method for adding and
// removing registers. Doing it this way saves you #defining the size
// of your slaves register array each time you want to add more registers
// and at a glimpse informs you of your slaves register layout.

//////////////// registers of your slave ///////////////////
enum
{     
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  ADC_VAL,     //0
  PWM_VAL,     //1
//line added for test of switch button 1 should be at regs address 2
  Switch1_State,  //2
  Switch2_State,  //3
  Led1_state,     //4   store valve from master
  HOLDING_REGS_SIZE // leave this one
  // total number of registers for function 3 and 16 share the same register array
  // i.e. the same address space
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array
////////////////////////////////////////////////////////////

void setup()
{
  /* parameters(HardwareSerial* SerialPort,
                long baudrate,
unsigned char byteFormat,
                unsigned char ID,
                unsigned char transmit enable pin,
                unsigned int holding registers size,
                unsigned int* holding register array)
  */
 
  /* Valid modbus byte formats are:
     SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
     SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
     SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
     
     You can obviously use SERIAL_8N1 but this does not adhere to the
     Modbus specifications. That said, I have tested the SERIAL_8N1 option
     on various commercial masters and slaves that were suppose to adhere
     to this specification and was always able to communicate... Go figure.
     
     These byte formats are already defined in the Arduino global name space.
  */

  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, byteFormat, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(9600, SERIAL_8N2, 1);
 
  pinMode(LED, OUTPUT);
}

void loop()
{


 
  modbus_update();
 
 // holdingRegs[ADC_VAL] = analogRead(A0); // update data to be read by the master to adjust the PWM
  // analogWrite(LED, holdingRegs[PWM_VAL]>>2); // constrain adc value from the arduino master to 255  value FROM master
 
 analogWrite(LED, holdingRegs[Led1_state]); // read led state from master
 
 // or
 
 if (holdingRegs[Led1_state] ==HIGH)
 {
 digitalWrite(LED, HIGH);
   }
 else {
digitalWrite(LED, LOW);
  }
 
 //Read button press and store in reg for master to read Switch1_State
 holdingRegs[Switch1_State] = digitalRead(button1Pin);
 holdingRegs[Switch2_State] = digitalRead(button2Pin);
  /* Note:
     The use of the enum instruction is not needed. You could set a maximum allowable
     size for holdinRegs[] by defining HOLDING_REGS_SIZE using a constant and then access
     holdingRegs[] by "Index" addressing.
     I.e.
     holdingRegs[0] = analogRead(A0);
     analogWrite(LED, holdingRegs[1]/4);
  */
 
}


Your help would be really appreciated. 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: gianni88 on Mar 30, 2015, 11:12 am
hello everyone,


i'm new about modbus comunication, i think i understand how it work, but i have some dubts about how send the data, or well, how encapsulate the information inside the packet, i'm reading the PDF about modbus MASTER but i have one question!

Code: [Select]

modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 1, 1, 0);


if i understand right , the first parameter is the packet i declared before in the enum, second is the address of slave that is to recieve the data (0 is the broadcast), three is the function, four is the begin address register of slave, five is the number of register and six is the position of regs array that contains the data to send to slave!

 for example if i would to comunicate to a slave the packet i have attach, how can i send the parameters? or rather, how can i set the parameters in modbus_construct?

thanks, and sorry for my bad english

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Apr 08, 2015, 10:12 am
Hi gianni88,

Your understanding of the parameters in the modbus_construct() function are correct. To answer your question... the last parameter is the index of the defined data block array of the master. This data array is the two way communication between slaves and the master. Using function 5, 6, 15 and 16 data from this data array is written to the individual slaves. Using functions 1, 2, 3, 4 data from the slaves is stored in this data array. Where the master reads from and stores this manipulated data is controlled by the index of the last parameter in modbus_construct().
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Apr 08, 2015, 12:24 pm
Hi les_well,

Attached are the master and slave sketches that example button presses. It will also reveal how easy it actually is to have two way communication.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: les_well on Apr 09, 2015, 07:50 pm
Hi JuanB. Thanks for that.

Reading this thread over and over a lot of people (like me) find it hard to understand.
My experience is very limited but i have put together the following to HELP other people starting with modbus.
constructing a packet with the correct regs was taxing so here is my attempt at explaining it.

modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 7, 5, 0);
//Hello slave one.
i have created a box to put this in called packet1.
I want you to deliver to me your data in reg 7 and the next 5 regs (total),
please put them in my masters reg starting at reg0

  modbus_construct(&packets[PACKET2], 6, PRESET_MULTIPLE_REGISTERS, 4, 2, 0);
//Hello slave six.
i have created a box to put this in called packet2.
I am delivering to you from my masters reg starting at 0 and the next 2 regs (total).
please put them in your reg starting at reg4

The attached Master and Slave code should demonstrate this.
The code is not pretty, it could be done other ways but with this you should be able to see the regs data, where it comes from and where it is going.



Another tip is to fit an LED to TxEnablePin 2, on the master and slaves. you can see packets being transmitted and a reply (or not) this helped me greatly as if you upload to a slave, the master will time the slave out and stop talking to it. this shows up on the LEDs. just reboot master to fix. (instead of ripping apart your code looking for a problem for the next 2 days)

I hope this helps anyone starting with mosbus.
 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: SteveMoore1883 on Apr 14, 2015, 09:05 pm
Hi All

I have a really quick question. I am trying to communicate with a ModbusRTU device over RS485 using this library. The third party device is showing OK messages, the output of the Serial.println(packets[PACKET1].successful_requests); command is incrementing as would be expected. The register I am reading is a static positive 16 bit data value, however the value which is being returned is not the value in the register. So this leads me to think that I am misunderstanding what to expect.

Firstly here is my sketch:

Code: [Select]
#include <SimpleModbusMaster.h>


////////////////////////////////////////////////////////
// Initialise the Modbus Module
// Port Information
////////////////////////////////////////////////////////
#define baud 9600
#define timeout 1000
#define polling 200
#define retry_count 10

// used to toggle the TxEnablePin 2
#define TxEnablePin 2

#define TOTAL_NO_OF_REGISTERS 1

// Create Packets
enum
{
  PACKET1,
  // PACKET2,
  TOTAL_NO_OF_PACKETS  // Leave last entry it will automatically update
};

// Create an array of packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];
// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

// SD Card Constant
const int chipSelect = 4;

void setup()
{
  Serial.begin(baud);
  Serial2.begin(baud);
  ////////////////////////////////////////////////////////
  // Setup Modbus Communications
  ////////////////////////////////////////////////////////
  // Initialise each packet
  modbus_construct(&packets[PACKET1], 5, READ_HOLDING_REGISTERS, 0102, 1, 0);
  //modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
  
  // Initialise the Modbus finite state machine
  modbus_configure(&Serial2, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
  
}

void loop()
{  
  modbus_update();
  Serial.println("Register value is:");
  Serial.print("DEC: ");
  Serial.println((int)regs[0],DEC);
  Serial.print("BIN: ");
  Serial.println(regs[0],BIN);
  Serial.print("HEX: ");
  Serial.println(regs[0],HEX);  
  Serial.print("Requests: ");
  Serial.println(packets[PACKET1].requests);
  Serial.print("Successful Requests: ");
  Serial.println(packets[PACKET1].successful_requests);
  Serial.print("Failed Requests: ");
  Serial.println(packets[PACKET1].failed_requests);
  Serial.print("Exception Errors: ");
  Serial.println(packets[PACKET1].exception_errors);
  Serial.print("retries: ");
  Serial.println(packets[PACKET1].retries);
  Serial.print("Connection: ");
  Serial.println(packets[PACKET1].connection);
}


I have been expecting regs[0] to hold the binary data value from the register in slave device the value should always be a 357 when cast to an int, however I am getting varying numbers from 292 through to 401.

Is there something obvious which I am doing incorrectly?
As standard are there any operations I need to do on the data before using it for, for example a bit shift? I have checked with the vendor and there are no special requirements from their side for this particular register.

Thanks

Steve
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on Apr 15, 2015, 09:30 am
Dear SteveMoore1883,

A couple of questions:

1. What slave are trying to communicate with? Datasheet?
2. RS485 or RS232? If RS485 what type of break out board or circuit is used?
3. You don't have to initialize Serial2.begin(). Its done for you.
4. What is the address that you want to read from? address 0102 does not make sense. The address is usually stipulated in decimal or hex(which is still just a numerical value). I personally use decimal value for address defining.
5. Double check slave id, address, baud, parity.
6. Good luck...
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: SteveMoore1883 on Apr 15, 2015, 11:10 am
Dear SteveMoore1883,

A couple of questions:

1. What slave are trying to communicate with? Datasheet?
2. RS485 or RS232? If RS485 what type of break out board or circuit is used?
3. You don't have to initialize Serial2.begin(). Its done for you.
4. What is the address that you want to read from? address 0102 does not make sense. The address is usually stipulated in decimal or hex(which is still just a numerical value). I personally use decimal value for address defining.
5. Double check slave id, address, baud, parity.
6. Good luck...
Hi Juan

The problem has mysteriously resolved itself, but here are the answers to the questions below:

1) Firstly, thanks for the help I really appreciate it, the slave device is an ABB ACH550 the manual for the device is fairly large so I will link to it. https://library.e.abb.com/public/84972362110984a7852579aa005961ba/3AUA0000004092_REVI.pdf

2) I am communicating over RS485 and I am using a MAX485 breakout.

3) Thanks for the tip I didn't know that.

4) The ABB device supports zero-based addressing so I can access the registers using a simple register number however in the code I provided it is actually incorrect lol it should have been 102 not 0102.

5) The slave id, baud and parity were all correct.

6) Thanks, well wishes appear to have solved my problem because I have changed nothing, been to bed for a sleep and returned to it this morning after reading this post and it is working flawlessly...

I have no idea what was causing the problem, I just hope it doesn't resurface.

Steve
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rbreuss on Apr 18, 2015, 02:25 pm
Guys, probably Im not only one facing this issue, but I cant find solution still. Im using Simplemodbus master library for communication with energy meter providing data via MODBUS RTU / RS485. Everything works great with Arduino UNO. Now I need to move my solution from UNO to YUN platform. And as you know, YUN has D0 and D1 pins (HW RX/TX) reserved for internal communication with LINUX part of it and there is no other HW serial available at YUN platform. Does is exist any solution, how to solve this issue? Via SW Serial or via any other workaround? Any idea?
Radek
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: LeeOutram on Apr 19, 2015, 04:11 pm
Hi all,

I've read through this thread with some interest. I've previously being using ASCII writes from a remote arduino to a local arduino over RS485 in order to transfer my telemetery but the time has come to add more remote units so I've started looking at Modbus.

Whilst I can get Modbus transfers working fine over 485 with the samples in the thread The issue I am still stuck with is that I'm using barebones Arduino UNO chips rather than fully fledged boards and as we all know they only have one hardware serial port which I must use for other communication on my finished application. I've seen references to making alterations to use the library with software serial or newsoft serial, however, (unless I've missed it) I can't see any examples of how to make this change.

Can anyone post up the modifications in order to make this happen?

All the best,

Lee

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: thousandparadox on May 03, 2015, 04:38 am
Hi i'm having trouble retrieving data from a modbus device.
My oscilloscope seams to indicate that everything electrical is working.
My message is sent through the RS485 link and a response makes it back to the RX pin on my Micro (a Teensy 3.1), i am trying to read 14 slave registers, However its only the response is only ~4 bytes long.
the "regs[]" is empty


Code: [Select]
#include <SimpleModbusMaster.h>

//////////////////// Port information ///////////////////
#define baud 19200
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 100
#define TxEnablePin 2

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum {
  PACKET1,
  //PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};
// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 14
Packet      packets[TOTAL_NO_OF_PACKETS];  // Create an array of Packets to be configured
unsigned int regs[TOTAL_NO_OF_REGISTERS]; // Masters register array

long previousMillis = 0;
long interval = 1000;

void setup()
{
  //---------------pcket arry pointer, node ID, Function,  adress,data,local_adress_start
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 40001, 13, 0); // Initialize each packet
  //modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
  modbus_configure(&Serial1, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);// Initialize the Modbus Finite State Machine

}

void loop()
{
  modbus_update();
  takeAction();
}

void takeAction(){
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval){
    previousMillis = currentMillis;
    Serial.print(packets[PACKET1].address); Serial.print("  ");
    Serial.print(packets[PACKET1].data);Serial.print("  ");
    Serial.print(packets[PACKET1].local_start_address);Serial.print("  ");
    Serial.print(packets[PACKET1].successful_requests);Serial.print("  ");
    Serial.print(packets[PACKET1].failed_requests);Serial.print("  ");
    Serial.print(packets[PACKET1].exception_errors);Serial.print("  ");
    Serial.print(packets[PACKET1].retries);Serial.print("  ");
    Serial.print(packets[PACKET1].connection);Serial.print("  ");
    Serial.println(regs[6]);//printMasterReg();
  }
    
}

The debug output says there requests are failing, 100 retries and 100 failed_requests.

I included my scope image just in case
RX = yellow, TX = blue, /RE,DE = pink.
the reply come within 1 - 2 ms of the /RE,DE line going low, interestingly the polarity is opposite the TX?

I hope it's something glaringly obvious
and thank you!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JuanB on May 04, 2015, 08:49 am
Hi thousandparadox,

I'm not sure if anyone has tested SMM on a cortex M4 but I will provide a few pointers..

1. Make sure of you hardware connections. The documentation describes the correct connections with regards to pull ups and pull downs.

2. In the packet that you are constructing you are assigning 40001 as the starting register but you are already implicitly requesting from address space 4xxxx by using function READ_HOLDING_REGISTERS. Try 0 or 1 depending on the offset.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: DDTechG on May 04, 2015, 09:35 pm
Juan,

thanks for the great work with the simpleModbus library.


I am willing to control one single slave from an Arduino, being the Master. Let's say it is a speed controller.
Depending on certain conditions the master will have to tell the client to set a certain speed, which could be anything from 0 to 5000 or so.
I read the SimpleModbusMasterManual, had a look at the sample and went through all of the posts, but I'm not sure, how I could (should) achieve that. Maybe something skipped my attention.

The way I currently understand it, the commands are being preset in the setup routine and thus kind of "static".
A user haxan had a question that sounded as if it would go in a similar direction (post #215 and following), but he later solved it somehow on his own.
I found Your post #246 where You conditionally set the .connection flag high or low in order to skip or execute certain requests, but how would I set changing setvalues on a function 6 or 16 request?

My idea was to "re"modbus_construct() that packet, but in one of the early posts You said this should not be done.


Sorry if am standing on the line or misinterpreted something wrong.

Thanks for any clarification.


let me know, if You need more information.


Frank
 



 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: DDTechG on May 06, 2015, 04:44 pm
Don't bother, I found it in the class.

function 5,6 and 16 (FORCE_SINGLE_COIL, PRESET_SINGLE_REGISTER, PRESET_MULTIPLE_REGISTERS) can be parametized via the regs[] array. That in combination with .communication = 0 / 1 makes it quite flexible.

I also extended the master class to optionally debug out error codes in case an exception occurs and the client returns a value with it.

reading values works like a charm now. Controlling the device does not yet work. But that's only a matter of properly setting the device. The communication per se works.

:)
 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Claudiaum on May 15, 2015, 08:18 pm
Hello from Brazil, \o\,

I have a question about this library.

In the slave parameters, there is a place called "enum", where the list of registers will be allocated. But from what I have read, the modbus protocol should have 4 lists, 2 for coils and 2 for registers. But I also know that because of the quantities of possibilites, (65535), they have usually change that to only one list and divided that list in 4 parts, something like, from 0-10000 discrete inputs, from 10001-20000, discrete outputs, and more 2 divisions.
My question is, since it appears that this library only implements one list, how can I divide this list in 4 parts?(discrete input, discrete, output, analog input, analog output)/(2 coils, 2 registers). How can I choose the number of the parameter that I'm using even though I only have a few parameters.

Ex:
enum{
Led1,   --> n° 0x0001 , 1
Led2,   --> n° 0x2711 , 10001
A0,      --> n° 0x4E21 , 20001
A2,      --> n° 0x9C41 , 40001
....}


Well, the question part was just that... for now, ^^
I wanna use this library for a project that I have to develop for a class that I'm taking, I just have to prove that a type of protocol can be used and implemented on a easy way, and I wanna make two arduinos Mega 2560 communicate with each other using the modbus protocol.

I'm also looking forward to use this library in a project that I'm starting at my job, but that I'll leave for later.

JuanB, thanks a lot for this library, \o\, and for your kind attention to each one of the people here in this thread, it is really good when someone that created something can help the users.

And of course, thanks to the other users that know way more than the new ones like me and help them in every single question (even on the most easy ones).
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: DDTechG on May 19, 2015, 11:59 pm
Quote
...But from what I have read, the modbus protocol should have 4 lists, 2 for coils and 2 for registers. ... My question is, since it appears that this library only implements one list, how can I divide this list in 4 parts?
those Figures are only the maximum values. See it as the maximum a database can reach and imagine this database consists of four tables, where two of them are for boolean values only (the coils).

Most devices do not use all of these. Some devices do have only implemented one register or even just one of the colis.

You can imagine the prepared array and the enum that is employed for the indices as prepared database requests. Each of these prepared database requests can address a different function, i.e. coil or register that it either reads or writes. So, if You have slaves that implement coils as well as registers, You can easily do that.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: DDTechG on May 20, 2015, 12:56 am
As Juan has announced that there will be no further development of the "Simple ModBus", I started to extend the Modbus Master according to my needs and currently see myself ending up with a complete rewrite.... guess I've already done that.

My Modbus Master has now become a true class that encapsulates all of its functionality and only exposes the properties and methods that are meant to be public.

The connection property now has several tasks and is being used bitwise. I can now defer calls which become active automatically upon the next start of the call chain. This is important if You need to make sure that certain (non regular) calls are being made in a specific order.

Additionally calls can now be set as single calls that will be deactivated automatically when done.

Finally a callback-Method can be provided that "fires" whenever one of the calls finishes with either success or failure. This allows for a much more event driven approach without the need to permanently poll and check the current status.

I'm currently doing this for my personal needs, but if You're interested in more on this, drop me a note.


I also think I found a design flaw in Juan's Code. He is talking of a three state mashine, but - if I got the specs right - it's actually just a two state machine, having "idle" and either "waiting for reply" OR "waiting for turnaround" depending on whether sending in unicast or broadcast mode instead of "idle", "waiting for reply" AND "waiting for turnaround", as implemented in the SimpleModbus Master

Maybe someone can check and confirm this. You'll find it in the "Modbus over serial" specs in figure 7 and 9 and the comments.

Following this find, I've changed the lines

Code: [Select]

  state = WAITING_FOR_TURNAROUND;
  delayStart = millis(); // start the turnaround delay


in processError() and processSuccess() to

Code: [Select]

  initTurnaround();



where initTurnaround() is a simple branch:

Code: [Select]
void initTurnaround(){
  // DD 2015-05-08
  // init TURNAROUND delay, but only
  // for broadcast-messages
  // -> processError() / processSuccess()
   
  if (packet->id == BROADCAST_ID){
       // has this been a broadcast message,
       // then give the clients some time to
       // process
       state = WAITING_FOR_TURNAROUND;
       delayStart = millis(); // start the turnaround delay
       
   }  else {
       // no broadcast message, then return to IDLE mode
       state = IDLE;
   } 

}



(BROADCAST_ID comes from a #define statement I added with a value of 0)


Since I did that little change, the communication is much more responsive.

regards

Frank


Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: LeeOutram on Jul 05, 2015, 09:05 pm
Hi all,

I've read through this thread with some interest. I've previously being using ASCII writes from a remote arduino to a local arduino over RS485 in order to transfer my telemetery but the time has come to add more remote units so I've started looking at Modbus.

Whilst I can get Modbus transfers working fine over 485 with the samples in the thread The issue I am still stuck with is that I'm using barebones Arduino UNO chips rather than fully fledged boards and as we all know they only have one hardware serial port which I must use for other communication on my finished application. I've seen references to making alterations to use the library with software serial or newsoft serial, however, (unless I've missed it) I can't see any examples of how to make this change.

Can anyone post up the modifications in order to make this happen?

All the best,

Lee
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Manidhar on Jul 07, 2015, 07:48 am
Hai to everyone,

I am newbie to arduino modbus,

is Modbus library working with arduino UNO??.

I am using Arduino UNO and RS485 ic, Arduino IDE V 1.6.4.

I am following this forum but i am not communicate two arduino's.

I am tried example of modbus.

and iam not understanding what register is reading and which is writing .

please help me to complete my project.

my connections are below attachment. 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Manidhar on Jul 07, 2015, 08:32 am
Any one can send the Arduino UNO working code Master and Slave.

Thanks.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: aleszu on Jul 07, 2015, 12:05 pm
Hi Sytex,

did you ever manage to get this working with these MAX485 modules ? I have the same modules, using 2 megas for testing, but can't get them to talk to each other. I can see master transmitting messages on tx led, but rx led never lights up on slave side ... Tried everything ... I don't know how to find the problem (don't have oscilloscope). On the code side - i'm just trying to get basic examples working (provided with library).
Modules work (at least in one way - master to slave)  - i can put data through pretty reliably with simple example with soft serial from this page: https://arduino-info.wikispaces.com/SoftwareSerialRS485Example

I'm really stuck with SimpleModbus. Any help would be appreciated.

Best Regards,
Ales

Hello Everyone!

My problems are hardware related maybe, but I post it here if someone knows the solution.
I use these type of Serial - RS485 converters, which uses MAX485 chips:
(http://bartanet.hu/rumli/link/arduinoforum/modul.jpg)

It has this schematics:
(http://bartanet.hu/rumli/link/arduinoforum/schematic.jpg)

My network:
Mega2560, MasterV2rev2 (I think this is the latest)
Nano, SlaveV10, modified to use software serial, so i can ddebug on HW serial.

My Packets:
Code: [Select]
 modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 8, 0);      //001 GET SOLAR CELL CURRENTS
  modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 8, 8, 8);   //001 SET SOLAR CELL DIODES
  modbus_construct(&packets[PACKET3], 1, READ_HOLDING_REGISTERS, 16, 5, 16);    //001 GET COMM ERRORS


This is what I RECEIVE on SLAVE side:
(http://bartanet.hu/rumli/link/arduinoforum/slavereceive.jpg)

As you can se, the slave receives a zero, after it transmits anything, and at every received packet end there is a trailing/closing zero too.
For this reason Function16, Write registers, my PACKET[2] never runs because this statement never gets true:
Code: [Select]
if (frame[6] == (buffer - 9))
Because my buffer is longer with one character (the last zero)

I took my logic analyzer, and attached to the serial buses:
(http://bartanet.hu/rumli/link/arduinoforum/logic1.jpg)

Lets zoom in a bit:
(http://bartanet.hu/rumli/link/arduinoforum/logic2.jpg)
As you can see while the Master transmits (TXEnable is enabled), the Master's RX Pin is high, and the Slave's RX pin stays high, after the data, and this causes the trailing zeros.

Let's see the response:
(http://bartanet.hu/rumli/link/arduinoforum/logic3.jpg)
Here you can see, that the Slave start to transmit, his RX pin goes high too, it get to RX buffer as a Zero, and causes the received single zeroes after each transmit.


The examples shows this is not related on that I modified the Slave libary to use SW serial, because this fault exists on both sides. And think I have to achieve, that MAX485 should not pull up the RX pins while there is some traffic on the bus.

All I would be grateful for any help!!

Thanks for reading it!

If you need more code, measurements, outputs, please ask!

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Manidhar on Jul 08, 2015, 06:20 am
hi every one in the arduino forum,

Is the Modbus library is working in the arduino uno ???....
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: lomassubedi on Jul 08, 2015, 10:20 am
Hello jaun,
First of all, thank you for creating the library. Among various libraries, your library seems efficient.
I'm new to arduino and just literate in C programming. I was trying to setup communication between my arduino and Delta VFD : http://www.delta.com.tw/product/em/drive/ac_motor/download/manual/DELTA_IA-MDS_VFD-M_UM_EN_20141021.pdf

I studied RS485 in detail, it was no problem understanding it. But later on I found that  modbus is used as an application layer. Then I collected basic information regarding RTU/ASCII frame structure, network topology etc. And then I started for implementations using arduino. I downloaded the library, studied couple of pages in forum but not understood sending a byte of data to slave from the master and receiving response. Even though example codes seems annoying to me since I'm not finding the way to write a byte into slave register. I was not planning to send mail or comment in the forum but frustration led me to do this. I will be continuing my study on same thread. Please send me the relevant information or links regarding the easy usages of your library.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jul 09, 2015, 01:02 am
lomassubedi. you might like to make contact with DDTechG, he has re-written or should I say, enhanced the ModbusMaster portion of the SimpleModbusMaster library.

Take a look at reply #363 here on this thread.

DDTechG made quite some improvements and uses it for his own needs of communicating with a VFD.

I would like to promote it as it seems DDTechG has carefully looked into existing small issues with the existing SimpleModbusMaster.

I am guessing you are trying to send data, say a setpoint, to the VDF, correct ?
Then you will need to use a Modbus master library, not a Modbus slave library.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: lomassubedi on Jul 10, 2015, 11:37 am
rockwallaby, thanks for the reply :).

Just uploaded master and slave codes into two Unos, checked the result. It works for initial status of the analog input at channel 0 but it does not gets updated though it is in the forever loop. In reply #363 custom edition by DDTechG, I could not understand his codes and the explanations. Also the library captures hardware serial and creates barrier in Serial terminal debug.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jul 10, 2015, 01:01 pm
Quote
Also the library captures hardware serial and creates barrier in Serial terminal debug.
I don't understand what you mean by this.

To use the library from DDTech, you need to make contact with him, Frank and ask nicely for the library.

In any case, the existing library as Juan has made should still work for you well enough.

Make sure you have no, I'll repeat that again 'NO' delay(x) in your code where the x is larger than a few mSec.
In fact, you should avoid all use of the delay(x) statement while using Modbus, and generally speaking also for good code.

Next, if you are using the UNO, then you only have one serial port, so you can not be using Modbus and doing serial.prints(..) in the same program, it simply does not work like that if you are.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: berkelium on Jul 10, 2015, 08:17 pm
I have used the SimpleModbus library successfully on the Uno configured as a Modbus slave device and using a MAX485 IC.

The problem I am having is using the library alongside another which communicates with a MPL3115A2 I2C Barometric Pressure/Altitude/Temperature sensor (Adafruit Product ID 1893)

I built one sketch to test the Modbus slave functionality, then another to test the MPL3115A2 sensor functionality separately, and both of these sketches worked perfectly.

However, after combining the sketches into one, I no longer can communicate with the Uno via Modbus. I have been trying to figure out how I can get the two pieces to work together, but I am stumped. Obviously some task management is required, but I am not sure what to do.

Am I asking the Arduino to do too much?

Any assistance would be greatly appreciated. Thanks!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jul 11, 2015, 01:17 am
berkelium, welcome to the forum.

No, you are not asking too much of the Arduino at all, you'll be amazed at all the things it can do.
I have seen some complex programs for these little things. Some are complex because of bad coding, others, just good complex code.

I think, like I have mentioned many times now, even above, any use of the delay(x) statement will likely mess up the operation of Modbus. So, I bet either you have put in something like a delay(x) in your code or it is there from Adafruit.

Or, simply, you haven't merged the two codes together in a way that allows it to work.
I don't know the MPL3115, but being an I2C device, I see no reason for your code not to work if you have merged them correctly.

Speaking of which, where is your code ?
Please, if you present your code, put it in code tags, the first on the top right in your reply editor.

Also, are you wanting the UNO to be modbus slave or master ?
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: berkelium on Jul 14, 2015, 07:52 am
Thanks rockwallaby for the kind welcome and the assistance. Very much appreciated.

I took a second look at the code this evening and there were some delay() calls with in the MPL3115A2 library, but each of the three calls only had a value of 10. I commented out these lines and uploaded the sketch, but no luck.

Then I started commenting out code and found that nothing was really working. I decided to try each test sketch again. I tried the SimpleModbus slave sketch and it worked. Then I tried the MPL3115A2 sketch and to my surprise it did not work. This sketch reports its data to the serial console and it was telling me it couldn't connect to the sensor.

I decided to recheck my wiring and it turns out SDA and SCL were crossed!! Boy do I feel dumb  :smiley-red:

After banging my head on my desk a couple times for good measure I went back and tested my combined sketch and (Queue the choir...) IT WORKED!

I am always amazed at what the Arduino can do. It is an awesome platform.

To answer your question, I want the Uno to be a Modbus slave. I work for a company that manufactures RTUs and it is always nice to have live data in hardware demos. Instead of having to lug around an expensive field transmitter, I would like to have an inexpensive and light device to use. The Arduino fits the bill nicely.

If you are interested in the sketch, or anyone else for that matter, please let me know.

Thanks again Rockwallaby for your help. Cheers Mate! 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: mrUnfused on Jul 14, 2015, 12:52 pm
Hello DDTechG and modbus users  :) !
Reading posts on the thread "Help with Modbus RTU", I came to know that you can help me regarding modbus control of motor using VFD. So far I have tested peer-to-peer modbus RS458 using couple of arduino UNOs and SP485EC line driver IC. So I have some confusions about using modbus in my system. I have listed them below.

1. It is said that dealy(x) messes up the modbus operation. It even worked when I inserted a delay(x) inside loop(). Can we use smaller delay (about 1ms - 10ms) inside loop() in our program?
2. In my system I need to interface 3 proximity switches, a 1024 Pulse Per Revolution incremental encoders and some LEDS along with system being modbus master to a VFD. I have interfaced A and B of encoders to two available hardware interrupts of UNOs in " State change triggering" mode. Will modbus gets affected by the execution of ISR due to back and forth occurrence of encoder pulses? Or do I need to leave an UNO just making it a modbus processor and carrying all other tasks by other UNO ?

Thanks.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jul 15, 2015, 04:03 am
berkelium, great to hear, and thanks for the update as to what you found and how you got it finally working.

I see the MPL3115A2 is a precision altimeter, nice device, that can measure to very fine increments of altitude :)

I wonder what sort of RTUs you guys make then ?
Yes, live demonstrations with read data are definitely more attractive.
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jul 15, 2015, 04:10 am
mrUnfused: with a slave, avoid use of long delay(x).
With Modbus master, it may be less of an issue as the master is the device doing the polling.

In any case, for good, you really do want to avoid any use of delay(x) on your code, whether in the main loop or elsewhere. Remember a delay(x) means just waste time and nothing can happen, except certain interrupts.

Instead, use smart methods to time your code if that is what you need.

With interrupt functions, keep your code in them as small and exact as possible, do all the heavy processing out of the ISR.

There should be no problem with three prox sensors, a quadrature encode and being a Modbus master, no problem at all.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: gerasalus on Jul 16, 2015, 08:58 am
So i've read all thread, and now have some questions.

My intent is to have Arduino Nano or Pro mini as slaves and Raspberry Pi as master.

1) Nano has only one serial (Pro Mini also if i understand correctly), so i cannot debug it via usb while at the same time using with ModBus. But i can use that single
serial for modbus explicitly, when i disconnect nano from usb. Just there won't be any way to troubleshoot it?

2) There are a lot of mentions that SoftwareSerial can be used instead of hardware, and it's even stated that "Porting the modbus library to accept SoftwareSerial is trivial though." and there are a lot of questions asking if anyone has ported it, but either no one managed, or no one has shared it?

3) I have these RS485 modules http://yourduino.com/sunshop2/images/products/detail_323_RS485-Arduino-Module3-512.jpg (http://yourduino.com/sunshop2/images/products/detail_323_RS485-Arduino-Module3-512.jpg) . So if i understand correctly i don't need any resistors except 120ohm termination resistor?

4) Raspberry pi part. This seems to be working with libmodbus. What hardware should i use? Simple usb to rs485 converter?

Edit:
it seems that SoftwareSerial has the same interface as HardwareSerial. Are there any gotchas if simply replaceing SoftwareSerial with HardwareSerial? Does flush work the same on both?

Thanks!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jul 16, 2015, 10:47 am
Quote
"Porting the modbus library to accept SoftwareSerial is trivial though."
I don't recall any mention of having to port the modbus library to work with the software based serial. There may be issues using SoftwareSerial at higher than 9600bps. It would be better to put your Modbus onto the hardware based serial and any debugging you want to SoftwareSerial.

If you program it correctly, there should be little to debug, do some initial tests with your code and then implement Modbus once you know your main code is fully functional.

Yes, just termination resistors, you need them at both ends of the EIA-485 network cable, so, in your case, RPi and Arduino.

What have you got on your RPi with libmodbus, I'm curious ?
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: gerasalus on Jul 16, 2015, 12:51 pm
I don't recall any mention of having to port the modbus library to work with the software based serial.
Well the quote is from JuanB. But ok, i'll try going with hardware serial.

What have you got on your RPi with libmodbus, I'm curious ?
I think i made myself a bit unclear. "This seems to be working with libmodbus." = "People have got working modbus by using libmodbus on raspberrypi"

My ultimate goal is to control underfloor heating system actuators from raspberry pi (via relays). Arduinos would feed temperature information from rooms and raspberry pi would controll the actuators based on configuration provided via web interface.

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: gerasalus on Jul 17, 2015, 09:17 am
rockwallaby would you be willing to share code from rpi with libmodus? Are you using modbus via usb converter? or via raspberry gpio pins?
I'm particularly interested in  Tx enable pin part on rpi
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jul 17, 2015, 11:33 am
Hi gerasalus, yes, I am willing to share code, no problems with doing that. The code I am developing, operates on many different platforms, basically any ARM based board running some form of GNU/Linux, or any Intel 32/64 running some flavour of GNU/Linux, or Mac OSX.

I was curious about your plans for using libmodbus on RPi, because it might be that what I am doing might be of some interest and maybe some help for your home heating control and monitoring system.

I am in the process of helping another person who is doing pretty well that, in-conjunction with a full off grid solar system. We are using Arduinos for the low level control and Cubieboards for the next level up. The Cubieboard talk to Arduino's or other devices via Modbus, so you can have a whole network of devices connected back to the main system.

The software I am developing can be setup to use either Modbus TCP or Modbus RTU, both with libmodbus.
With Modbus RTU, that means anything essentially async serial, like TTL, RS-232, EIA-485, USB, so on.
With Modbus RTU communications, you can specify the EIA-485 Tx enable output pin.
Modbus TCP is just that, TCP, meaning Ethernet.

Maybe you looked at my signature already to know something ?

Anyhow, if you are interested, have a look or ask.
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: gerasalus on Jul 17, 2015, 12:26 pm
ok rockwallaby, you're miles ahead:) And that solar project looks awesome.

I'll see what i can do with modbus. I don't have rs485 to usb, and it will take month or so to arrive from aliexpress, so in the meantime i though i could hook up my current rs485 shield that i use with arduino on raspberry.
One quick hacky option would maybe to use arduPi and this modbus library on rpi, not sure how that would work out :)

Do i need to worry about voltage on raspberry (3.3 vs 5v for rs485) ?

Yesterday i tested two Pro Minis (master/slave) via modbus - works perfectly. Thanks all for contribution and examples:)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: gerasalus on Jul 17, 2015, 05:00 pm
Ok one more question.

Let's say i have 10 slaves:
5 of them report temperature and humidity (basically they are the same)
2 of them report only temperature
1 reports light intensity
1 reports temperature, barometric pressure.

What would be the modbus design for this? Should i have 10 different packets? Or only 4 (based on different available slaves?).
If i understand correctly i can read address and id from the packet?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jul 18, 2015, 01:32 am
On your master you will need a packet for each slave, so ten packets.

This assumes the data on your slaves will be of the same modbus type and also within the same address range limitations on the 64byte serial buffer in an Arduino.

What this means is:
If you are reading 'holding registers' and 'input registers' from a slave, then each will need a packet defined.
If you are reading 'holding registers' and also writing 'multiple registers', again, a separate packet for each.

I think you will need the system so you can read data from each Arduino thermostat as well as send setpoint data to each, correct ?

The other condition is not so much a problem for small Arduino projects, but say for example you need to read from 'holding register' address 1 as well as 'holding register' address 32, then that will need a packet for each as 31 holding registers separation, with each register being a 16 bit word, this equates to 62 bytes. With the overhead of the protocol, this exceeds what the Arduino can send using a single packet structure.

I expect if you design your modbus mappings correctly, and understanding you will need to also send data to the Arduino thermostats, you will need a total of 20 packets.

Now, the packet structure is based on you having an Arduino as master and using a modbus master library.
But, I recall you are wanting to use a small GNU/Linux board, RPi and will therefore be not using any Arduino master library, but instead the libmodbus library.

With this library, you will do things differently.
You will open the port with the correct configuration.
You then make a connection to the port.
You then make a read call, reading the registers you need.

So, your code on the RPi will be very different and will not use the same packet definitions as you might read about here. You code on each Arduino will be modbus slaves.

Are you having an Arduino as master or will you just use the RPi as master, as both ideas are valid ?
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: gerasalus on Jul 19, 2015, 01:24 pm
rockwallaby thanks for very detailed explanation!

For v1 thermostats would only report temperature and humidity, so slaves would only report data to the master, and master would control the relay. If all goes well, then further enhancement would be adding an lcd display, etc... but first i want some MVP working.

My initial idea was to use raspberry pi as a master (since i already have one lying around) via rs485 usb adapter - gather data from slaves, and then raspberry pi would control the relay and relay would trigger actuators. But upon your suggestion i think I'll get Arduino Uno as a master (cause it's cheap), and lan adapter and hook everything to it (both modbus and relays). For controlling Uno i would expose simple json api (i thought i saw some web server libraries for arduino) which would report thermostat data, and a rest api through which you would trigger relays.

The core "logic" would sit on raspberry (since i already use is as some sort of home server) and be accessible via web.

I've ran some simple tests over the weekend with two arduinos connected together (master/slave - slave every 5000 loop iterations reverses a flag to 0 or 1 and sends it to the master which triggers on board led based on the flag - on/off), and there are some connection problems, cause sometimes after half an hour, sometimes more ,the master marks slave as non responding. It seems that at some point 10 failed connection attempts are reached. (e.g. stats: requests: 1637 successful_requests: 1431, failed_requests: 206).

But maybe it's because I've connected them directly via rs485 adapters without any resistors.
Setting packet.connection = 1 on each loop fixes the problem (i know, it's a hack). But since i don't have big timing requirements IMHO that should not be a problem.

Other thing .. how accurate the DHT22 sensors are. I somehow feel that i might have problems there. But we'll see.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: berkelium on Jul 22, 2015, 06:50 pm
@rockwallaby: Yeah the MPL3115A2 is pretty sweet  :)

To answer your last question, the company I work for manufactures an RTU that includes a wide range of TCP/IP services like an integrated web server, ftp client & server, firewall, SMTP/POP3 support, VPN client and server, etc. It has an optional integrated 2G/3G M2M modem that allows users to not only access the device via the cellular network, but also use SMS to push alarms and events. It is a pretty awesome little unit (But I might be a tad bit biased  :) )

I do have another question regarding serial ports. Up until now I have been using Pins 0 and 1 on the Uno for the Modbus slave application, having to disconnect the RS-485 connections during uploads. This has been fine up until now, but moving forward I do not want to open a finished unit up and disconnect the RS-485 connections just to make changes to the sketch.

If I read correctly, the Leonardo does not use Pins 0 and 1 as the USB connection is virtualized in the 32U4 chip. Would using a Leonardo be a possible solution? Do you have any other suggestions on how the Uno could handle both the RS-485 and the USB connection?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: AlexNester on Aug 01, 2015, 06:20 pm
Hi all

Arduino Due (as master)
and slave work normal thanks library.
but faced with the problem.

I'm Using programing port for transmit data from computer to arduino and transmit data to slave (ModBus).

So, Atmel chips have a comport error rate of 2%, so we need here a checksum

and need this functions for checksum

Code: [Select]
bool CheckChecksum() //Atmel chips have a comport error rate of 2%, so we need here a checksum
{
byte checksum=0;
for(int z=0; z < 3; z++)
{
byte val=commandbuffer[z];
checksum ^= val;
}
if(checksum==commandbuffer[3]){return true;}
return false;
}

void SerialWorker()
{
while(Serial.available())
{
if(buffercount==-1)
{
buffer = Serial.read();
if(buffer != 'X'){buffercount=-1;}else{buffercount=0;}
}
else
{
buffer = Serial.read();
commandbuffer[buffercount]=buffer;
buffercount++;
if(buffercount > 3)
{
if(CheckChecksum()==true){ParseCommand();}else{errorcount++;}
buffercount=-1;
}
}
}
}


as you see this functions used buffer. Buffer we used for ModBus,

some have any ideas  ::)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Aug 02, 2015, 03:17 am
AlexNetser, I am trying to understand what you are trying to say, it is very confusing and not clear to me.

But, you say this;
Quote
I'm Using programing port for transmit data from computer to arduino and transmit data to slave (ModBus).
Which to me sounds like you are using the programming port for both data to the computer and also for Modbus communications, is this correct ?

If so, then you can't do this, you need to dedicate a serial port for each, one for communications to the computer and another for communications for Modbus.

There is no evidence of the error you talk about, none at all.
And if it were 2%, then you would see two things, Atmel would fix it and secondly, you see it as a major problem and talked about so much that people would stop using Atmel.

None of this is true.

It is simply because you are not using the communications in the correct way from what I can understand from your post.


I use Modbus and have not one error in around 10 million transactions, not one.
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: AlexNester on Aug 02, 2015, 07:54 pm
Hi
thanks for your reply rockwallaby

But you do not understand me.

I'm use program port only for communication between computer and arduino due.

between controller(as master) and slaves I'm use Usart 1 (RX1 TX1). Its work with out problems.

But I'm find firmware (fora arduino UNO or arduino duemilanove) where use function checksum for data communication between computer and controller.


may be for usart1 arduino has another buffer, but in manual I'm not find this buffer.
or function checksum is no need for due :smiley-roll-sweat:



there a part that firmware, there use a buffer.
Code: [Select]


bool CheckChecksum() //Atmel chips have a comport error rate of 2%, so we need here a checksum

{
byte checksum=0;
for(int z=0; z < 3; z++)
{
byte val=commandbuffer[z];
checksum ^= val;
}
if(checksum==commandbuffer[3]){return true;}
return false;
}

void SerialWorker()
{
while(Serial.available())
{
if(buffercount==-1)
{
buffer = Serial.read();
if(buffer != 'X'){buffercount=-1;}else{buffercount=0;}
}
else
{
buffer = Serial.read();
commandbuffer[buffercount]=buffer;
buffercount++;
if(buffercount > 3)
{
if(CheckChecksum()==true){ParseCommand();}else{errorcount++;}
buffercount=-1;
}
}
}
}
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Aug 03, 2015, 01:53 pm
Alex,
I am even more confused with what you say, I am really trying to understand what you are trying to say.
I guess English is not your native language, but you are not at all making yourself clear to me.

Looking back over your posts, it appears you have been struggling for nearly one year with this issue, since last September 2014.

I understand you have a computer connected to your DUE programming port and that this is working very good, correct ?

Next, I understand you have the DUE setup as Modbus master on the DUE serial port 1, which is on pins 18 and 19, is this correct ?

What modbus library do you use, as you have not detailed this ?


You write the following;
Quote
But I'm find firmware (fora arduino UNO or arduino duemilanove) where use function checksum for data communication between computer and controller.
I can not understand at all what you are trying to say.

First, I notice you always write 'I'm', which is short for 'I am'. So, when you write 'But I'm find firmware', is incorrect use of English. Rather, you should write 'But, when I find firmware, for an Arduino UNO or Arduino Duemilanove ....'

Are you mixing up the Arduino Duemilanove with the Arduino DUE, as they are two completely different boards.
The reason I ask, is that are you certain the Modbus library you are using can function on a DUE, as you say you have ?

Then you write;
Quote
may be for usart1 arduino has another buffer, but in manual I'm not find this buffer.
or function checksum is no need for due
Which is a complete puzzle to try to decipher what you are trying to say, it makes no sense to me.

What exactly are you trying to do ?


So, many questions for you to think about and to answer each one clearly.
Santé
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: DDTechG on Aug 03, 2015, 02:24 pm
Hello mrUnfused,

sorry for not answering in time. I stopped checking this thread after my post remained the last one for a longer time.

Hello DDTechG and modbus users  :) !
Reading posts on the thread "Help with Modbus RTU", I came to know that you can help me regarding modbus control of motor using VFD. So far I have tested peer-to-peer modbus RS458 using couple of arduino UNOs and SP485EC line driver IC. So I have some confusions about using modbus in my system. I have listed them below.

1. It is said that dealy(x) messes up the modbus operation. It even worked when I inserted a delay(x) inside loop(). Can we use smaller delay (about 1ms - 10ms) inside loop() in our program?
Here the communication is asynchronous. I am not asking a question and wait for the response but rather, like sending an e-mail, send the request and continue doing something else. Every now and then I check my inbox in order to see if a reply has arrived.

In this case the size of the inbox is very limited and I can only communicate with one "client" at a time. Therefore You will want to check the inbox often and you'll want to make sure that messages arrive when they are available. Using delay(x) does not necessarily mix up everything, but chances of this happening go up.


Quote from: mrUnfused
2. In my system I need to interface 3 proximity switches, a 1024 Pulse Per Revolution incremental encoders and some LEDS along with system being modbus master to a VFD. I have interfaced A and B of encoders to two available hardware interrupts of UNOs in " State change triggering" mode. Will modbus gets affected by the execution of ISR due to back and forth occurrence of encoder pulses? Or do I need to leave an UNO just making it a modbus processor and carrying all other tasks by other UNO ?
I am also talking to a VFD, doing very similar things. When I first started with Juan's library, I was struggling a lot and as he announced that no further development would be made and the library did not work well for my needs, I started to rewrite (or enhance) it.
It's now an event driven class without the necessity of rapidly polling for replys and allows doing easy single time commands as You would want them when talking to a VFD.
I have prepared a "package" for "rockwallaby" that also contains a sample program stub that should help to get You up and running in no time. Let me know, if You like to try that out and I'll make it available for You.

Modbus or not, I always find encoders demanding as they just provide impulses which You do not want to loose. I would assume that delay() affects reading the encoder more than it does the modbus stuff.

As I wrote, I am planning to do something similar, also time critical. My current idea is to "outsource" that part to a separate chip (ATTiny or so), but I also have other tasks to do. It might well be that in Your case all can be handled well by one chip - just try and see.

Kind regards

Frank

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: DDTechG on Aug 03, 2015, 02:52 pm
.... If I read correctly, the Leonardo does not use Pins 0 and 1 as the USB connection is virtualized in the 32U4 chip. Would using a Leonardo be a possible solution? Do you have any other suggestions on how the Uno could handle both the RS-485 and the USB connection?
I'm using a Leonardo that way and it works very well. I can control my VFD and at the same time debug to screen or control everything with my PC GUI.

regards

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: mrUnfused on Aug 04, 2015, 10:05 am
Hello DDTechG,
thanks for reply.
Using the library, I have done several testing. Up to now I'm able to exchange data bytes between a master and a slave with some modes.

Quote
It's now an event driven class without the necessity of rapidly polling for replys and allows doing easy single time commands as You would want them when talking to a VFD.
yes, I want to see your library if they are open-source. But currently project is not on progress. I will continue it soon and will be interacting on the forum. 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tuhuynh on Aug 10, 2015, 11:37 am
Hi all.
i dont understand how to use function 06 to write only one time , this lib use FSM so it send so it continue to send the same value, i want to send just only one time. Anybody can help me.
i have 128 slave and 1 master, in each slave have one read funtion and one write function. Master and slave use pro mini and max485. Because of using max485, i break serial use digital switch. Can this lib work if i break the serial up to 4 line serial. thanks alot.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Rberg on Aug 11, 2015, 02:54 pm
Hi bsahilu,

Unfortunately, Now, I'm forced to abandon the ModBus approach.  The need to have auto-slave address detection is becoming a driving factor.  My search for that topic returns convoluted schemes that just sound ridiculously complicated and people are just utterly pessimistic regarding collisions. I get it, there is no (need for) collision detection when you have only ONE master.

Here's a brief description of the re-direction on the project scope.  If I have 100+ (or more) devices that are NOT physically accessible (no direct or pre-deployment programming of the address) AND they must be loaded with identical firmware, how do I access them to automatically detect and change their ID's respectively.  I do however, have a unique serial provided by a physical IC on the board of each device.  I want a means for all to be fired up and each to broadcast their unique serial and have a central unit provide/assign addresses.


I have similar thing. in my case it is to change the MAC and IP from the Arduino ethernet.
I flash the sketch with one specific MAC/IP, this specific IP is used for the first boot.
Once it is up for the first time I send a command to change the MAC/IP and save the values in the EEPROM (most of people forget arduino has EEPROM). Bingo.

I can change the MAC/IP at anytime. I just need to send the command to the current IP.
I will implement same thing for the Modbus I'm working on.

Code: [Select]

/**********************************************************************************
 * How to use the EEPROM to save a NODE number
 * By Rhaurison Bergamin
 * rhaurison
 * at
 * gmail
 *
 * Tested with Arduino Mega 2560
 *
 * Default NODE is 100, so this is a reserved number in the network/bus
 *
 * You must change the NODE # after plug your new flashed arduino into network/bus
 *    in order to release the NODE # 100 for the next new arduino.
 *
 * To Factory Reset NODE to 100, Jumper pin 52 to GND and reset.
 *       after boot is complete, don't forget to remove the jumper.
 *********************************************************************************/
#include <EEPROM.h> 

const int ID_ADDR = 0;
const int NODE_ADDR = 1;
byte NODE = 100;

void EEPROMWriteInt(int p_address, int p_value) {
    byte lowByte = ((p_value >> 0) & 0xFF);
    byte highByte = ((p_value >> 8) & 0xFF);

    EEPROM.write(p_address, lowByte);
    EEPROM.write(p_address + 1, highByte);
}

unsigned int EEPROMReadInt(int p_address) {
    byte lowByte = EEPROM.read(p_address);
    byte highByte = EEPROM.read(p_address + 1);

     return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
 }

void setup(){
pinMode(52,INPUT); // 1=EPROM RESET
digitalWrite(52,HIGH); // pull up..
if (digitalRead(52) == LOW) {
Serial.println("I found the Pin 52 jumper to GND,  this means you want me to come to factory reset.");
EEPROM.write(ID_ADDR,0x00);
EEPROMWriteInt(NODE_ADDR,NODE);
}
byte id = EEPROM.read(ID_ADDR); // Read first byte from eeprom
  if( id == EEPROM_ID) {
  // here if eeprom has data
NODE = EEPROMReadInt(NODE_ADDR);
Serial.print("Node #:");Serial.println(NODE);
  } else {
  Serial.println("No Data in EEPROM, Booting with default NODE # 100");
  }
// from here you have the NODE  byte variable, from default value defined on the very begin or the new value
// read from the eeprom.
// Now you can set any paramter as IP, MAC, SLAVE
}

void(* resetFunc) (void) = 0;

void writeNODE (unsigned int new_node) {
EEPROM.write(ID_ADDR,EEPROM_ID);
EEPROMWriteInt(NODE_ADDR,new_node);
Serial.println("New NODE # saved into eeprom, we must reboot now.");
resetFunc(); // not a true reset but it force to reload the firmware, enough to reload the setup()
}

void loop{
unsigned int the_new_node_number;
//Somewhere in your code, you catch the command to change the node # and call the writeNODE to save into eeprom
if (command == true) { // here is with you, somewhere in the code you receive the command with the new NODE #
writeNODE(the_new_node_number);
}
}


Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: xtremixt on Aug 18, 2015, 05:12 am
 :( Hello everyone, I'm using the google translator so I apologize if something is not well understood. well I need your help, I'm working with a PLC FATEK, and I have an Arduino as temperature controller, I wish I could write about the PLC, but so far I could not get it to work, I would leave the Arduino as master and the PLC as a slave someone has experience with this type of PLC, greetings from Chile.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: bojankoce on Sep 22, 2015, 09:11 pm
Hello there !

This one is a pretty long thread. It took me a lot of time to read it up to this point.
Let me try to give you my experience with the ModbusMaster library.

I was using this library to communicate with the ElNet LT Powermeter (http://www.lsa.hu/files/files/elnet_comm.pdf) that supports ModBus RTU communication (Functions 3, 4, 6, and 16 are supported). My Arduino Uno board was connected to the ElNet Powermeter device via RS485 module (http://arduino-info.wikispaces.com/rs485-modules).

I slightly modified the example from the ModbusMaster library in order to adapt it to the ElNet device. Here is the code I was using to read a few registers from the ElNet Powermeter:

Code: [Select]

#include <SimpleModbusMaster.h>
#include <SoftwareSerial.h>

SoftwareSerial mySerial(3, 4); // RX, TX

/*
   The example will use packet1 to read a register from address 0 (the adc ch0 value)
   from the arduino slave (id=1). It will then use this value to adjust the brightness
   of an led on pin 9 using PWM.
   It will then use packet2 to write a register (its own adc ch0 value) to address 1
   on the arduino slave (id=1) adjusting the brightness of an led on pin 9 using PWM.
*/

//////////////////// Port information ///////////////////
#define baud 19200
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

//#define LED 13

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 220

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
  PACKET5,
  PACKET6,
  PACKET7,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];
//packetPointer packet1 = &packets[PACKET1];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

unsigned int readRegs[2];
unsigned long currentMillis;
long previousMillis = 0;
long interval = 1000;

void setup()
{
  // Initialize each packet
  modbus_construct(&packets[PACKET1], 1, READ_INPUT_REGISTERS, 7799, 20, 0);    // 1 min values 1/6
  modbus_construct(&packets[PACKET2], 1, READ_INPUT_REGISTERS, 7819, 20, 20);   // 1 min values 2/6
  modbus_construct(&packets[PACKET3], 1, READ_INPUT_REGISTERS, 7839, 20, 40);   // 1 min values 3/6
  modbus_construct(&packets[PACKET4], 1, READ_INPUT_REGISTERS, 7859, 20, 60);   // l min values 4/6
  modbus_construct(&packets[PACKET5], 1, READ_INPUT_REGISTERS, 7879, 20, 80);   // l min values 5/6
  modbus_construct(&packets[PACKET6], 1, READ_INPUT_REGISTERS, 7899, 20, 100);  // l min values 6/6
  modbus_construct(&packets[PACKET7], 1, READ_HOLDING_REGISTERS, 301, 14, 120);  // take Date&Time from ElNet
  
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
  
  mySerial.begin(9600);
  mySerial.println("Setup done!");

}

void loop()
{
  modbus_update();
  
  float VoltageL1;
  unsigned long temp = (unsigned long) regs[80]<<16 | regs[81];
  VoltageL1 = *(float*)&temp;

  // use the following code to avoid using delay()
  currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  {

  mySerial.print("Voltage on L1: ");
  mySerial.println(VoltageL1);
    
  mySerial.print("readReg[120]: ");
  mySerial.println(regs[120]);
  mySerial.print("readReg[121]: ");
  mySerial.println(regs[121]);
  mySerial.print("readReg[122]: ");
  mySerial.println(regs[122]);
  mySerial.print("readReg[123]: ");
  mySerial.println(regs[123]);  
  mySerial.print("readReg[124]: ");
  mySerial.println(regs[124]);
  mySerial.print("readReg[125]: ");
  mySerial.println(regs[125]);
  mySerial.print("readReg[126]: ");
  mySerial.println(regs[126]);  
  mySerial.print("readReg[127]: ");
  mySerial.println(regs[127]);
  mySerial.print("readReg[128]: ");
  mySerial.println(regs[128]);
  mySerial.print("readReg[129]: ");
  mySerial.println(regs[129]);  
  
  mySerial.print("requests: ");  
  mySerial.println(packets[PACKET1].requests);
  mySerial.print("successful_requests: ");
  mySerial.println(packets[PACKET1].successful_requests);
  mySerial.print("failed_requests: ");
  mySerial.println(packets[PACKET1].failed_requests);
  mySerial.print("exception_errors: ");
  mySerial.println(packets[PACKET1].exception_errors);
  mySerial.print("connection: ");
  mySerial.println(packets[PACKET1].connection);    
    
    previousMillis = currentMillis;
  }
}


So the modbus_update() function is called often, there is no long delay(x) functions etc. As I said, the code is pretty much the same like the example code from the ModbusMaster library. Some of the registers I read (301-314) are used to store Date&Time. Within the main() loop I print these registers in order to ensure that I properly read them.

What I noticed when implementing this code on Arduino Uno board is the following:
At the beginning, everything works flawlessly. Date and Time values are properly stored and read from the regs[] array.
However, it seems that the system suddenly stops working behaving like frozen. I mean, my main() loop is running showing me always the same (frozen) values for Date and Time.
I'm really confused and can not realize where is the source of the problem!? Maybe the fact that I have too much mySerial.prints() within the main() loop? This should be equal to long delay(x) functions that waste too much time.
@rockwallaby, you seems to be an expert on the field. Would you like to glance at my code and try to give me some feedback? I would really appreciate this.

If my assumption is correct, this would mean that this library is pretty hard to match with the rest of the code that requires some extensive processing.

To the best of my understanding, this library is designed to constantly write to/read from regs[] array.
Reading/writing process is performed in the background via modbus_update() function. That is why this function supposed to be often called.

I also wonder if there is a way for me to read from the particular register (or to write it) at the specific moment in time (as I want in my code), not constantly in the background? This possibility would make the library more useful (at lest for me).

I noticed that DDTechG improved John's ModbusMaster library by introducing some little changes. @DDTechG, would you be so kind to share your library with us?

Thank you very much for your time and effort to help me with this issue?


Sincerely,
Bojan.


P.S. I just put modbus_contruct() and modbus_configure() functions within the true part of the if {} statement (before mySerial.prints). It now seems that the code is constantly running as expected! I wonder is it a good practice to have this modbuc_construct() and modbus_configure() functions on a multiple places in the code? Thanks in advance
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rexlee on Sep 23, 2015, 03:54 am
I have only just started to use SimpleModBus for a few days using Arduini Nano as slave & Arduino Mega1280 as master using Serial1.  I have had all sorts of problems getting this going and checked out this thread and tried some of the ideas... nothing.  Consistantly 100% loss get no reponse back at the master despite the fact that the slave was sending a response.
So  I got my Salea logic Analyzer, which quickly got to the bottom of the problem and it turns out to be a biasing issue.  The very common eBayTTL-RS485 modules that I use a 120 Ohm terminating resistor & two 20 K biasing resistors.  This would be OK if there were 30 or so modules on the bus, but with only two or three, you get all sorts of problems.
I removed the two 20K resistors and it did improve the situation, but the loss was about 20%.  The logic analyzer was showing the the master rx was getting a glitch just prior to the packet when the slave TXEnable was asserted.

The recommended total terminating resistance per side for the MAX485 is 680 Ohms, not the 10K ohm which you get with only two modules.    see    http://www.ni.com/support/serial/resinfo.htm
I changed the resistors on my master module to 1K Ohm per side  and I intend to leave the 20 K ohm resistors on the 8 slaves (that I will ultimately need), which will give me close to 680 Ohm per side.
Since doing that I have had 0% packet loss for 10's of thousand correct transfers!

Edit.

I have just added an additional four slaves and I found it necessary to remove the 120 Ohm termination resistors on the intermediate slaves.  The bus works 100% now.

Summary.
For the  common TTL-RS485 modules from eBay.

Master                      -     Replace 20 K resistors with 1K resistors
Intermediate slaves -     Remove the 120 Ohm termination resistor.
Last slave                 -     Leave it as it is.   
 


Lee
   
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Sep 23, 2015, 01:39 pm
Bojan,
It seems to me, from having a look over your code, that you have considered things carefully.

I don't see any real reason why your code would do as you say.
I am guessing that something in either the packet definitions or maybe the other device may well be the cause of the problem.

I see you keep your packets to 20 registers each, which is within the size limits of the Arduino hardware serial buffer.

You are using the hardware serial for Modbus which is good, and software serial for communicating back to your computer, again, all seems good.

The first thing I would suggest is you can adjust is the polling rate, from 200mS, try between 500mS to 1000mS.

What you can try is to reduce the number of serial prints, say just try a few to see the impact.
You are printing out errors, do you get any at all ?

In your P.S., no, don't place the construct and configure statements in the main loop, this is not the place to put such statements. Typically, doing things like this may cause sorts of issues such as out of memory due to allocation of resources each time around the main loop().

The modified Modbus master code form DDTechG works well, I have used it and will continue to use it and will look at small improvements over time with it.

The library you are using presently has also been proven to be functional and should work well enough for you too.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: bojankoce on Sep 23, 2015, 02:03 pm
Paul,

thank you for a fast reply and useful hints. I will try as you suggest - to increase the polling rate and to exclude construct and configure statements from the main loop.
Regarding the errors, I sometimes get a few errors but not too often.

Sincerely,
Bojan.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: bojankoce on Sep 23, 2015, 02:45 pm
Hey Paul,

It seems that increasing the polling rate indeed improved the behavior of my system. The time is now constantly read from the regs[] array without freezing. :)

However, I would actually like to ask you for your valuable opinion on how to implement this ModbusMaster code into the rest of my needs.

Namely, I have a code that is already organized as a finite state machine (FSM). In some of the FSM states, I would need to read the modbus registers.
If you advice me that is better to exclude configure and construct statements from the main loop, does it means that I should call the modbus_update() function as often as possible (maybe at the beginning of each FSM state)?

I did like this (configure and construct statements are only in the setup() function, I call modbus_update() at the beginning of each FSM state). However, I'm unable to read modbus registera (to refresh the content of the regs[] array) as often as I would like. It would be satisfied for me if I could read modbus time each 2-3 seconds. However, it appears that regs[] array refresh on each 15-16 seconds?
Is there any way for me to improve the refresh rate (the speed of regs[] updates) of the modbus registers?

Thank you very much for your time and effort.

Sincerely,
Bojan.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Sep 25, 2015, 02:01 am
Hi Bojan,

Quote
It seems that increasing the polling rate indeed improved the behavior of my system. The time is now constantly read from the regs[] array without freezing. :)
Good to hear :)

Quote
However, I would actually like to ask you for your valuable opinion on how to implement this ModbusMaster code into the rest of my needs.

Namely, I have a code that is already organized as a finite state machine (FSM). In some of the FSM states, I would need to read the modbus registers.
If you advice me that is better to exclude configure and construct statements from the main loop, does it means that I should call the modbus_update() function as often as possible (maybe at the beginning of each FSM state)?
I don't understand when you say you have organised 'code' as a finite state machine, do you mean your own code or the Modbus library code which is a FSM ?

If it is your own code, then what drives the FSM, you still need a procedural loop that allows things to work, based on either repetitive loop or based on events such as external hardware interrupts.

Without knowing what you are trying to achieve, it is difficult to advise, and can only make guesses.

The Modbus FSM is normally called only once, and that will be in your main loop().
It needs to be called as often as possible for it to function correctly, slaves need to be constantly on the watch for requests from the master, and as a master, it needs to constantly be on the watch for replies from the slave or slaves. Any significant and introduced delays may give issues.

If you delay the checking of the Modbus FSM significantly, you can get buffer overflows in your Arduino hardware buffer as the FSM is not being allowed to suck waiting data from it at an appropriate rate.

It will be best to stay with the standard methods of use, that is, place your constructs in the setup() section and your Modbus update function call in the main loop() and don't hold it back with any sort of delays.

Then get your code functioning as you need and then work on any improvements, but you will most likely find you will run into reliability problems because you are not using the Modbus protocol in the way it is intended. This will be difficult for others to offer help.


If all you want is to exchange data with another device or number of devices at a slow rate of every few seconds, then use the Mobus library how is is detailed and documented. The code you then wrap around this will need to be designed to suit your particular needs and this is where you can really do anything you wish.

Using Modbus at baud rates of 19200 as you have I recall, you can transfer a fair amount of data, (registers), far more than you have. I have made small test codes that really push the polling time to look at how the protocol stands up to being pushed hard against the reliability. I was happily surprised at how well it worked, with polling times down to around 20mSec. Essentially a constant stream of data at any of the baud rates from 19200 to 115200 working well.

Think about your other device, maybe it has some limitations, what is it ?


Quote
Thank you very much for your time and effort.
You are welcome :)
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: bojankoce on Sep 30, 2015, 12:15 pm
Hello Paul,

Sorry for a little late reply from my part.

Quote
I don't understand when you say you have organised 'code' as a finite state machine, do you mean your own code or the Modbus library code which is a FSM ?
I mean that my own code is organized as a FSM. I know that Modbus library code is in a FSM fashion as well.

What drives my FSM is a repetitive loop as you can see below.

Code: [Select]
/*

#include <SimpleModbusMaster.h>
#include <dataflash.h>
#include <SoftwareSerial.h>
#include <EEPROM.h>

SoftwareSerial SIM900(5, 6); // RX, TX - configure software serial port for SIM900 module
SoftwareSerial mySerial(3, 4); // RX, TX - USB to serial port for debugging
Dataflash dflash;

//////////////////// Modbus Port information ///////////////////
#define baud 19200
#define timeout 1000
#define polling 700 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2
#define wkpSIM900 9

// FSM states
#define START 0
#define GET_TIME 1
#define LOG_TO_FLASH 2
#define ESTABLISH_TCP 3
#define READ_SERVER_INST 4
#define DECODE_SERVER_INST 5
#define READ_FROM_FLASH 6
#define SEND_DATA_TO_SERVER 7
#define CHECK_TCP 8
#define WAIT_FOR_INST 9
#define DECODE_INST 10
#define CHECK_TIME 11
#define STOP 12


// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 152

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
  PACKET5,
  PACKET6, 
  PACKET7,   
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];
//packetPointer packet1 = &packets[PACKET1];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

unsigned long currentMillis;
long previousMillis = 0;
long interval = 1000;

int FSM_state = START;        // master variable for the FSM.
uint8_t trnsmt_buf1[245];     // transmit buffer. Data from Flash memory are copied to this buffer and sent to the server
char aux_str[100];
int x = 0;
char instruction[100];
unsigned long previous;
float VoltageL1;
unsigned long temp;
uint8_t curr_day;
uint8_t curr_min = 0;
bool next_day_flag;

void setup()
{
  configureElNet();

  dflash.init(); //initialize the memory (pins are defined in dataflash.cpp
 
  SIM900.begin(19200);
  pinMode(wkpSIM900, OUTPUT);
  mySerial.begin(9600);
  next_day_flag = true;
  curr_day = EEPROM.read(0);


  SIM900.listen();
  power_on();

  delay(100);
   
  mySerial.println("SIM900 ON");

  SIM900.listen();
  while( sendATcommand2("AT+CREG?", "+CREG: 0,1", "+CREG: 0,5", 1000)== 0 );

}

void configureElNet(void){
    // Initialize each MODBUS packet
  modbus_construct(&packets[PACKET1], 1, READ_INPUT_REGISTERS, 7799, 20, 0);    // 1 min values 1/6
  modbus_construct(&packets[PACKET2], 1, READ_INPUT_REGISTERS, 7819, 20, 20);   // 1 min values 2/6
  modbus_construct(&packets[PACKET3], 1, READ_INPUT_REGISTERS, 7839, 20, 40);   // 1 min values 3/6
  modbus_construct(&packets[PACKET4], 1, READ_INPUT_REGISTERS, 7859, 20, 60);   // l min values 4/6
  modbus_construct(&packets[PACKET5], 1, READ_INPUT_REGISTERS, 7879, 20, 80);   // l min values 5/6
  modbus_construct(&packets[PACKET6], 1, READ_INPUT_REGISTERS, 7899, 20, 100);  // l min values 6/6
  modbus_construct(&packets[PACKET7], 1, READ_HOLDING_REGISTERS, 301, 14, 120);  // take Date&Time from ElNet
//  modbus_construct(&packets[PACKET7], 1, READ_INPUT_REGISTERS, 7951, 16, 152);  // immediate values 1/2
//  modbus_construct(&packets[PACKET8], 1, READ_INPUT_REGISTERS, 7967, 14, 168);  // immediate values 2/2 
//  modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
 
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
}

void loop()
{
  modbus_update();

  switch(FSM_state){
   
    case START:
      //mySerial.println("State: START");
      modbus_update();
      FSM_state = CHECK_TCP;
    break;

    case CHECK_TCP:
      modbus_update();
      if (establish_TCP_server()){
        modbus_update();
        FSM_state = WAIT_FOR_INST;
      }else{
        modbus_update();
        sendATcommand2_v1("AT+CIPSHUT", "SHUT OK", "ERROR", 2000, 3);
        modbus_update();
        FSM_state = CHECK_TCP;
      }
    break;

    case WAIT_FOR_INST:
      modbus_update();
      memset(instruction, '\0', 100);    // Initialize the string

      while( SIM900.available() > 0){
        SIM900.read();    // Clean the input buffer
        modbus_update();
      }
      x = 0;
      previous = millis();

      // this loop waits for the answer
      do{
        // if there are data in the UART input buffer, reads it and checks for the asnwer
        if(SIM900.available() != 0){   
            instruction[x] = SIM900.read();
            x++;
            modbus_update();
        }
      }
    // Waits for the asnwer with time out
    while((millis() - previous) < 2000);   
    modbus_update();
    mySerial.print("Instruction:"); mySerial.println(instruction);
    modbus_update();
    modbus_update();
    if (instruction[0]=='I'){
      modbus_update();
      mySerial.println("Instruction received");
     if (sendATcommand2_v1("AT+CIPSEND", ">", "ERROR", 2000, 3) == 1){
      modbus_update();
      SIM900.print("ack");
      SIM900.print('\x1A');
      modbus_update();
     }
     FSM_state = DECODE_INST;
    } else {
      FSM_state = CHECK_TIME;
    } 
   
    break;

    case CHECK_TIME:
      modbus_update();
     
      if(curr_min!=regs[122]){
        curr_min = regs[122];
        curr_day = EEPROM.read(0);
        writeToFlashMin1(1440*curr_day + regs[124]*60+curr_min +1);
      }

      if ((curr_min == 59) && (regs[124]==23)){
        mySerial.println("One minute until Midnight...");
       if(next_day_flag == true){
        next_day_flag = false;
        if (EEPROM.read(0) == 4){
          EEPROM.write(0,0);
        } else {
          curr_day++;
          EEPROM.write(0,curr_day);
          mySerial.print("increasing curr_day parameter... New curr_day: ");mySerial.println(curr_day);
        }
      }
      } else {
        next_day_flag = true;
      }
     
   
      if(sendATcommand2("AT+CIPSTATUS", "SERVER LISTENING","CONNECT OK", 1000)  != 0 ){
        modbus_update();
        FSM_state = WAIT_FOR_INST;
      } else {
        modbus_update();
        power_on();
        FSM_state = CHECK_TCP;
      }     
     
    break;

    case DECODE_INST:
      modbus_update();
      mySerial.print("Instruction: "); mySerial.println(instruction);
     if (instruction[1] == 'M'){
      readFlashMin1(1000*(instruction[2]-'0')+100*(instruction[3]-'0')+10*(instruction[4]-'0')+ (instruction[5]-'0'));
     
     if (sendATcommand2_v1("AT+CIPSEND", ">", "ERROR", 2000, 3) == 1){
            for (int j=0;j<245;j++){
              SIM900.print(trnsmt_buf1[j]);
              SIM900.print("+");
            }
            SIM900.print('\x1A');
      }
      }

     
      FSM_state = WAIT_FOR_INST;
    break;


    default:

    break;
   
  }
 
 
}


So, I thought it will be enough to call modbus_update() function before entering each particular FSM state (very first line in the loop()). However, the result was lost connection between Arduino and Modbus slave. When speaking about Modbus slave, it is ElNet Powermeter (http://www.ddc.co.il/elnet-pdf/elnet_lt_man_rev3.pdf).

The fact that modbus_update() at the beginning of the loop() did not make a modbus communication possible, motivated me to call modbus_update() as well as configure and construct statements somewhere within a FSM states. When doing this, I noticed that the communication between my ARduino and Modbus slave exist. However the refresh rate of what regs[] array is once in each 15-16 seconds. I hope I was clear in my explanations.

By taking a look in to my code, can you give me a hint on where to put modbus_update() function as well as configure and construct statements.

Thank you very much for your effort. I really appreciate this.

Sincerely,
Bojan.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Sep 30, 2015, 03:53 pm
Bojan,
Looking at your code at first glance I see lots of modbus_update() calls.
In my previous post I mentioned the following:
Quote
The Modbus FSM is normally called only once, and that will be in your main loop().
How many more times than 'once' is it listed in your main loop() ?

Unfortunately, it is a mess to my eyes that should really be able to be far more simplified.

Things to thing about:
If you work with time as a single long, as in Unix time, not separate units for hours minutes and so on, you may find your code will appear and work better.

Reduce the amount of characters in your serial prints, avoid extra characters like '....', each character steals time especially at low baud rates.

This code will not help things, even if you have modbus_update() in the middle of it as you don't act on any modbus registers during the while loop()
Code: [Select]
do{
        // if there are data in the UART input buffer, reads it and checks for the asnwer
        if(SIM900.available() != 0){   
            instruction[x] = SIM900.read();
            x++;
            modbus_update();
        }
      }
    // Waits for the asnwer with time out
    while((millis() - previous) < 2000);   


It seems you are really trying hard to make this work and I wish I could help better. but it's a mess, sorry to say :|

If you are willing and able, write up a functional description (FD) of exactly what you want and need to do, then I can understand better your requirements. With an FD, I may be able to advise better.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: zerox12 on Oct 01, 2015, 01:10 am
Hello,

Can anyone confirm that these RS485 shields work with SimpleModbus?
https://www.sparkfun.com/products/12965

No matter what I try I can't get the example Master and Slave sketches to communicate with these shields.

Master:
Mega R3 using Serial1 and pin 9 for TX enable

Slave:
Uno R3 using Serial (the only serial port) and pin 9 for TX enable.

I load both sketches, then monitor the master via Serial. The master TX is triggering, but the RX of the slave never lights up. I can see that my packets.[PACKET1].failed_requests is increasing.

I see that this shield uses MAX481CSA instead of a MAX485, perhaps that is the problem? I have a few MAX485CSAs in the mail. Hopefully these shields aren't a waste of money.

Thanks
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Oct 01, 2015, 01:44 am
Welcome to the forum zerox12,
Looking at the example code at the link you provided and noticing that they are using the Tx data as Tx_Enable, while you are using D9 as the Tx_Enable pin, you will need to manually operate the D9 pin.

So, in the code for both master and slave, you will need to set pin D9 high before transmitting and then set it low directly after to allow the receiver to operate.

You can first try putting the Tx_Enable select to Tx_CTRL on P2.
Manually controlling the Tx_enable line is a better method in any case.

Hope this helps.
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: bojankoce on Oct 01, 2015, 12:45 pm
Hi Paul,

Now when I have your full attention I'm more than willing to write you up a functional description of my project.
My system consists of the following devices:

- ElNet Powermeter that communicates via Modbus RTU protocol
- Processing unit which is an Arduino Uno in my case
- DataFlash memory
- SIM900 GPRS module

Various parameters about the power supply network (voltages on each phase, frequencies, currents...) are stored in ElNet Powermeter registers. By using Arduino Uno, I need to access some of these registers via Modbus RTU protocol (Arduino as Master, ElNet as Slave). Each "X" seconds, I need to log these data into non-volatile DataFlash memory.
On the other hand, I need to configure SIM900 GPRS module (via serial AT commands) to be a server listening on a specific TCP port and waiting for the instructions to come from the remote client. Each time I receive an instruction from the client, I need to deliver a portion of the DataFlash memory locations (readings from the ElNet Powermeter).

As you can see from the above description, Arduino Modbus communication is just one part of my project requirements. I need to do some other things apart from communicating with the ElNet Powermeter. That is why I decided to organize the code as a Finite State Machine.

In the attached document I tried to give you a diagram of states together with a short description of what I suppose to do in each state. Please, take a look on it. Any advice from your side will be highly appreciated.

I believe that it is worth mentioning that the current code I have is functional. I can do what I want, I move through the FSM states as expected. The only thing that is bothering me is the fact that I can not read Modbus register with the speed I want. I want to be able to read registers (refresh regs[] array) each 5 seconds. Currently, I can achieve only 15-20.

Quote
How many more times than 'once' is it listed in your main loop() ?
You are right, I call this modbus_update() function many many times through my code. One time at the beginning of the loop() and at least one time in each FSM state.
This is because I noticed that calling modbus_update just one time (at the beginning of the loop() is simply not enough causing Modbus communication to freeze).

Quote
It seems you are really trying hard to make this work and I wish I could help better. but it's a mess, sorry to say :|
I really appreciate your wish to help me. The code I attached is pretty messy, I agree. This is because I'm still in a testing phase, adding and removing the lines of the code everywhere.
When speaking about the code organization... is there any book about microcontrollers, Arduinos, programming etc. that you can recommend to me for a reading? The book that helped you a lot on how to organize the code. I would be happy to read it.

One more time, thank you very much for your time and effort.

Sincerely,
Bojan

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Oct 01, 2015, 04:03 pm
Bojan,

Can you explain the following part of your code:
Code: [Select]
readFlashMin1(1000 * (instruction[2] - '0') + 100 * (instruction[3] - '0') + 10 * (instruction[4] - '0') + (instruction[5] - '0'));
If I understand what you are trying to do, you can't do this, you are attempting to do maths on a char data type:
Quote
1000 * ('x' - '0')
Where are the functions power_on and establish_TCP_server and sendATcommand2 ?
Where did you get the dataflash library from, can you supply a link please ?
I am assuming you are using the SimpleModbusMaster2v2 library, yes ?


In terms of code clarity, there are of course conventions that are often used, but also, people tend to have their own preferred methods that work for them.

In terms of good working code practices, that comes down to experience, with looking at a lot of other peoples code. I am not an expert in C/C++, not yet anyhow, but I have coded in many languages including a lot of assembler for too many years for me to think about.

Just keep coding and looking at how others who know code do it.

I have the code you posted above as a new project in the Eclipse IDE to give it a little massage.
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: zerox12 on Oct 01, 2015, 04:13 pm
Welcome to the forum zerox12,
Looking at the example code at the link you provided and noticing that they are using the Tx data as Tx_Enable, while you are using D9 as the Tx_Enable pin, you will need to manually operate the D9 pin.

So, in the code for both master and slave, you will need to set pin D9 high before transmitting and then set it low directly after to allow the receiver to operate.

You can first try putting the Tx_Enable select to Tx_CTRL on P2.
Manually controlling the Tx_enable line is a better method in any case.

Hope this helps.
_____
Paul
Isn't this line already defining the TxEnable pin?

Code: [Select]
// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 9

  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial1, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);


I also have pin 9 defined in the Slave modbus_configure.

EDIT: My MAX485 ICs came in the mail today. I put it together on a bread board using the MAX485 instead of the RS485 shields and everything works perfectly. I think there is a problem with the shields and SimpleModbus.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Oct 02, 2015, 12:39 am
zerox12,

Can you detail exactly your wiring between the master and slave.
Can you list your entire code for both as well please.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Oct 02, 2015, 07:08 am
Bojan,

With what I understand you might wish to do, but with parts of your code missing, I am guessing the following re-work is more how I would expect such a program to look. I can't test it or compile it as I don't have the missing code sections.

Follow it through slowly and carefully and I hope you will understand the concept and flow.

Code: [Select]
/*---------------------------------------------------------------------------------
 * Some program to request data from power meter and make it
 * available to connected tcp clients via a SIM900 module
 *
 * main.cpp
 *
 * Author:    your name
 * Created:   02 Oct 2015
 * Modified:  02 Oct 2015
 *
 * Notes:
 *   EIA-485 transmit enable on pin 2 of the Arduino
 *
 *  Put all your important information here and any links to datasheets
 *  or forum posts that give insight to the workings of this code:
 *
 */

#include "bojan.h"  // header used by my system, comment it out if you want:
#include <SimpleModbusMaster.h>
#include <dataflash.h>
#include <SoftwareSerial.h>
#include <EEPROM.h>

SoftwareSerial SIM900(5, 6);   // RX, TX - configure software serial port for SIM900 module
SoftwareSerial mySerial(3, 4); // RX, TX - USB to serial port for debugging
Dataflash dflash;

// Modbus port configuration:
#define baud 19200       // modbus baud rate
#define timeout 1000     // timeout in mSec before error
#define polling 1000     // the packet poll scan rate in mSec
#define retry_count 10   // retries before error
#define TxEnablePin 2    // used to toggle the receive/transmit pin on the driver
#define wkpSIM900 9

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 152

enum {
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
  PACKET5,
  PACKET6,
  PACKET7,
  TOTAL_NO_OF_PACKETS   // leave this last entry
};

//-------------------------------------------------------------------------------------------------------------------
//const type         variable          =  value;              comment
        bool         next_day_flag     = true;             // some trigger I guess that tells when the next day has arrived:
        uint8_t      rtc_day           = 0;                // value of day from RTC:
        uint8_t      rtc_hour          = 0;                // value of hour from RTC:
        uint8_t      rtc_min           = 0;                // value of minute from RTC:
        uint8_t      trnsmt_buf1[245];                     // transmit buffer. Data from Flash memory are copied to this buffer and sent to the server

        uint16_t     tcp_buffer_count  = 0;                // available tcp server buffer bytes to read:

        uint32_t     lastTCPScan       = 0;                // last time tcp srver is scanned:
const   uint32_t     periodTCPScan     = 500;              // rate period to scan tcp server:

        Packet       packets[TOTAL_NO_OF_PACKETS];         // Create an array of Packets to be configured
        unsigned int regs[TOTAL_NO_OF_REGISTERS];          // Modbus register array map

/*---------------------------------------------------------------------------------
 *  void setup()
 *  Initial setup of board:
 */
void setup() {
  modbus_construct(&packets[PACKET1], 1, READ_INPUT_REGISTERS, 7799, 20, 0);    // 1 min values 1/6
  modbus_construct(&packets[PACKET2], 1, READ_INPUT_REGISTERS, 7819, 20, 20);   // 1 min values 2/6
  modbus_construct(&packets[PACKET3], 1, READ_INPUT_REGISTERS, 7839, 20, 40);   // 1 min values 3/6
  modbus_construct(&packets[PACKET4], 1, READ_INPUT_REGISTERS, 7859, 20, 60);   // l min values 4/6
  modbus_construct(&packets[PACKET5], 1, READ_INPUT_REGISTERS, 7879, 20, 80);   // l min values 5/6
  modbus_construct(&packets[PACKET6], 1, READ_INPUT_REGISTERS, 7899, 20, 100);  // l min values 6/6
  modbus_construct(&packets[PACKET7], 1, READ_HOLDING_REGISTERS, 301, 14, 120);  // take Date&Time from ElNet
//  modbus_construct(&packets[PACKET7], 1, READ_INPUT_REGISTERS, 7951, 16, 152);  // immediate values 1/2
//  modbus_construct(&packets[PACKET8], 1, READ_INPUT_REGISTERS, 7967, 14, 168);  // immediate values 2/2
//  modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);

  // Initialise the modbus finite state machine
  modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);

  //initialise the memory (pins are defined in dataflash.cpp)
  dflash.init();

  mySerial.begin(9600);

  pinMode(wkpSIM900, OUTPUT);
  SIM900.begin(19200);
  SIM900.flush();  // verify if flushing actually resets the buffer pointer:

  SIM900.listen();
  mySerial.println("SIM900 Listening");

  rtc_day = EEPROM.read(0);

  power_on(); // where is this function, what does it do, is there ever a power_off as well ?
  delay(100); // is delay to give time after power on, explain ?

  if (!establish_TCP_server()) // where is this function ?
  sendATcommand2_v1("AT+CIPSHUT", "SHUT OK", "ERROR", 2000, 3); // where is this function and what does it do ?

  while (sendATcommand2("AT+CREG?", "+CREG: 0,1", "+CREG: 0,5", 1000) == 0 ); // why while loop and where is this function ?
}

/*---------------------------------------------------------------------------------
 *  void loop()
 *  Mission Control:
 *
 *  Check the Modbus state machine continuously:
 *  Every TCPScan check for TCP server status and process accordingly:
 *  Check RTC by reading modbus registers and update:
 */
void loop() {
  modbus_update();  // check modbus status from connected slaves:

  if (millis() - lastTCPScan > periodTCPScan) { // call routines at a set rate:
    if ((tcp_buffer_count = SIM900.available()) && SIM900.find("\0")) // get tcp bytes and verify it is terminated.
      process_tcp(tcp_buffer_count);

    check_rtc();
    lastTCPScan = millis();
  }
}

/*---------------------------------------------------------------------------------
 *  void process_tcp()
 *  Read and process any TCP server input:
 *
 *  This routine will be called when a string terminator is found in the tcp_buffer
 */
void process_tcp(uint16_t tcp_byte_count) {
  char tcp_buffer[tcp_buffer_count];
  int instr_index = 0;

  SIM900.readBytes(tcp_buffer, tcp_byte_count);

//    mySerial.print("Instruction:");
//    mySerial.println(instruction);

    if (tcp_buffer[0] == 'I') {
      mySerial.println("Instruction received");
      if (sendATcommand2_v1("AT+CIPSEND", ">", "ERROR", 2000, 3) == 1)
      {
        SIM900.print("ack");
        SIM900.print('\x1A');
      }
      if (tcp_buffer[1] == 'M') { // what is 'M'
        readFlashMin1(1000 * (tcp_buffer[2] - '0') + 100 * (tcp_buffer[3] - '0') + 10 * (tcp_buffer[4] - '0') + (tcp_buffer[5] - '0'));
        if (sendATcommand2_v1("AT+CIPSEND", ">", "ERROR", 2000, 3) == 1) {
          for (int j = 0; j < 245; j++) {
            SIM900.print(trnsmt_buf1[j]);  // what is this ?
            SIM900.print("+");  // why a "+", and anyway should be '+'
          }
          SIM900.print('\x1A');
        }
      }
    }
}

/*---------------------------------------------------------------------------------
 *  void check_rtc()
 *  Check and update time from modbus registers from power meter:
 *
 *  May be best if you either work in minutes per day or Unix time rather than this:
 */
void check_rtc() {
  if(rtc_min != regs[122]) {
    rtc_min = regs[122];
    rtc_hour = regs[124];
    rtc_day = EEPROM.read(0);
    writeToFlashMin1(1440 * rtc_day + rtc_hour * 60 + rtc_min + 1);  // this seems wrong, why rtc_day * 1440 and rtc_hour * 60 ?
  }

  if ((rtc_min == 59) && (rtc_hour == 23)) { // if you want to use this method, why not check for trigger of 0h 00m ?
    if(next_day_flag == true) {
      next_day_flag = false;
      if (EEPROM.read(0) == 4)
        EEPROM.write(0, 0);
      else {
        rtc_day++;
        EEPROM.write(0, rtc_day);
        mySerial.print("New day: ");
        mySerial.println(rtc_day);
      }
    }
  } else
    next_day_flag = true;

//  if (sendATcommand2("AT+CIPSTATUS", "SERVER LISTENING","CONNECT OK", 1000)  == 0 ) { // not sure what this is all about ?
//    power_on();
//  }
}


____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: bojankoce on Oct 02, 2015, 04:56 pm
Paul,

Thank you for your unbelievable effort to help me. I was reading through your code and I can say I understand your approach and what you suggest to me. I will try implementing your code (i.e. to re-organize my own) in a near future.

You said that you don't know some of the functions in my code. Here attached are three files that contain all the code I use. I hope that by looking into the files you will have a complete insight into what I want to implement.


Quote
Can you explain the following part of your code:
Code: [Select]
readFlashMin1(1000 * (instruction[2] - '0') + 100 * (instruction[3] - '0') + 10 * (instruction[4] - '0') + (instruction[5] - '0'));
The function readFlashMin1(int) take some integer as an argument and reads about 250 consecutive DataFlash memory location starting from the address defined by the integer. This integer value is something I receive from the remote client.
Instruction received from the remote client is in the format 'IMxxxx' where xxxx is an unsigned integer from the range [0 - 7200]. What I receive from the client is stored in the 'instruction[]' array. Consequently, instruction[2], instruction[3], instruction[4], and instruction[5] contain the values of xxxx in the form of bytes.

Quote
If I understand what you are trying to do, you can't do this, you are attempting to do maths on a char data type:
Code: [Select]
1000 * ('x' - '0')
I don't think I'm wrong here. At least, I obtain expected result. if 'x' is an ASCII value of the numerics 0-9, i.e. from 0x30 to 0x39, if I subtract 'x' from '0' (which is 0x30), I will actually convert a byte to integer (I will obtain result from 0 to 9 decimal). Right?

Quote
Where are the functions power_on and establish_TCP_server and sendATcommand2 ?
Where did you get the dataflash library from, can you supply a link please ?
I am assuming you are using the SimpleModbusMaster2v2 library, yes ?
As I said, you now have attached complete code that I use.
Regarding a dataflash library, I have AT45DB161D flash memory chips and the library I use for it can be found here (https://forum.arduino.cc/index.php?topic=298022.0).
Regarding the ModbusMaster library, I'm using v2rev2, you are right.

Thank you for the suggestions on how to organize the code. The template you proposed when re-writing my code looks pretty good for me. I will force myself to adopt it.

Sincerely,
Bojan.




Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: pathead on Oct 04, 2015, 06:55 pm
Can anyone post an example of how to convert 2 registers into a single floating point number?

Thank you!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: bojankoce on Oct 04, 2015, 07:11 pm
Code: [Select]

 float FreqL1;
 unsigned long temp1 = (unsigned long) regs[150]<<16 | regs[151];
 FreqL1 = *(float*)&temp1;


Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: pathead on Oct 04, 2015, 09:07 pm
Code: [Select]

 float FreqL1;
 unsigned long temp1 = (unsigned long) regs[150]<<16 | regs[151];
 FreqL1 = *(float*)&temp1;



Wow thank you so much that is just perfect.  Been trying to figure this out for the last 3 hours...
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: uausa on Oct 07, 2015, 10:50 pm
After a much time of trying Modbus communication and Arduino I must ask for help ... 

goal : connect Temperature sensor to Arduino ( uno, due, pro-mini) accros through modbus then usb send to some pc app and see T value in Modbus Poll, QModBus  ...

I have same TTL/485 converter and usb/485 converter like in this example :
http://adatum.ru/podklyuchenie-konvertera-rs-485-v-ttl-k-arduino.html

I make connection as on picture from link one ttl/485, one usb/485 and one UNO.
In device manager Win7x64b usb/485 recognised as usb-serial CH340 on port 4 and UNO with same label but on other port, port 20.

I combine code from sketch below picture with dht11.ino from example folder in DHTlib library
Code: [Select]
#include <ModbusRtu.h>
Modbus slave(1,0,1);

#include <dht.h>
dht DHT;
#define DHT11_PIN 5  // T i H se preuzima na pinu 5

#define SerialTxControl 10   //RS485  arduino pin 10
#define RS485Transmit    HIGH
#define RS485Receive     LOW  
char buffer[100];

void setup(void) {
  Serial.begin(9600);
   pinMode(SerialTxControl, OUTPUT);  
   digitalWrite(SerialTxControl, RS485Transmit);
   Serial.println("TEST");  
  delay(100);
  digitalWrite(SerialTxControl, RS485Receive);  
  Serial.println("DHT TEST PROGRAM ");
  Serial.print("LIBRARY VERSION: ");
  Serial.println(DHT_LIB_VERSION);
  Serial.println();
  Serial.println("Type,\tstatus,\tHumidity (%),\tTemperature (C)");
}
 
void loop(void) {
digitalWrite(SerialTxControl, RS485Receive);  //
int i=0; if(Serial.available()){delay(100);
while( Serial.available() && i< 99)
{ buffer[i++] = Serial.read();} buffer[i++]='\0';}
  if(i>0)
  {
  Serial.println(buffer); //
 }

  Serial.print("DHT11, \t");
  int chk = DHT.read11(DHT11_PIN);
  switch (chk)
  {
    case DHTLIB_OK:  
   Serial.print("OK,\t");
    break;
    case DHTLIB_ERROR_CHECKSUM:
    Serial.print("Checksum error,\t");
    break;
    case DHTLIB_ERROR_TIMEOUT:
    Serial.print("Time out error,\t");
    break;
    case DHTLIB_ERROR_CONNECT:
        Serial.print("Connect error,\t");
        break;
    case DHTLIB_ERROR_ACK_L:
        Serial.print("Ack Low error,\t");
        break;
    case DHTLIB_ERROR_ACK_H:
        Serial.print("Ack High error,\t");
        break;
    default:
    Serial.print("Unknown error,\t");
    break;
  }
  // DISPLAY DATA
  Serial.print(DHT.humidity, 1);
  Serial.print(",\t");
  Serial.println(DHT.temperature, 1);

  delay(2000);
}


and serial monitor of Arduino app display proper T and H from sensor every 2 sec .
Problem is in modbus comm when on Qmodbus or ModbusPoll apps getting nonsense data 
I work with modbus in other platform and i know that T or H must write in Registers in form 1 byte. 
What I must do to solve this example?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Exander on Oct 09, 2015, 12:00 pm
Hi guys,
I seem to have a problem with the library

modbus_construct(&packets[B1_VALUE], 1, READ_HOLDING_REGISTERS, 1, 1, 1);

generates

00 00 00 01 00 01 90 1B

wich is not correct, any advices?
Thank You
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: manjunathele on Oct 13, 2015, 07:30 am
Hai every one,

I am Manjunath & new to use Arduino, I want read Power meter(Model no EN8400) Mod-Bus RTU through RS485. I have read/checked/test with MOXA-Uport-1130 that is USB to RS485 converter by using Mod-bus -Tester and OK.I am attaching PIC also you can see.

Now my goal is read Mod-bus data of Holding register values at-least for every one second OK. and show the data on Hyper terminal/Hercules OK.
Even though I am attaching the code also. I do not know where I am doing mistake. I can not find out this thing.Now I am in pressure. Please help me....Sorry for bad English and Thanks in advance.

---- Manjuanth
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: uausa on Oct 13, 2015, 10:46 pm
if I understand :
combination {Pm/EN8400--rs485}<---ser485/cable-usb-->{PC(modbus tester)}   working fine

You want the {Pm/EN8400--rs485}<  ?? ? ??    >{PC(Hyper or Hercules)} to display data on screen of PC ?!

If ?? ? ?? is ser/usb moxa cabl You get first solution, but because You put Arduino sketch in post, maybe you want that part of ?? ? ?? is some arduino board ?!

With first combination and with some scada software you can create fine and easy HMI. And this is the end.

Arduino is needed if you want some phisical data from some sensor(s) put on modbus ( in this topic) communication line and allow to view all device on this modbus network who need this value. For example, if you need on scada value of state of relay, with arduino sketch/DI you check is it open or close contact, then current state as data form with modbus library, send as output serial data to the max485, and further through modbus net to the target device.

I stopped with modbus library and sketch who can send  data as modbus data.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: manjunathele on Oct 14, 2015, 07:21 am
uausa,

Thanks understand my topic, Yes your wright. The Arduino is used as madbus tester, need to send data on PC.
I did not check relays change or functionality of EN-8400.But I will do it.

I have added code that's working only thing is Ardunio communicating for some few seconds time only. if press reset button Ardunio then ok for few seconds.

I read the data on terminal and I am not sure whether it is wrong / right data.

According to you what is correct form of the modbus data from the EN8400?

I want read total 125 holding registers data continuously for every 1 second period.

Please help me.

----- Manjunath
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: manjunathele on Oct 15, 2015, 01:31 pm
I am not getting the modbus data from Elmeasure EN8400 to duemilanove  , I have trying for a week. but no luck. When I sending data to it. its com led starts blinking, but not send the data to duemilanove  .

I am using

I want to read frequency parameter  at 40157 holding register ;
 slave id is 4 ;
 serial baud 9600 8bit;
 even parity;
 1 stop bit ;

How can see the received data from EN8400 energy meter.?

 can any body help me where i done mistakes.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Oct 15, 2015, 03:08 pm
manjunathele, I'm not sure where to start.
After being told a few times over on the Midnightsolar forum where you posted your vague question which had nothing to do with that forum and now over here, where you say in one post you want to read 125 registers and then in another post you then only want 1 register, I can only conclude you are totally lost and confused over what you are wanting and how to program a program that successfully do what you want.

First, be consistent in what you are saying.
Second, detail your problems clearly so others can easily understand and have a better chance of offering you some sort of help. You will find if you can be consistent and clear, you will attract more help.

Next, your code a few posts back at reply #421 has a few issues:
You only have one packet, so make it so:
Code: [Select]
enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS // leave this last entry
};


You only allow for 1 modbus read register when you have the following:
Code: [Select]
unsigned int readRegs[1];So, make sure you only ever address this one register and not more.

Just to make sure you understand, you are sending any serial messages via the software serial which is set to communicate on pins 10 and 11. You will need a TTL to USB converter to be able to see this on your PC in a terminal program.
Do you understand this and have it set up accordingly ?
Have you proved your messages come to the PC terminal program ?

Be clear and understand, you will communicate to the power meter via the hardware serial port which is on pins 0 and 1, with pin 2 as tx enable for the RS-485 transmitter.
What form of TTL to RS-485 converter are you using on the Arduino, and does it use Tx enable on pin 2 ?

You would be better to use the softwareSerial library to communicate to the power meter and use the normal USB provided on the Arduino to communicate to your PC.

Next, remember you only have 1 read register declared, so the following is rubbish:
Code: [Select]
for(unsigned char i=0;i<124;i++)
There is no more registers than readReg[0], just one and only one, due to you only declaring one.

Your mail loop() is racing around at full speed, with printing your results as fast as it is possible.
I don't think this is what you want, slow down the printing via a time based event check.

Lots of questions for you to sort out, but you seem to make it so difficult for yourself unfortunately.
___________________
Paul Alting van Geusau
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: manjunathele on Oct 17, 2015, 09:26 am
 rockwallaby,

I really appreciate your feed back on my messages.
I am new to use Arduino & I dont know where to post message and query......
At that time I was in trouble & dont know how to use modbus library kept in arduino site.Code  - Modbus Master (http://playground.arduino.cc/Code/ModbusMaster)
even I tried with google.... no library is not helped me.I have seen replies and put my message
for my output.

After seeing modbus topics on so many fourms for arduino. Now I have answers for all your questions.
Quote
Do you understand this and have it set up accordingly ?
Have you proved your messages come to the PC terminal program ?

Be clear and understand, you will communicate to the power meter via the hardware serial port which is on pins 0 and 1, with pin 2 as tx enable for the RS-485 transmitter.
What form of TTL to RS-485 converter are you using on the Arduino, and does it use Tx enable on pin 2 ?

for this please see the pics, Yes I know how to connect usb to serial converter to arduino & I confirm that even RS485 circuit also working because I it is connected com led starts bilking while tx and rx happened.
Arduino pin 0 for Ro of Max 485.
Arduino pin 1 for Di  of Max 485
Arduino pin 2 for both short of RE&DE of Max 485.

Arduino pin 10 for RX 232 TTL
Arduino pin 11 for Tx  232 TTL


Quote
Next, remember you only have 1 read register declared, so the following is rubbish:
Code: [Select]
for(unsigned char i=0;i<124;i++)

There is no more registers than readReg[0], just one and only one, due to you only declaring one.
but no luck its not shows data on terminal, that why I trying with many libraries and asking for help in forums..... By your feedback only I got an Idea.. Thanks a lot for that.

I just know about readReg that its store read modbus data from my energy meter.
 for showing all addresses 40101 to 40125 data on terminal I used
Quote
for(unsigned char i=0;i<124;i++)
Now please tell me where is my mistake happened?

forget what happened with me,Now Clearly asking that Which library I need to use?
How to see entire all holding registers data on terminal as string,  thtat for Example
"30.12,48,15,444,47,50.12, bla bla bla......this only my exact goal

please see the pics I have clearly mentioned what I am doing....
Sorry for my bad English and thanks in advance.


------ Manjunath
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Oct 18, 2015, 11:50 pm
manjunathele,

You absolutely need to read the documentation that goes with the library for SimpleModbusMaster or you will not understand some of the very important details that you will need to know.

The Arduino only has a small serial hardware buffer, 64 bytes. You can not expect to read in a single packet all 125 registers, as that equates to 250 bytes. Remember, 1 register is 16 bits, which is 2 bytes.

Please read the documentation thoroughly to know exactly the process and limitations for Arduino.

Try the following code:

Code: [Select]
#include <SimpleModbusMaster.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX

//////////////////// Port information ///////////////////
#define baseAddress 40101       // start address
#define registersPerPacket 25   // number of registers per packet: (read the manual on this, very important)

#define slaveID 4
#define baud 9600
#define timeout 1000
#define polling 1000            // the scan rate

// If the packets internal retry register matches the set retry count then communication is stopped
// on that packet. To re-enable the packet you must set the "connection" variable to true.
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

#define LED 9

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS is automatically updated.
enum
{
  PACKET1,
  PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Create a packetPointer to access each packet
// individually. This is not required you can access
// the array explicitly. E.g. packets[PACKET1].id = 2;
// This does become tedious though...
packetPointer packet1 = &packets[PACKET1];
packetPointer packet2 = &packets[PACKET2];

// Data read from the arduino slave will be stored in this array
// if the array is initialized to the packet.
unsigned int readRegs[totalRegisters];

// Data to be written to the arduino slave
// unsigned int writeRegs[1];

// total number of registers to get. This will be registersPerPacket * TOTAL_NO_PACKETS
  int totalRegisters = registersPerPacket * TOTAL_NO_OF_PACKETS

void setup() {
  mySerial.begin(4800);
  mySerial.println("Starting");

  // The modbus packet constructor function will initialize the individual packet with the assigned parameters.
  // You can always do this explicitly by using struct pointers.
  // The first parameter is the address of the packet in question.
  // It is effectively the "this" parameter that points to the address of the passed object.
  // It has the following form:
  //   modbus_construct(packet, id, function, address, data, register array)
  //   For functions 1 & 2 data is the number of points
  //   For functions 3, 4 & 16 data is the number of registers
  //   For function 15 data is the number of coils
 
  modbus_construct(packet1, slaveID, READ_HOLDING_REGISTERS, baseAddress, registersPerPacket, readRegs);
  modbus_construct(packet2, slaveID, READ_HOLDING_REGISTERS, baseAddress + registersPerPacket, registersPerPacket, regRegs)
 
  // write 1 register starting at address 1 
  // modbus_construct(packet2, 1, PRESET_MULTIPLE_REGISTERS, 1, 1, writeRegs);
 
  // P.S. the register array entries above can be different arrays
 
  /* Initialize communication settings:
     parameters(HardwareSerial* SerialPort,
long baud,
unsigned char byteFormat,
unsigned int timeout,
unsigned int polling,
unsigned char retry_count,
unsigned char TxEnablePin,
Packet* packets,
unsigned int total_no_of_packets);

     Valid modbus byte formats already defined in the Arduino global name space are:
     SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
     SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
     SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
     
  */
  modbus_configure(&Serial, baud, SERIAL_8E2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
 
  pinMode(LED, OUTPUT);
}

void loop() {
  modbus_update();

  for(int i = 0; i < totalRegisters; i++) {
    mySerial.print(F("Register: "));
    mySerial.print(i);
    mySerial.print(F(" : "));
    mySerial.println(readRegs[i]);
  }

  delay(1000);  // a delay of sorts to slow down the getting and printing of data to console:

//  writeRegs[0] = analogRead(A0); // update data to be written to arduino slave
//  analogWrite(LED, readRegs[0]>>2); // constrain adc value from the arduino slave to 255
 
  /* You can check or alter the internal counters of a specific packet like this:
     packet1->requests;
     packet1->successful_requests;
     packet1->failed_requests;
     packet1->exception_errors;
     packet2->requests;
     packet2->successful_requests;
     packet2->failed_requests;
     packet2->exception_errors;
  */
}


I did not take the time to test it, just in a simple text editor.
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: manjunathele on Oct 19, 2015, 10:16 am
rockwallaby,

Thanks for your reply and for your attached code for me.

I have copied and pasted and compile on my Arduino_1.6.5 and with SimpleModbusMasterV12 library

compiled and have some errors as shown below...



Modbus_Test_1:4: error: 'registersPerPacket' does not name a type
Modbus_Test_1:44: error: 'totalRegisters' was not declared in this scope
Modbus_Test_1:52: error: expected ',' or ';' before 'void'
Modbus_Test_1.ino: In function 'void loop()':
Modbus_Test_1:103: error: 'readRegs' was not declared in this scope
'registersPerPacket' does not name a type



I have solved Modbus_Test_1:4: error: 'registersPerPacket' does not name a type
Modbus_Test_1:52: error: expected ',' or ';' before 'void'

Even though few errors still unsolved by me . can you please guess whats the wrong..


I am attaching .ino file please look into that...
Modbus_Test_1:44: error: array bound is not an integer constant before ']' token
Modbus_Test_1.ino: In function 'void setup()':
Modbus_Test_1:66: error: 'readRegs' was not declared in this scope
Modbus_Test_1:67: error: 'reagRegs' was not declared in this scope
Modbus_Test_1.ino: In function 'void loop()':
Modbus_Test_1:103: error: 'readRegs' was not declared in this scope
array bound is not an integer constant before ']' token
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Oct 19, 2015, 10:46 am
I took your code and put it into my setup and made a small adjustment.
The following code compiles.

You need to make sure you have libraries;
Softwareserial,
SimpleModbusMasterV11

Code: [Select]
#include <SimpleModbusMaster.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX

//////////////////// Port information ///////////////////
#define baseAddress 40101       // start address
#define registersPerPacket 25   // number of registers per packet: (read the manual on this, very important)

#define slaveID 4
#define baud 9600
#define timeout 1000
#define polling 1000            // the scan rate

// If the packets internal retry register matches the set retry count then communication is stopped
// on that packet. To re-enable the packet you must set the "connection" variable to true.
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

#define LED 9

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS is automatically updated.
enum
{
  PACKET1,
  PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Create a packetPointer to access each packet
// individually. This is not required you can access
// the array explicitly. E.g. packets[PACKET1].id = 2;
  packetPointer packet1 = &packets[PACKET1];
  packetPointer packet2 = &packets[PACKET2];
#define totalRegisters registersPerPacket * TOTAL_NO_OF_PACKETS

// Data read from the arduino slave will be stored in this array
// if the array is initialized to the packet.
unsigned int readRegs[totalRegisters];

// Data to be written to the arduino slave
// unsigned int writeRegs[1];

// total number of registers to get. This will be registersPerPacket * TOTAL_NO_PACKETS
//  int totalRegisters = registersPerPacket * TOTAL_NO_OF_PACKETS;

void setup() {
  mySerial.begin(4800);
  mySerial.println("Starting");

  // The modbus packet constructor function will initialize the individual packet with the assigned parameters.
  // You can always do this explicitly by using struct pointers.
  // The first parameter is the address of the packet in question.
  // It is effectively the "this" parameter that points to the address of the passed object.
  // It has the following form:
  //   modbus_construct(packet, id, function, address, data, register array)
  //   For functions 1 & 2 data is the number of points
  //   For functions 3, 4 & 16 data is the number of registers
  //   For function 15 data is the number of coils

  modbus_construct(packet1, slaveID, READ_HOLDING_REGISTERS, baseAddress, registersPerPacket, readRegs);
  modbus_construct(packet2, slaveID, READ_HOLDING_REGISTERS, baseAddress + registersPerPacket, registersPerPacket, readRegs);

  // write 1 register starting at address 1
  // modbus_construct(packet2, 1, PRESET_MULTIPLE_REGISTERS, 1, 1, writeRegs);

  // P.S. the register array entries above can be different arrays

  /* Initialize communication settings:
     parameters(HardwareSerial* SerialPort,
    long baud,
    unsigned char byteFormat,
    unsigned int timeout,
    unsigned int polling,
    unsigned char retry_count,
    unsigned char TxEnablePin,
    Packet* packets,
    unsigned int total_no_of_packets);

     Valid modbus byte formats already defined in the Arduino global name space are:
     SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
     SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
     SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit

  */
  modbus_configure(&Serial, baud, SERIAL_8E2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);

  pinMode(LED, OUTPUT);
}

void loop() {
  modbus_update();

  for(int i = 0; i < totalRegisters; i++) {
    mySerial.print(F("Register: "));
    mySerial.print(i);
    mySerial.print(F(" : "));
    mySerial.println(readRegs[i]);
  }

  delay(1000);  // a delay of sorts to slow down the getting and printing of data to console:

//  writeRegs[0] = analogRead(A0); // update data to be written to arduino slave
//  analogWrite(LED, readRegs[0]>>2); // constrain adc value from the arduino slave to 255

  /* You can check or alter the internal counters of a specific packet like this:
     packet1->requests;
     packet1->successful_requests;
     packet1->failed_requests;
     packet1->exception_errors;
     packet2->requests;
     packet2->successful_requests;
     packet2->failed_requests;
     packet2->exception_errors;
  */
}

____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: manjunathele on Oct 19, 2015, 01:55 pm
rockwallaby,

I have compiled and uploads on Arduino so many time but output on serial sofrware is showing only zeros per location.

so here we can read only 50 registers.

From your previous message what I under-stood that readRegs register is 16 bits i.e., 2bytes ;Arduino serial hardware buffer, 64 bytes. This means I can read 32 registers only wright.!

For testing purpose, no load connecting to EN8400 but only one Holding register that is 40157(Frequency parameter) is can be read as value on soft serial.

If I want to read further Holding registers, then how? Is Arduino Duemilanove  can not helps me?

Regards
--- Manjunath



out put of soft serial can you watch by attached file.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Oct 19, 2015, 02:02 pm
Quote
This means I can read 32 registers only wright.!
wrong, read the documentation about the SimpleModbusMaster. You will learn that the Modbus protocol will also use some bytes for itself, leaving you even less, depending on the function used.

You can read more by creating more packets than the two packets you already have.
What you have is a start, try to make it work with just a few registers first, then when you succeed, then increase your request for more registers.

If you are only getting zeros, then look for the reason.
Learn to debug your code.
learn to use the error codes that are available to you in the protocol.

____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: gerasalus on Oct 19, 2015, 04:33 pm
What would be the best way to send temperature (two decimal places) via modbus (temperature range -55C +125C)?

1) create a function for converting on both sides, where 0 is -55 and 65535 is +125
2) Use two registries - one for sign, other for temperature multiplied by 100 or 10000 (dependending on the precision)
3)... ?


With option 1 i might loose some precision (probably not significat) but option 2 takes two registers.

Since i'm using ds18b20 sensors, arduino library for those sensors  reports temperatures by signed ints in range of -7040 - 16000, so if i want those raw numbers, option 1 does not work, i first need to convert them to C (again some precission loss)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: manjunathele on Oct 19, 2015, 04:36 pm
rockwallaby,

I have read your simplemodbusmanual.pdf I understood some basic points &
I have just modified few lines your code as per my requirement. I checked output on Hercules Terminal with patiently, but no luck all address locations shows 0 0 0 0 0 0 0 0 0 0 upto 100 registers,

I have created 4 packets and 4 readRegs and 4 modbus_construct().
finally readRegs1,2,3,4 put for output on Hercules Terminal.

I have read your simplemodbusmanual.pdf I understood some basic points.Even though my rs485 ckt is also OK as compare with shows on manual.
See the output is possible by using the Arduino or not? Its become a like dream for me.

I am attaching code. Please look it in to and tell where I done mistakes?

Regards

Manjunath
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: manjunathele on Oct 20, 2015, 01:55 pm
rockwallaby,

I need your help on above message

----- Manjunath
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: monk_duck1 on Oct 21, 2015, 10:20 am
Hi,

I'm very new with modbus, and I'm trying to do some tests. So I have an project where arduino nano works as slave and PLC as master. Is following hardware correct for that? Is the D- same as rs485 DX and D+ same as TX?


I'm trying also to figure out the (SimpleModbusSlaveArduino) code part:

Quote
ADC_VAL,
- At the enum this is analog/digital INPUT value register 0?
Quote
holdingRegs[ADC_VAL] = analogRead(A0);
-Here I tell is the value analog, digital and which PIN. Also prepare data to be read by master?
Quote
PWM_VAL,
-analog/digital OUTPUT?
Quote
analogWrite(LED, holdingRegs[PWM_VAL]>>2);
-writes value to the LED from master's register 0 or what?  what is >>2?
Quote
modbus_update();
-Is not must?

If I want to add more registers, I can just write at enum:
ADC_VAL,
ADC_VAL1,
ADC_VAL2..?


thanks,
Joonatan
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Oct 21, 2015, 12:01 pm
Hi guys,
      Thanks for the library, I am new in all this! and i have to make a project on making a arduino based master and slave for communicating with each other on sensor values of slave with plc. Hope this will help me a lot! I will post my queries if i got any thanks for your help!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Oct 23, 2015, 12:18 pm
Hey guys i read those documents and posts over here, I want to establish comunication pair between master and slave UNO, so can I simulate it over proteus, and if yes how?
sorry guys I am too bad in this all, so asking foolish questions but I really not understanding how to make it!
I downloaded proteus library for arduino also find hex files of arduino, but now i dont understand how to test it.
1> Do i need to use max232 or other IC as I am directly connection two arduinos with rx-->tx, tx-->rx
2> Should I use led or how to check memory locations with proteus.
3>Could any body can share the schematic which I have to build to test it?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: manjunathele on Oct 26, 2015, 10:56 am
Paul,


Thanking you so much. what you suggest me, each and every word is correct.

I have got ultimate success. I learn lot from you.

Many more thanks once again for your ultimate support.

Its time to celebrate and complete my main task.

Manjunath
India.

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: manjunathele on Oct 26, 2015, 11:23 am
yatin,

monk_duck1 ,


Hai for the last few days your posting your requirement.

can you send block diagram with arduino what you want to doing.

Manjunath
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Oct 26, 2015, 11:29 am
Manjunathele,
Congradulations for your success!
I just want to communicate between two arudino UNO with this protocol nothing else for now! I am trying with different codes but I am unable to understand how to test it on proteus or where in memory location that data exactly goes in slave or in master that's all!
Here is my code that I am trying to use
Master:-
Code: [Select]
/**
 *  Modbus master example 1:
 *  The purpose of this example is to query an array of data
 *  from an external Modbus slave device.
 *  The link media can be USB or RS232.
 *
 *  Recommended Modbus slave:
 *  diagslave http://www.modbusdriver.com/diagslave.html
 *
 *  In a Linux box, run
 *  "./diagslave /dev/ttyUSB0 -b 19200 -d 8 -s 1 -p none -m rtu -a 1"
 * This is:
 * serial port /dev/ttyUSB0 at 19200 baud 8N1
 * RTU mode and address @1
 */

#include <ModbusRtu.h>

// data array for modbus network sharing
uint16_t au16data[16];
uint8_t u8state;

/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  u8serno : serial port (use 0 for Serial)
 *  u8txenpin : 0 for RS-232 and USB-FTDI
 *               or any pin number > 1 for RS-485
 */
Modbus master(0,0,0); // this is master and RS-232 or USB-FTDI

/**
 * This is an structe which contains a query to an slave device
 */
modbus_t telegram;

unsigned long u32wait;

void setup() {
  master.begin( 19200 ); // baud-rate at 19200
  master.setTimeOut( 2000 ); // if there is no answer in 2000 ms, roll over
  u32wait = millis() + 1000;
  u8state = 0;
}

void loop() {
  switch( u8state ) {
  case 0:
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1:
    telegram.u8id = 1; // slave address
    telegram.u8fct = 3; // function code (this one is registers read)
    telegram.u16RegAdd = 1; // start address in slave
    telegram.u16CoilsNo = 4; // number of elements (coils or registers) to read
    telegram.au16reg = au16data; // pointer to a memory array in the Arduino

    master.query( telegram ); // send query (only once)
    u8state++;
    break;
  case 2:
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 100;
    }
    break;
  }
}

And for slave:-
Code: [Select]
/**
 *  Modbus slave example 1:
 *  The purpose of this example is to link a data array
 *  from the Arduino to an external device.
 *
 *  Recommended Modbus Master: QModbus
 *  http://qmodbus.sourceforge.net/
 */

#include <ModbusRtu.h>

// data array for modbus network sharing
uint16_t au16data[16] = {
  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, -1 };

/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  u8serno : serial port (use 0 for Serial)
 *  u8txenpin : 0 for RS-232 and USB-FTDI
 *               or any pin number > 1 for RS-485
 */
Modbus slave(1,0,0); // this is slave @1 and RS-232 or USB-FTDI

void setup() {
  slave.begin( 19200 ); // baud-rate at 19200
}

void loop() {
  slave.poll( au16data, 16 );
}


The schematic that I am using is:-
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: monk_duck1 on Oct 26, 2015, 12:44 pm
Hi Majunath,

There is a temperature sensor connected in the arduino nano's port A5.

Master (PLC) should ask the value of the sensor from slave (arduino nano)
-> arduino answers the value using modbus rtu protocol with rs485. Nothing else for now.

I just need to know if this schematic (picture from my post before) is correct.
And I'm not fully sure about the code.. Maybe someone could give me an example?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Oct 27, 2015, 05:40 am
Hey guys I figured it out that it gets stored in au16data variable in proteus where i can check this data out, but still I don't no in which memory it is getting stored or do it take random available memory! But for now its ok for me, as it is getting at least transfer so now i can at least check it with diff software. If I came across any problem I will post over here thanks!
Now I am trying to make use of function 16 and write some numbers on slave registers, lets see how it goes!
Thanks for your help friends!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Oct 27, 2015, 06:48 am
Hey friends,
First of all sorry for multiple posts,
I got success in establishing 3rd function that is reading from slave memory location, thanks a lot for it!
But now I am unable to establish function 16! as code that I share above is only for query to an slave device, not to write it!
I found only one library and example which can make function 16 I am sharing that here.
Code: [Select]
#include <SimpleModbusMaster.h>

/*
   The example will use packet1 to read a register from address 0 (the adc ch0 value)
   from the arduino slave (id=1). It will then use this value to adjust the brightness
   of an led on pin 9 using PWM.
   It will then use packet2 to write a register (its own adc ch0 value) to address 1
   on the arduino slave (id=1) adjusting the brightness of an led on pin 9 using PWM.
*/

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

#define LED 9

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 1

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
  // Initialize each packet
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 1, 0);
  modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
  
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
  
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
  
  regs[0] = analogRead(0); // update data to be written to arduino slave
  
  analogWrite(LED, regs[0]>>2); // constrain adc value from the arduino slave to 255
}


Slave code:-
Code: [Select]
#include <SimpleModbusSlave.h>

/*
   SimpleModbusSlaveV10 supports function 3, 6 & 16.
  
   This example code will receive the adc ch0 value from the arduino master.
   It will then use this value to adjust the brightness of the led on pin 9.
   The value received from the master will be stored in address 1 in its own
   address space namely holdingRegs[].
  
   In addition to this the slaves own adc ch0 value will be stored in
   address 0 in its own address space holdingRegs[] for the master to
   be read. The master will use this value to alter the brightness of its
   own led connected to pin 9.
  
   The modbus_update() method updates the holdingRegs register array and checks
   communication.

   Note:  
   The Arduino serial ring buffer is 64 bytes or 32 registers.
   Most of the time you will connect the arduino to a master via serial
   using a MAX485 or similar.
 
   In a function 3 request the master will attempt to read from your
   slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES
   and two BYTES CRC the master can only request 58 bytes or 29 registers.
 
   In a function 16 request the master will attempt to write to your
   slave and since a 9 bytes is already used for ID, FUNCTION, ADDRESS,
   NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write
   54 bytes or 27 registers.
 
   Using a USB to Serial converter the maximum bytes you can send is
   limited to its internal buffer which differs between manufactures.
*/

#define  LED 9  

// Using the enum instruction allows for an easy method for adding and
// removing registers. Doing it this way saves you #defining the size
// of your slaves register array each time you want to add more registers
// and at a glimpse informs you of your slaves register layout.

//////////////// registers of your slave ///////////////////
enum
{    
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  ADC_VAL,    
  PWM_VAL,        
  HOLDING_REGS_SIZE // leave this one
  // total number of registers for function 3 and 16 share the same register array
  // i.e. the same address space
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array
////////////////////////////////////////////////////////////

void setup()
{
  /* parameters(HardwareSerial* SerialPort,
                long baudrate,
unsigned char byteFormat,
                unsigned char ID,
                unsigned char transmit enable pin,
                unsigned int holding registers size,
                unsigned int* holding register array)
  */
  
  /* Valid modbus byte formats are:
     SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
     SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
     SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
    
     You can obviously use SERIAL_8N1 but this does not adhere to the
     Modbus specifications. That said, I have tested the SERIAL_8N1 option
     on various commercial masters and slaves that were suppose to adhere
     to this specification and was always able to communicate... Go figure.
    
     These byte formats are already defined in the Arduino global name space.
  */

  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, byteFormat, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(9600, SERIAL_8N2, 1);
  
  pinMode(LED, OUTPUT);
}

void loop()
{
  // modbus_update() is the only method used in loop(). It returns the total error
  // count since the slave started. You don't have to use it but it's useful
  // for fault finding by the modbus master.
  
  modbus_update();
  
  holdingRegs[ADC_VAL] = analogRead(A0); // update data to be read by the master to adjust the PWM
  
  analogWrite(LED, holdingRegs[PWM_VAL]>>2); // constrain adc value from the arduino master to 255
  
  /* Note:
     The use of the enum instruction is not needed. You could set a maximum allowable
     size for holdinRegs[] by defining HOLDING_REGS_SIZE using a constant and then access
     holdingRegs[] by "Index" addressing.
     I.e.
     holdingRegs[0] = analogRead(A0);
     analogWrite(LED, holdingRegs[1]/4);
  */
  
}

1.But I didn't understand exactly where in here we are defining function which we need to execute either 3 or 16!
2.I tried this code in circuit I attached but it giving errors count 19 and all requests are get failed so communicating at all! I am shearing the pictures of these too, so if there is any suggestions for me it would be lot helpful for me!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: manjunathele on Oct 27, 2015, 07:56 am

yatin,


Please read the documentation thoroughly to know exactly the process and limitations for Arduino.
You need to read the documentation that goes with the library for SimpleModbusMaster or you will not understand some of the very important details that you will need to know.


Manjunath
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Oct 27, 2015, 08:33 am
Hi Manjunath,
Thanks for your suggestion, I read those documents it made many of my concepts clear and also provide great idea about this library and framing of protocol!
Still I have following problems,
1.There are many resistors are suggested for pulling purpose but as I am using it on proteus not on hardware and also not using computer interface so do I still need max232 kind IC's and those pull up resistors.
2. In my above shared program do I need any additional delays?
3. Right now I am making 10 requests and all of them getting failed with exception errors for the above shared hardware configuration, so where am i doing wrong?
And really thankful for your suggestions and guidelines.
Yatin
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Oct 27, 2015, 11:27 am
Hey Monk_duck 1,
I am not good in this section yet, but read this following link It may give you little idea, and help you out from your difficulties.
https://drive.google.com/folderview?id=0B0B286tJkafVYnBhNGo4N3poQ2c&usp=drive_web&tid=0B0B286tJkafVSENVcU1RQVBfSzg
If you have already read this then sorry, let some expert give you the answer!
Yatin
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: manjunathele on Oct 27, 2015, 12:52 pm
Yatin,


Quote
1.There are many resistors are suggested for pulling purpose but as I am using it on proteus not on hardware and also not using computer interface so do I still need max232 kind IC's and those pull up resistors.
As per your shared block diagram"schematic.JPG" you connect the circuit wright.

If you connected like this I think its wrong.You need to add some circuit like RS485 for Modbus.

Even your not mention what kind of application is doing.?
what is you goal?

clearly explain what you want do with using 2 arduino pcb? and how much distance needs between
2 arduinos?
 I mean if you want to use some feets distance  ,the maximum cable length is 50 feet for RS232.

 
RS485 must work,  for more than 1000 meters with similar baud rate by using telephone twisted cable pair. The cable resistance also < 200 ohm.


Check your driver for the proper functioning

See these basic fundamentals behind the RS 232 and RS 485. OK.

Based on circuit you must use some resisters and capacitor because they reduce noise and increase
communication signal strength. OK.

Quote
2. In my above shared program do I need any additional delays?
Avoiding the delays in your code is become good program. OK.

Quote
3. Right now I am making 10 requests and all of them getting failed with exception errors for the above shared hardware configuration, so where am i doing wrong?
yes your doing absolutely wrong and look at code and start debug your code your self its very easy.
you need to read again document for why exception errors will come.OK.



Look Arduino is so easy to do coding and debugging as well as you find very working library for your task.
Go ahead good luck Yatin !

---- Manjunath
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Oct 27, 2015, 01:16 pm
Manjunathele
Hey thanks a lot!
Quote
what you want do with using 2 arduino pcb? and how much distance needs between
2 arduinos?
I want to make a program for my sensors to make them communicate with PLCs at the end, this is my final goal!
But for now to start with, I am trying to Make it run with simulating software's so right now I don't have distance problem, ( thanks for that tip as I have to consider this when I will implement this on hardware)
And now I solved my problem and now all attempts are getting successful, thanks for your advice to read data!
So as it is running on proteus I will test it with modbus testers and then I will make Hardware after its success!
Thanks for your help, thanks a lot!

Yatin
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Oct 28, 2015, 09:40 am
Hey,
Thanks for all your help guys, this program is running awesomely on mod testers also, but I am facing problem when I go to interface multiple slave on software! After reading all program I only found a single command where I should define my command i.e.
Code: [Select]
modbus_configure(&Serial, 9600, 1, 2, HOLDING_REGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(9600, 1);


In this section only making change to following for my second slave other every thing is same,
Code: [Select]
modbus_configure(&Serial, 9600, 2, 2, HOLDING_REGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(9600, 2);

But I don't no why it is not runing, it is sending data succesfully when only one id  but when I tried to send on one of two ID it is geting time out.
So is there any thing that I am missing to change?
Is it any delay problem, because my slave are receiving data which master writing using function 16, but they are not responding or may be master not receiving and attempt gets failed, so I am not understanding the problem.
also attaching my hardware I don't think there is any problem in it as it runs properly in single!
So if anyone who could help me out of this it would be a appreciated!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Nov 01, 2015, 07:01 am
I am thinking that this is more likely a hardware error on proteus as he displaying error for multiple slave about my masters RX pin is getting logic contentions. I am not understanding is it a proteus fault or my hardware is wrong, or is a programming fault.I didn't able to solve above problem, but now I am assuming it as a proteus problem so I started doing this system with hardware.
As I mentioned earlier my program is properly running on proteus with external modbus tester also. But now when I made hardware using max 485 with computer I am unable to get successful tries all of my attempts are getting time out.
I attached my circuit diagram used for max 485.
To check hardware I checked with serial write and read programs and bot are working it means my hardware is allowing arduino to write and read from computer on serial port.
I also on doubt of delay so I put 1000 polling and 5000 timeout, still its not functioning!
Can any body help me over my problem?

Yatin
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: mohit-singh on Nov 02, 2015, 08:49 pm
Hello juanB I've implemented your code to communicate with PLC via rs485 but without any success please help me out. :smiley-confuse:
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Nov 03, 2015, 10:53 am
Mohit-singh
Please post your status, your hardware diagrammed, program so that some one here can help you out.
No one could help you out until you share your problem?
What you exactly implemented?
Is slave are receiving data?
What is exact problem?
Yatin
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Nov 04, 2015, 11:24 am
hi every one,
I am trying to run code of my earlier posts from long here is my problem!
It is running on proteus properly.
But when I am trying to run it as slave and my computer as master with master simulator, my slave is receiving data properly
This is I checked with following code
Code: [Select]
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 6, 5, 4, 3);
int check;
void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // initialize the serial communications:
  Serial.begin(9600);
}

void loop() {
  // when characters arrive over the serial port...
  if (Serial.available()) {
    // wait a bit for the entire message to arrive
    delay(20);
    // clear the screen
    lcd.clear();
    // read all the available characters
    while (Serial.available() > 0) {
      // display each character to the LCD
      lcd.print(Serial.read());
      //check = Serial.read();
      //Serial.print("check");
    }
  }
}

and my lcd is showing exactly same data which my proteus lcd showing me, so i guess my arduino uno is receiving data, but when I use program
Code: [Select]
#include <SimpleModbusSlave_DUE.h>
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 6, 5, 4, 3);


/*
   SimpleModbusSlaveV10_DUE supports function 3, 6 & 16.
   
   This example code will receive the adc ch0 value from the arduino master.
   It will then use this value to adjust the brightness of the led on pin 9.
   The value received from the master will be stored in address 1 in its own
   address space namely holdingRegs[].
   
   In addition to this the slaves own adc ch0 value will be stored in
   address 0 in its own address space holdingRegs[] for the master to
   be read. The master will use this value to alter the brightness of its
   own led connected to pin 9.
   
   The modbus_update() method updates the holdingRegs register array and checks
   communication.

   Note: 
   The Arduino serial ring buffer is 64 bytes or 32 registers.
   Most of the time you will connect the arduino to a master via serial
   using a MAX485 or similar.
 
   In a function 3 request the master will attempt to read from your
   slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES
   and two BYTES CRC the master can only request 58 bytes or 29 registers.
 
   In a function 16 request the master will attempt to write to your
   slave and since a 9 bytes is already used for ID, FUNCTION, ADDRESS,
   NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write
   54 bytes or 27 registers.
 
   Using a USB to Serial converter the maximum bytes you can send is
   limited to its internal buffer which differs between manufactures.
*/

#define  LED 13 

// Using the enum instruction allows for an easy method for adding and
// removing registers. Doing it this way saves you #defining the size
// of your slaves register array each time you want to add more registers
// and at a glimpse informs you of your slaves register layout.

//////////////// registers of your slave ///////////////////
enum
{     
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  ADC_VAL,     
  PWM_VAL,       
  HOLDING_REGS_SIZE // leave this one
  // total number of registers for function 3 and 16 share the same register array
  // i.e. the same address space
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array
unsigned int check;
////////////////////////////////////////////////////////////

void setup()
{
  /* parameters(HardwareSerial* SerialPort,
                long baudrate,
                unsigned char ID,
                unsigned char transmit enable pin,
                unsigned int holding registers size,
                unsigned int* holding register array)
  */
// set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  modbus_configure(&Serial, 9600, 1, 2, HOLDING_REGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(9600, 1);
 
  pinMode(LED, OUTPUT);
}

void loop()
{
  // modbus_update() is the only method used in loop(). It returns the total error
  // count since the slave started. You don't have to use it but it's useful
  // for fault finding by the modbus master.
  digitalWrite(13, HIGH);
  modbus_update();
 
  holdingRegs[ADC_VAL] = analogRead(A0); // update data to be read by the master to adjust the PWM
 
  analogWrite(LED, holdingRegs[PWM_VAL]>>2); // constrain adc value from the arduino master to 255
  check=holdingRegs[PWM_VAL];
  lcd.clear();
  lcd.write(check);
  delay(30);
 
   digitalWrite(13, LOW);
  /* Note:
     The use of the enum instruction is not needed. You could set a maximum allowable
     size for holdinRegs[] by defining HOLDING_REGS_SIZE using a constant and then access
     holdingRegs[] by "Index" addressing.
     I.e.
     holdingRegs[0] = analogRead(A0);
     analogWrite(LED, holdingRegs[1]/4);
  */
 
}

My lcd is showing 0.
and no message is getting send back to master!
So I am not understanding where is fault exactly!
I am in real need of help on this please some one suggest me something on it I am stucked and dont no what to do!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: monk_duck1 on Nov 04, 2015, 12:56 pm
Hello again.

I checked SimpleModbusMasterManual.pdf from here juanB libraries (https://drive.google.com/folderview?id=0B0B286tJkafVYnBhNGo4N3poQ2c&usp=drive_web&tid=0B0B286tJkafVSENVcU1RQVBfSzg). JuanB explains there how to do hardware connection for arduino slave.
After I did this connection, I can't download my code anymore to arduino.

arduino says:
Code: [Select]
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x01
avrdude: stk500_recv(): programmer is not responding


Code I'm downloading:
Code: [Select]
#include <SimpleModbusSlave.h>

/*
   SimpleModbusSlaveV10 supports function 3, 6 & 16.
   
   This example code will receive the adc ch0 value from the arduino master.
   It will then use this value to adjust the brightness of the led on pin 9.
   The value received from the master will be stored in address 1 in its own
   address space namely holdingRegs[].
   
   In addition to this the slaves own adc ch0 value will be stored in
   address 0 in its own address space holdingRegs[] for the master to
   be read. The master will use this value to alter the brightness of its
   own led connected to pin 9.
   
   The modbus_update() method updates the holdingRegs register array and checks
   communication.

   Note: 
   The Arduino serial ring buffer is 64 bytes or 32 registers.
   Most of the time you will connect the arduino to a master via serial
   using a MAX485 or similar.
 
   In a function 3 request the master will attempt to read from your
   slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES
   and two BYTES CRC the master can only request 58 bytes or 29 registers.
 
   In a function 16 request the master will attempt to write to your
   slave and since a 9 bytes is already used for ID, FUNCTION, ADDRESS,
   NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write
   54 bytes or 27 registers.
 
   Using a USB to Serial converter the maximum bytes you can send is
   limited to its internal buffer which differs between manufactures.
*/

#define  LED 9 

// Using the enum instruction allows for an easy method for adding and
// removing registers. Doing it this way saves you #defining the size
// of your slaves register array each time you want to add more registers
// and at a glimpse informs you of your slaves register layout.

//////////////// registers of your slave ///////////////////
enum
{     
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  ADC_VAL,     
  PWM_VAL,       
  HOLDING_REGS_SIZE // leave this one
  // total number of registers for function 3 and 16 share the same register array
  // i.e. the same address space
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array
////////////////////////////////////////////////////////////

void setup()
{
  /* parameters(HardwareSerial* SerialPort,
                long baudrate,
unsigned char byteFormat,
                unsigned char ID,
                unsigned char transmit enable pin,
                unsigned int holding registers size,
                unsigned int* holding register array)
  */
 
  /* Valid modbus byte formats are:
     SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
     SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
     SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
     
     You can obviously use SERIAL_8N1 but this does not adhere to the
     Modbus specifications. That said, I have tested the SERIAL_8N1 option
     on various commercial masters and slaves that were suppose to adhere
     to this specification and was always able to communicate... Go figure.
     
     These byte formats are already defined in the Arduino global name space.
  */

  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, byteFormat, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(9600, SERIAL_8N2, 1);
 
  pinMode(LED, OUTPUT);
}

void loop()
{
  // modbus_update() is the only method used in loop(). It returns the total error
  // count since the slave started. You don't have to use it but it's useful
  // for fault finding by the modbus master.
 
  modbus_update();
 
  holdingRegs[ADC_VAL] = analogRead(A0); // update data to be read by the master to adjust the PWM
 
  analogWrite(LED, holdingRegs[PWM_VAL]>>2); // constrain adc value from the arduino master to 255
 
  /* Note:
     The use of the enum instruction is not needed. You could set a maximum allowable
     size for holdinRegs[] by defining HOLDING_REGS_SIZE using a constant and then access
     holdingRegs[] by "Index" addressing.
     I.e.
     holdingRegs[0] = analogRead(A0);
     analogWrite(LED, holdingRegs[1]/4);
  */
 
}

So if someone could check my hardware connection and tell, if they find anything problematic, please respond.. As far as I understand, capasitors are only for stabilazing the voltage level, so I didn't add those yet.

EDIT: Thanks yatin.  So I disconnect all the wiring, and the arduino program downloaded ok. Then I wired it back again, one wire at the time. Problem seems to be the wire between arduino pin RX0 and AMD485 R0. When it is connected, program won't be downloaded to arduino. Any ideas how to solve this? Any other than downloading without wires?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Nov 04, 2015, 01:01 pm
Monk it happens some time just make sure any serial simulator or other software is not running.
Also try again with restarting your computer still if it is showing same then takeout your serial pin connection and then upload code!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Nov 04, 2015, 07:35 pm
Guys I am in Real need please can some one help me on my issue?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: mazc on Nov 06, 2015, 04:56 am
I'm trying to use the same library and code for read some registers from a power meter PM9C by schneider electric, but i get many error mesages, could somebody help me?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Nov 06, 2015, 05:07 am
Hello Mazc,
Can u please post your code with photo or errors you are getting so we can help you out properly!
Regards
Yatin
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: mazc on Nov 06, 2015, 06:58 am
Well, i was trying to use the library <ModbusRtu.h>

Code: [Select]


#include <ModbusRtu.h>

uint16_t au16data[16]; //!< data array for modbus network sharing
uint8_t u8state; //!< machine state
uint8_t u8query; //!< pointer to message query
/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  u8serno : serial port (use 0 for Serial)
 *  u8txenpin : 0 for RS-232 and USB-FTDI
 *               or any pin number > 1 for RS-485
 */
Modbus master(0,0,2);


modbus_t telegram[2];

unsigned long u32wait;

void setup() {
  // telegram 0: read registers
  telegram[0].u8id = 1; // slave address
  telegram[0].u8fct = 3; // function code (this one is registers read)
  telegram[0].u16RegAdd = 1020; // start address in slave
  telegram[0].u16CoilsNo = 1; // number of elements (coils or registers) to read
  telegram[0].au16reg = au16data; // pointer to a memory array in the Arduino
 
  master.begin( 9600 ); // baud-rate at 19200
  master.setTimeOut( 5000 ); // if there is no answer in 5000 ms, roll over
  u32wait = millis() + 1000;
  u8state = u8query = 0;
}

void loop() {
  switch( u8state ) {
  case 0:
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1:
    master.query( telegram[u8query] ); // send query (only once)
    u8state++;
  u8query++;
  if (u8query > 2) u8query = 0;
    break;
  case 2:
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 1000;
    }
    break;
  }

  Serial1.println(au16data[16],DEC);

}


but i was only getting some strange symbols in the serial monitor with or withouth the slave device connected, then i decide to use the same library than you, because this is the biggest post with a lot of information that i have found, but I'm getting this errors:

Arduino: 1.6.6 Hourly Build 2015/11/03 04:46 (Windows 7), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

elmasbueno:16: error: 'packetPointer' does not name a type

 packetPointer packet1 = &packets[PACKET1];

 ^

C:\Users\Casa\Documents\Arduino\elmasbueno\elmasbueno.ino: In function 'void setup()':

elmasbueno:22: error: 'packet1' was not declared in this scope

   modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 1008, 1, readRegs);

                    ^

elmasbueno:24: error: too few arguments to function 'void modbus_configure(HardwareSerial*, long int, unsigned char, long int, long int, unsigned char, unsigned char, Packet*, unsigned int, unsigned int*)'

   modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);

                                                                                                                       ^

In file included from C:\Users\Casa\Documents\Arduino\elmasbueno\elmasbueno.ino:1:0:

C:\Users\Casa\Documents\Arduino\libraries\SimpleModbusMasterV2rev2/SimpleModbusMaster.h:134:6: note: declared here

 void modbus_configure(HardwareSerial* SerialPort,

      ^

C:\Users\Casa\Documents\Arduino\elmasbueno\elmasbueno.ino: In function 'void loop()':

elmasbueno:33: error: 'writeRegs' was not declared in this scope

   writeRegs[0] = analogRead(A0); // update data to be written to arduino slave

   ^

exit status 1
'packetPointer' does not name a type

  This report would have more information with
  "Show verbose output during compilation"
  enabled in File > Preferences.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Nov 06, 2015, 07:07 am
I never face such errors in my trials with arduino UNO. I just curious that did you add the library in your sketch to the library location?
It can cause so many errors while compiling
So double check librariy is properly added or not
Regards
Yatin
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: mazc on Nov 06, 2015, 07:09 am
And do you have experience with the <ModbusRtu.h>??
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Nov 06, 2015, 07:22 am
Yes I did implemented simple slave and master in the example of that library on UNO successfully.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: mazc on Nov 06, 2015, 07:25 am
Can you help me? I'm trying to read 3 holding registers, i have the adress of each one, but I'm only reading trash, strange symbols, do you have an idea of what's wrong?

I'm new in this topic, i have no idea what i have to do.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Nov 06, 2015, 07:41 am
Mazc,
I am also new in this topic, But I studied SimpleModbusSlave_DUE.h and SimpleModbusSlave_DUE.h so I can help you with that!
But I dont realy studied modbusrtu thorughly I just tried to run its availble examples to check is my hardware runing properly or not!
If you want to implement with modbusrtu, I need to study it, so I can reply you in day or two!
Mean while you can try with my libraries!
Regards
Yatin
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: robert71 on Nov 06, 2015, 02:21 pm
Hi, does anyone tried to have both Master&Slave togheter on one board eg Mega? This is not typical solution but in my case its needed. Seems that both libraries cannot compile togheter.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 06, 2015, 11:34 pm
Firstly, I see a lot has happened in the past weeks, I have been too busy with other projects to be here :)

Yatin, I sent you a PM reply in regards to Modbus.
Please make sure if you are using Arduino AVR based boards to only use AVR libraries.
The SimpleModbusSlave_DUE and SimpleModbusSlave_DUE libraries are specifically for the DUE.
Yatin, with all the posts, I am unclear what issues you are currently facing.

Robert, there should be no problem in using a setup such that you have Modbus master and Modbus slave operating on a board such as a Mega. You will of course need to assign different serial ports to them.

There are a few combinations, you can in fact even have a TCP slave and serial master setup.
The important thing is that your code is constructed in a way that allows the functionality to run smoothly.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 07, 2015, 04:01 am
mazc, referring to your post 458, you have a mess, a real mess!

Firstly, this tread is not about the library called 'ModbusRtu', it is about the libraries named SimpleModbus, a totally different library.

Next, even with the code posted at that post, the error messages can not come from that code, as there is a reference to SimpleModbus in your error, but you don't make any reference to SimpleModbus in your code. How can this be ?

Again, the error message you get, 'packetPointer packet1 = &packets[PACKET1]' simply can not occur given the code you present, there is no packetPointer reference anywhere.

Then, I can only assume you are using a Mega, correct ?
You do a Serial.print1 in the main loop to print data to your serial monitor on the computer, correct ?
But you never instantiate the Serial1 hardware port in your setup, you need to initiate it with Serial1.begin(some baud rate).

My suggestion, is decide on the library you wish to use, I would suggest SimpleModbus and read the documentation carefully.

The SimpleModbus library suit is proven well enough in my opinion and you should be able to have something up and working in a matter of a few hours to your power meter.

To get your degree, you need to learn how to learn and to be able to show something for your efforts, rather than relying wholly on the efforts of others.

There is more than enough information in this long thread for you to know everything you need for your university project.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: robert71 on Nov 07, 2015, 04:07 pm
Hi Paul, thanks for answer. Just tried to compile and got following errors:

>>>>
In file included from mega.ino:4:0:
C:\Users\plroszc\Documents\Arduino\libraries\SimpleModbusMasterV2rev2/SimpleModbusMaster.h:125:20: error: new declaration 'void modbus_update()'
 void modbus_update();
                    ^
In file included from mega.ino:3:0:
C:\Users\plroszc\Documents\Arduino\libraries\SimpleModbusSlave/SimpleModbusSlave.h:56:14: error: ambiguates old declaration 'unsigned int modbus_update()'
 unsigned int modbus_update();
              ^
Error compiling.
<<<<

seems that libraries dont want to work togheter.

Robert
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Tallguy3412 on Nov 07, 2015, 05:31 pm
Hello,

Is somebody has experience a lot of slaves using this  Master/Slave Simple Modbus libraries ?

I am in a project to have 1 to 50 slaves with 1 master. The controllers for master and slaves are Mega2560 sending/receiving on serial1.

Attached are the schematics that I have used and my sketches for master and slaves.

My problem is that I did my tests with breadboards with 1 master and 4 slaves and everything goes correct. I ordered some PCB to mount my hardware. If I go more than 5 slaves, the communication stop. I read about the bias resistors and tried to remove them with bad result. I increase the bias resistors at 1Kohms and I am able to add 1 more slave that bring me to 6 slaves. It is far from the 50 slaves that I need.

I am suppose to do my production now at this time it is 40 slaves that I need. If I do not find the solution by Monday, I will lost this project.

It is a project that I begin in February to help a friend that need this kind of system and decide to go with Arduino and find this forum that help me a lot. This is my first micro-controller and C programming experience, I am more in the PLC (Ladder) and HMI programming. This is the first time that I post for help.

Each slaves I can enter a unique ID on the touchscreen and save it to EEPROM. On the Master I enter and save the number of slaves to scan.

I receive 1 register from each slave and the master send 1 register to each slave to keep the communication as fast as possible.

I have tried to lower the baud rate to 9600  and change the polling time to 500 milliseconds with no effect.

The communication chips that I use is the SN65HVD3082E that are 1/8 unit load suppose in theory to go up to 256 slaves.

Now the board is on my desk with 2 feet cables (twisted pair) between modules. And the terminator resistors are at the master and last module only. On the project place, the distance will be 20 feet between slaves. 20 feet X 50 units = 1000 feet that is lower than the 4000 feet limitation of the RS-485.

I have include a function if I lost communication with a slave, I will tried to reconnect each 5 minutes. It is working too if I have up to 6 slaves.

Everything works fine except this slaves limitation to 6.

I do not have a scanner to see the exchange between modules.

I think, I have describe the more important things but feel free to ask me more info.

Thank you for your help. :)

Tallguy3412

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 08, 2015, 02:16 am
Robert, I had a look and you are correct, the code for both master and slave both have the same function called 'modbus_update'.

What you could do is rename this function in one of the libraries, for example the library for master, say to 'modbus_master_update'. You will need to change it in the header file as well as the actual library code.

Then in your code, in the loop(), have both modbus_update() and modbus_master_update() function calls.

The other option is to use another library that doesn't for either master or slave that doesn't have a function called 'modbus_update'

I have been working with another library 'libmodbus' which allows all this functionality to co-exist and hence my confusion. I use 'libmodbus' for my GNU/Linux programming to talk to Arduino modbus boards.

Tallguy, bonjour, I have looked at your code quickly and understand your desperation to find a solution. Sorry to hear you have such a short time frame to make this work.

Some things to try:
In your master code:
Code: [Select]
    for (int a = 1; a < NombrePorte+1; a++) // Part la communication en lecture avec le nombre de porte sélectionné
    {
      modbus_construct(&packets[a], a, READ_HOLDING_REGISTERS, 0, 1, a);
    }

    for (int b = 1; b < NombrePorte+1; b++) // Part la communication en écriture avec le nombre de porte sélectionné
    {
      modbus_construct(&packets[b+50], b, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
    }

I don't think you have this correct. What you are doing is assigning the serial ports 1, 2 and 3 on your Mega as slave ID's.
The second parameter in the construct is Slave_ID, not serial port number, which is what you appear to be doing.

Try to do the constructs manually, like you have above this code, at least to prove you can talk to 10 or so slaves in the first instance.

Next, you have a few lines down from above at line 387 the following:
Code: [Select]
  modbus_configure(&Serial1, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);Where ' TOTAL_NO_OF_PACKETS' is going to equal the last count in the enumeration, being 101, as you start at PACKET0 and go to PACKET100.

You don't actually have 100 or 101 packet constructs setup and so it is highly possible that when the master tries to poll for all these packets that undefined behaviour will occur.

If you only have 6 packet constructs, then set the  TOTAL_NO_OF_PACKETS to 6.


In you slave code at line 207 you have:
Code: [Select]
modbus_update_comms(baud, SERIAL_8N2, PorteID);You don't need this as it was already setup in the previous line. Such a statement is used only if you wish to change parameters during runtime.

Hope some of what I say makes sense and can provide you with some assistance.
Santé
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 08, 2015, 03:06 am
Tallguy,

Additionally, in your master code you have:
Code: [Select]
#define polling 2This is too short, set this to something greater than 500 to start with, say 1000.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Nov 08, 2015, 05:07 am
Hey Guys,
I got my solution!
With me the problem was I was trying to burn code using USB to arduino and I was also using a usb to serial with max 485 for RS 485 communication. Now when I try to communicate with slave in my hardware I unintentionally have both connection that is RS232 by usb and RS45 by USB to serial! so when i communicate generally to test serial checkup there was no direction pin enable causing the stop of communication by rs485 and gives output by communicating using RS232.
But as soon as I try to implement this code which has direction pin enable due to my both rs232 and rs485 style connection on same pins I got conflicts at pins causing problem and so my controller was not giving any response.
As soon as I remove the direct USb (RS232) cable and try to implement it starts running smoothly!
It was really silly mistake and I shouldn't suppose to do that!
Sorry guys, for asking such irritating questions and thanks for your support!
Yatin
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Tallguy3412 on Nov 08, 2015, 06:53 am
Hi Paul,

I think you're right, but I do not know why.

First, I have tried to lower the scan rate from 2 msec to 1000 msec and same thing happen.

I do not know why my program works fine from 1 to 6 slaves if I address port instead of slaveID.

I have found a USB to RS485 converter, with the Multiway V8.4 program, I have look what I receive from the RS485. I see that something happen after slave 3  (see attached file) that make sense with what you said.

What will be the best way to initiate the Modbus construct from the variation of the door that I have (from 1 to 50). Without having a separate program for each project.

In a few hour I will test to initialise each packet manually like you suggest me but now I have to go to sleep. It is almost 1 o'clock in Québec.

Thank you Paul, you point me on the right path.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: robert71 on Nov 08, 2015, 12:48 pm
Hi Paul, thanks. I will try to look and check your suggestions next days.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 08, 2015, 01:35 pm
Yatin, you say:
Quote
With me the problem was I was trying to burn code using USB to arduino and I was also using a usb to serial with max 485 for RS 485 communication. Now when I try to communicate with slave in my hardware I unintentionally have both connection that is RS232 by usb and RS45 by USB to serial! so when i communicate generally to test serial checkup there was no direction pin enable causing the stop of communication by rs485 and gives output by communicating using RS232.
I am trying to make sense of what you say.
Are you saying that you have an RS-485 shield or interface connected while you are also connected via USB to your computer ?
And that you are programming the Arduino while the RS-485 interface is connected ?

Quote
It was really silly mistake and I shouldn't suppose to do that!
It seems like you were trying to use the USB on serial0 while also using the same communications port for RS-485 (now EIA-485 or TIA-485).

Many people seem to forget that many Arduino boards only have one hardware serial port and use it for both the communications to the computer as well as using Modbus. This simply does not work.

If you want to have your Arduino board talking Modbus RTU via async serial as well as to your computer then you need separate interfaces.

For separate interfaces you need either to use the softwareSerial library on boards with only a single hardware async serial port or use a board such as a Mega or DUE that has multiple serial async ports.

It seems to be a common problem I see many people fall into and not understand.

Anyhow, Yatin, I'm happy to see that you are learning and making progress, finally  :)
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 08, 2015, 03:57 pm
Tallguy,

I went through your master code and cleaned up the formatting of the indentation so that it is more readable.
Also, corrected many conditional statements to be more explicit with use of parenthesis where needed.

Also, the following changes to the packet constructs, as follows:
Code: [Select]
uint8_t data_size = 1;  // size of packet data in bytes:

// construct packets pour slaves:
  for (uint8_t slave_id = 0; slave_id < TOTAL_NO_OF_PACKETS; slave_id++)
    modbus_construct(&packets[PACKET0 + slave_id], slave_id + 1, READ_HOLDING_REGISTERS, BASE_ADDRESS, data_size, (slave_id * data_size));

  modbus_configure(&Serial1, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);


Where ever I have placed 'XXX' as a comment, you need to address the issue.

Look closely at how I have formatted much of the code in reference to how you have it.
I hope you will find the subtle changes more readable in may places and that it will be more understandable for you.

If you are doing this in the standard Arduino IDE, I will say you will have trouble progressing a complex program quickly as you just will not see all the potential problems.

I use Eclipse IDE and find it far superior to use, in fact I never use the Arduino IDE.
Have a similar background in PLC and SCADA, so I understand where you are coming from :)

Take a look at the following code for the master and see if it helps une peu.
Santé
____
Paul

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Tallguy3412 on Nov 08, 2015, 06:55 pm
Hi Paul,

I have tried all the things that you suggest to me.

baud to 9600
polling to 1000
define the modbus_construct manually for the packet that I use
define the packet size and in the enum for what I use

But all these changes give me the same result at the end.

The 100 msec delays are just in the setup page and when I run the program I do not go there.

Thank you for the program modif but when I compile this program, it give me a lot of errors and I have not enough time now to debug. I will do when I will have more time.

I am thinking now that it is possible that my hardwire have something missing.

See this test:

I write to my master to communicate only with the slave #1

     I add more slaves on the bus without communicating with them.
     When I add slave #7, the communication with slave #1, stop working.

It is like the bus is overloaded. I saw on internet that sometime there is a 10 Kohms resistor between RE/DE and 5 VDC and sometime it is connect to the 0VDC. But I think the chip that I use take care off the failsafe.

I have tried to change some SN65HVD3082E to the MAXIM 3088E but same result. With these chips I am suppose to be able to have 256 slaves (in theory) on the bus.

If I put the 510 pull up and pull down bias resistors, I am limited to 5 slaves and If I put bias resistors of 1Kohms, I can go up to 6 slaves. I have tried others bias resistors values without better result.

I already have attached the schematic with my first post.

Is somebody has tried to communicate with more than 6 slaves ? And what is your connection diagram.

Regards,

Tallguy

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Tallguy3412 on Nov 08, 2015, 08:11 pm
Hi,

I have tried to remove the master from the equation.

I have my USB to RS485 converter on my PC with a software as master.

It is not anymore the simplemaster program that is use.

With the PC polling, I can put 6 slaves without problem. When I put 7 or 8 slaves on the bus, then 2 slaves stop communicate. If I put 9 slaves on the bus, then 6 slaves stop communicate. Each slaves has a different ID number.

I really think, I have a bus loading problem.

Is somebody or Paul has an idea ?

Tallguy
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 08, 2015, 09:49 pm
Tallguy, just to confirm with you the setup of the EIA-485 circuits:

For the master side you have the 510Ω bias resistors in circuit ?
For slaves, there are no 510Ω bias resistors ?

What is the power supply concept you are using that powers the EIA-485 line drivers ?

When you use the computer as master node, are you still using the same EIA-485 driver or do you use another circuit, such as USB to EIA-485 ?

If you do use a different EIA-485 driver for master for the computer, then it would seem to me that the issue is with the slave side.

Other things to check and try:
Check absolutely circuit wiring and connections on EIA-485 side.
Check that each slave board you are using does function individually to make sure you have greater that 6 working slave interfaces.
Check voltage levels at each slave interface.
Check voltage across A and B lines and compare to when you add additional slaves onto the network.
Confirm each slave Arduino also functions as a separate unit, making sure none incorrectly set the Tx_enable_Pin high, thus stopping the network, this is very important.
Note down all conditions as you find them to help diagnose the situation.

Prendre le petit déjeuner
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 08, 2015, 09:55 pm
Additionally:
Set baud rate on each slave to a very low speed, even 2400.
Set baud rate on your program acting as modbus master on your computer to same.

What is the cable length between each slave, in metric ?

It might be possible you have a faulty EIA-485 interface for one of your slave Arduinos ?
Is the EAI-485 interface an Arduino shield mounted board or separate board that is wired to the Arduino ?
If separate, double check the wiring of the Tx_Enable_Pin line to each EAI-485 board.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 08, 2015, 11:59 pm
Tallguy, you say
Quote
Thank you for the program modif but when I compile this program, it give me a lot of errors and I have not enough time now to debug. I will do when I will have more time.
When I comment out all your code that is specific to the graphics screen, as I don't have those graphics libraries, it compiles 100% for me, so any error is in that part of your code.

Any progress with diagnosis ?
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Tallguy3412 on Nov 09, 2015, 12:13 am
Hi Paul,

I confirm with you that the bias resistors of 510 Ohms are at the master side only, when I use my arduino master. None of the slaves have these bias resistors.

To power the line driver IC, I use the 5 VDC of the Arduino. I have check all the voltage between pins 5 and 8 on every line driver and it is vary from 4.99 to 5.02 VDC.

The power section come from a 24 VDC, 20 amps external power supply. On my PCB I have added a DC to DC power supply to lower the voltage from 24 VDC to an average of 7.2 VDC.  I have tried to higher this voltage up to 8 VDC but this does not help.

The system consist of a PCB board that I have develop consisting of 6 inputs, 6 outputs, a 3.2 inches touchscreen, a RTC and the communication. The inputs are opto-isolated. The RTC is not implemented yet. I have nothing connected to the inputs/outputs for debugging.

For testing, I have removed this afternoon the touchscreen.

I have tried to add a pull up resistor of 10 Kohms for the RE/DE and after I have tried a pull down.

I just tried to a lower baud rate of 2400 Bds.

The separated converter that I use is a molded commercial converter, I will be surprise that it will be the same line driver that I use.

The cable length is 0.604 mm between each node. They are cat 5e cables. I use the pin 4 and 5 of the cable that is a twisted pair.

I have tried with a longer cable, 5 meters and the result give me the same thing.

I have a led on the Tx_Enable_Pin and it is only light up on the slave that I question.

Every thing works perfect except this communication problem.

My last test......... I have compared the voltage between the A and B line when it is power and the communications cables disconnected. I was surprise that all the SN65HVD3082E except 1, have 3.9 Volts. The two MAXIM 3088E and the last SN65HVD3082E have only 3.5 millivolts. I just have 5 MAXIM 3088E in total available. I have probably 200x SN65HVD3082E in stock. I will tried to find some that are at 3.5 millivolts.

I will look in that way, thank you Paul for the support that you give me. I will let's you know the results. I do not have a lot of time to do that because the line driver are solder on the board.

Regards,

Tallguy

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 09, 2015, 12:49 am
Good with all the test results and feedback.

Datasheet for http://www.ti.com/lit/ds/symlink/sn75hvd3082e.pdf (http://www.ti.com/lit/ds/symlink/sn75hvd3082e.pdf)
Go to section 9, in particular section 9.2.2 Detailed Design Procedure

Read the section about typical application and how to wire up, it may be that you don't need any extra resistors other than the two end terminators, typically 120Ω each.

Maybe also check that you don't need a ground reference line between the nodes. Normally not, but I have seen systems where you still need the ground reference.

The chip has internal biasing resistors I note.
I would use SN65HVD3082E for all boards.

See if you can determine why some are only at 3.5mVolts.
You need them to be consistently all the same.

Quote
thank you Paul for the support that you give me
You are welcome :)

I'll be about today except for a few hours where I need to check on an off grid solar / LifeYPo4 system installation. Anyhow, must be a change from ladder logic I guess. I'm hopeful a solution will be found in time.
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: monk_duck1 on Nov 11, 2015, 12:17 pm
I'm still pretty lost.. I can't make any data to move between my master (plc) and slave (arduino nano). Connection is same as in the picture before.

So.. I load following code to arduino.
Code: [Select]
#include <SimpleModbusSlave.h>

#define  LED 13 //Arduino's own led

//////////////// registers of your slave ///////////////////
enum
{     
  PWM_VAL,       
  HOLDING_REGS_SIZE // leave this one
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array
////////////////////////////////////////////////////////////

void setup()
{

  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, byteFormat, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(9600, SERIAL_8N2, 1);
 
  pinMode(LED, OUTPUT);
}

void loop()
{
 
  modbus_update();
  digitalWrite(LED, holdingRegs[PWM_VAL]>>2); //led on/off, by master
}


Could this code work? I only want master to force this led on/off. And what is point of >>2 in the end of code?

I just want to be sure the problem is not at the arduino part.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 11, 2015, 12:30 pm
monk, your diagram looks fine to me and your code for the Arduino looks to be ok as well.
It might well be that your PLC code is where the problem exists.

Have you been able to confirm the PLC is making a modbus request ?
Have you checked that your PLC is configured to use EIA-485 correctly ?
What sort of PLC is it ?

You can remove this code:
Code: [Select]
modbus_update_comms(9600, SERIAL_8N2, 1);
The point of >> 2 is to shift the data right by 2 places, which is the same as divide by 4.

You would be better if you turned an LED on and off, rather than adjust the brightness.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: monk_duck1 on Nov 11, 2015, 01:21 pm
Thanks Paul!

doesn't this part make the led run only on/off, if PWM_VAL's data type is BIT at master?
Code: [Select]
digitalWrite(LED, holdingRegs[PWM_VAL]>>2); //led on/off, by master

The master is not actually PLC, but HMI panel. It should support modbus rtu.

I'm not very good with the HMI neither..
I have a button at screen, using toggle data for tag led_pin_13.

I am not sure about masters request, because I am not sure about the reference which I should use.

I tried references 00000 and 1:00000 (I think 1 should be arduino slave ID), As function 5.
With 1:00000 HMI says there is comm error, but somehow it should be possible to tell the slave ID I think. With 00000 it does not make errors, but nothing still happens with button.

HMI is correctly configured to RS-485, that is sure, and baud is set to 9600, data bits to 8 and stop bit to 2.

edit: sorry for bad english.. :D I did some changes to this text
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 11, 2015, 01:33 pm
Well the HMI should be addressing 4000 registers, as that is what you have configured in your Arduino.
Code: [Select]
modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);
Read up on the HMI software to understand how it uses HOLDING_REGISTERS that start at address 4000.
Some device may start at 40000.

The slave ID is different from the address.
Consider it like a house, it has an address on a street, but may have many people in it.
So does your Arduino, it has a specific address on the EIA-485 network which you have said is 1.
But, there are occupants at that address, and they can be the individual components that make up the data.

I think you will be close to getting it working :)
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: monk_duck1 on Nov 11, 2015, 02:07 pm
Many thanks!! I do have now some data moving on! I will ask further questions later on, if i'll need more help :)

Problem was that with button (value 0 or 1) nothing happened, but when I used slider (value 0 to 5) it works.

EDIT:
I don't understand still how to set LED on/off as boolean type data. Now I have to set PWM_VAL at the HMI to 5, when I want to set LED on. Any help with that?

For example:
Code: [Select]

if (holdingRegs[PWM_VAL]>>2 == 0) digitalWrite(13, LOW); //led on/off, by master
  if (holdingRegs[PWM_VAL]>>2 != 0) digitalWrite(13, HIGH); //led on/off, by master


As far as I understand, this should set LED at pin 13 ON always, when PWM_VAL is not 0.
But still LED is OFF until PWM_VAL is 4 or higher.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 11, 2015, 09:18 pm
Look at your code to understand it:
Code: [Select]
digitalWrite(LED, holdingRegs[PWM_VAL]>>2)
You are using digitalWrite, not analogWrite, so the output will be off when the value is zero and be turned on for values greater than 4.

If you give a value of 4 or 5 or 100, or anything number greater than 4, the output will be turned on and the LED will be on.

The reason it is greater than 4 is because you have '>> 2' in there, which is the same as divide by 4.
Learn from the reference: Bit Shifting (https://www.arduino.cc/en/Reference/Bitshift)

The code looks as if it was originally analogWrite to write a PWM value to the output.
If you just want it operated such that a zero turns the LED off and anything greater than zero turns the LED on, then you need to change your code:
Code: [Select]
digitalWrite(LED, holdingRegs[PWM_VAL])
If you want to adjust the LED brightness then use:
Code: [Select]
analogWrite(LED, holdingRegs[PWM_VAL]>>2)
Where the value from the PLC can be 0 to 1023 to give a value of 0 to 256.
If you wish, you can have:
Code: [Select]
analogWrite(LED, holdingRegs[PWM_VAL])
And have the PLC send a value of 0 to 256.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: mazc on Nov 12, 2015, 03:37 am
Hello modbus knights, i'm trying to connect a Merlin Gerin PM9C Power Meter by Schneider Electric with an arduino UNO, i want t oread active and reactive energy, this is the datasheet:

http://www.engineering.schneider-electric.dk/Attachments/ed/instal/PM9_instruction1.pdf

Well I'm using SimpleModbusmaster, this is my code and picture of my results and connections. When it starts to work it only receive strange symbols and first a 0, after that all the values become 0, I made the test of the request, request success and request failed counters, but it show me all the request failed, the baudrate it's ok, the power meter is working at 9600. I cant understand why I'm getting this. :o

this is the code

Code: [Select]


#include <SimpleModbusMaster.h>
#include <SoftwareSerial.h>

#define baud 9600
#define timeout 500
#define polling 200
#define retry_count 50
#define TxEnablePin 2
#define LED 13

enum{
  PACKET1,
  TOTAL_NO_OF_PACKETS};

Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];

unsigned int readRegs[3];
SoftwareSerial mySerial(10,11);
void setup()
{
  while(!Serial){}
  mySerial.begin(9600);
 
  modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 1039, 1, readRegs);
  modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS); 
  pinMode(LED, OUTPUT);}

void loop(){
  modbus_update(); 
if (mySerial.available()){
  Serial.write(mySerial.read());
  Serial.println(mySerial.read(), DEC);}
  analogWrite(LED, readRegs[0]>>2); }


Did someone saw a similar situation? :(
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 12, 2015, 03:45 am
mazc,
You are not using the protocol correctly at all.

You can not use serial commands on the serial channel that is used by the modbus library, not at all.
Look at all the examples, especially in this thread, do any of them have any sort of code like you do, no, of course not.

Go read and study carefully the documentation for SimpleModbusMaster please.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: mazc on Nov 13, 2015, 05:00 am
That going to help me a lot, thank you so much :D
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: monk_duck1 on Nov 13, 2015, 08:31 am
Thank you Paul! You are super. I didn't think about that at all :)

One more question:

So my first reference is 40000.
It would make sense that next in the line would be 40001, and after that 40002 and so on.

Mine works now:
first; 40000
second; 40002
third; 40003
fourth; I don't know.. It's not 40001, 40004, 40005 or 40006.

So why it is like that?

This is my arduino code:
Code: [Select]

#include <SimpleModbusSlave.h>

//////////////// registers of your slave ///////////////////
enum
{    
  PIN_D12,//Digital IN/OUT
  PIN_D13,//Digital IN/OUT
  PIN_D2,//Digital IN/OUT
  PIN_D4,//Digital IN/OUT
  HOLDING_REGS_SIZE // leave this one
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array

////////////////////////////////////////////////////////////

void setup()
{
 
  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, byteFormat, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(9600, SERIAL_8N2, 1);
  
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(4, OUTPUT);
}

void loop()
{
  modbus_update();
  digitalWrite(12, holdingRegs[PIN_D12]);
  digitalWrite(13, holdingRegs[PIN_D13]);
  digitalWrite(2, holdingRegs[PIN_D2]);
  digitalWrite(4, holdingRegs[PIN_D4]);
}


Pins 12 works with reference 40000, 13 with 40002, 2 with 40003 and 4 doesn't work.
Maybe there is still something with the modbus connection?
I add here screenshot from my modbus settings in the HMI panel.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 14, 2015, 12:00 am
monk, have a think about your use of digital pin 2, see where else it is being used for another function that will cause such a problem as you are noticing to occur.

If all you want to do is send a few digitals, then a far better method is to pack the digitals into a larger data type, such as a unsigned integer, such as uint16_t

The modbus holding registers are already 16 bit unsigned words, that can accommodate 16 discrete digitals.
Why use 4 holding registers that each can hold 16 bits, for a total of 32 bits of data exchange only to hold 4 bits of actual meaningful data, it is not efficient use of the protocol, especially if you are exchanging larger amounts of data.

Additionally, I recall mentioning to remove the following line, as it is not needed at all.
Code: [Select]
modbus_update_comms(9600, SERIAL_8N2, 1);
Why try to update the communications configuration when on the previous line you set them.
Modbus update is for use in a program when you need to change allowable parameters, not for setting your initial configuration.
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: monk_duck1 on Nov 16, 2015, 10:18 am
Thanks again! I had to think for a while until I find out the problem with pin 2... Sometimes I'm pretty blind.

Well it is working now with multiple references, starting from 40001,40002...and so on.

I don't know how to pack digitals to uint16_t, and unpacking again at the master, that is problem for me also. I'm not sure if that is possible with my HMI.

EDIT:
I noticed that analog input signals don't work correctly with me!

Now I try communication with 2 analog inputs, A1 & A2.

Code: [Select]
#include <SimpleModbusSlave.h>

//////////////// registers of your slave ///////////////////
enum
{     
  PIN_A1,//Analog INPUT
  PIN_A2,//Analog INPUT
  HOLDING_REGS_SIZE // leave this one
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array

////////////////////////////////////////////////////////////

void setup()
{

  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);
}

void loop()
{
  modbus_update();
  holdingRegs[PIN_A1] = analogRead(A1);
  holdingRegs[PIN_A2] = analogRead(A2);
}


A1 reference is here 40001 and A2 is 40002.
There is no errors, but both (A1 and A2)values are same in the HMI. It doesn't matter if in the A2 pin is +3V and pin A1 0V, still both values is shown +3V in the HMI.

If I use instead PWM outputs, lets say D9 with reference 40001 and D10 with 40002, everything is OK..

So.. any ideas?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 16, 2015, 03:25 pm
monk, you mention:
Quote
Well it is working now with multiple references, but for some reason it still skips 40001. Maybe it is used for modbus communication?
No, it is not used for anything in terms of communications protocol overhead. It is there specifically for you to use.

Remember some systems start at 40000 and others at 40001, so you need to know what both ends use so they will match up.

Quote
If I use 40001, there is no errors, but both (A1 and A2)values are same in the HMI. It doesn't matter if in the A2 pin is +3V and pin A1 0V, still both values is shown +3V in the HMI.
Why not make your program send this data out the serial port where you can see it quickly and easily, and where you can better diagnose the location of your problems ?

Knowing the analog data via your serial port will tell you if the problem is either at the Arduino end or the Modbus communications.

As a test, I would suggest you try the following code and organise your HMI to match the data:
Code: [Select]
#include <SimpleModbusSlave.h>

enum
{    
  mb_data_0,
  mb_data_1,
  mb_data_2,
  mb_data_3,
  mb_data_4,
  mb_data_5,
  HOLDING_REGS_SIZE // leave this one
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array


void setup() {
  holdingRegs[mb_data_0] = 123;
  holdingRegs[mb_data_1] = 234;
  holdingRegs[mb_data_2] = 345;
  holdingRegs[mb_data_3] = 456;
  holdingRegs[mb_data_4] = 567;
  holdingRegs[mb_data_5] = 678;
 
  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);
}

void loop() {
  modbus_update();
  delay(10);
}

With this code you will fill 5 modbus holding registers with the values you see above.
Try to get your HMI to read this data correctly from the 5 registers.

If you can do this, then you can do other things like analogs or other data that may be constantly changing from the Arduino.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: monk_duck1 on Nov 17, 2015, 10:41 am
Yeah, I was wrong about references, my first reference is now 40001 and it continues with 40002,40003...
And it works okey.

With your test code, everything is perfectly ok. In HMI all the values are same as in your code.


If I use this code instead, without any changes to HMI:
Code: [Select]

//Everything same here as in your code, only loop is different:
void loop() {
  modbus_update();
    holdingRegs[mb_data_1] = analogRead(A0);
    holdingRegs[mb_data_4] = analogRead(A4);
  delay(10);
}

All other values are correct, but A0 and A4 are same as other. If I set any voltage level to either of those, another jumps to same in HMI.
If I measure it, there is no volts in both pins at same time.

Then again if I use this, no changes to HMI:
Code: [Select]

//Everything same here as in your code, only loop is different:
void loop() {
  modbus_update();
  analogWrite(9, holdingRegs[mb_data_1]>>2);
  analogWrite(10, holdingRegs[mb_data_4]>>2);
  delay(10);
}

Both values A0 and A4 are correctly what I set them to be in HMI, and others are ok also.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 17, 2015, 11:00 am
monk:
Quote
All other values are correct, but A0 and A4 are same as other. If I set any voltage level to either of those, another jumps to same.
I am suspecting you have one analog input connected to a voltage source and the other is left floating, unconnected to anything.

If this is true, then of course this will tend to happen.
It is nothing to do with the Modbus code or protocol at all, simply everything to do with the way you are working with the analog inputs. This is why I mentioned using serial.print() to show your analogs. You will find if you that you will need to have a low impedance source connected to your analog inputs, not leave them floating.

If you have unused analog inputs, then tie them low to 0Vdc via a 4k7Ω resistor.

Anyhow, good to see you are making progress.

Mostly, it comes down to the methodology of your diagnostic methods :)
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: monk_duck1 on Nov 17, 2015, 11:53 am
Ahh.. I'm sorry to bother you with stupid questions. Thanks, everything works now.

EDIT: yes, so the analog pins were floating, and that affected analog values to look like to jump same level at once when I changed only one of them.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 17, 2015, 12:00 pm
Monk, no, not stupid questions at all :)

Better to say what you found so it can help others.
Were my assumptions correct with a floating analog ?

Happy that you have the program working.
Play with it and experiment to learn more :)
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: EdgardoU on Nov 18, 2015, 08:09 am
Hi JuanB and to all!

I'm going to use your master JuanB and my question is what Arduino do you recomend to use with your lib. I dont have any Arduino kit so I have to buy one.
I need a modbus master to read a flow meter based on coriolis and it is a modbus slave.

Thank you JuanB and to all for the help

Regards from Buenos Aires, Argentina

Edgardo
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Nov 18, 2015, 08:16 am
Welcome to the forum Edgardo.
The SimpleModbus library suit will work fine with any AVR based Arduino.
I don't recall I have tried it with the SAM based DUE as yet.

What Arduino do you have in mind ?

Juan doesn't seem to visit the thread very often these days.

____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: EdgardoU on Nov 18, 2015, 09:20 am
Hi rockwallaby!

Thank you for the welcome!

I don't have any Arduino yet, but since the libs are for Arduino I don't know what arduino is the correct one for this modbus libs. I do use psoc 5lp and psoc 4 a lot but nothing with arduino so I have to buy one for this modbus lib.

Thank you again for the great welcome!

Edgardo
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: soundmanu on Nov 26, 2015, 07:54 pm
Hi,

this is my first Post. Hello to Everybody!
 
I hope somebody would help me with that SimpleModbusMaster.

I own a Probe Sensor to control the waterlevel of my (very (very) big) aquariums. Until now, I worked with the 4-20mA Scale from the sensor with my Arduino and a Adafruit 16bitADC. It works very well. But the sensor also could give me the 'BAR'-Values directly with RS485 Modbus RTU Protocol.... without calibrating....

Here is the Modbus Communication Protokoll of my Sensor:
http://www.keller-druck.com/picts/pdf/engl/comm_protocol_e.pdf (http://www.keller-druck.com/picts/pdf/engl/comm_protocol_e.pdf)

I've got the 'RS485 to TTL Modul' on my Arduino MEGA connected on Serial1 (TX1/RX1). Enable PIN 30

I'm new in Arduino and since Days I've tried to get any Response from the Sensor using the actually Library with Demo Code... I'd only changed the start adress and the Registers to read, compare to the Communication Protokoll of my Sensor (hope so :smiley-confuse: )..... How its going on?  I can't use all previus Posts and Examples with my actually SimpleModbusLibrary because it doesn't compile.... The Librays are differnt....

Here is my DemoCode.... only the Example of the Library:
Code: [Select]
#include <SimpleModbusMaster.h>

/*
   The example will use packet1 to read a register from address 0 (the adc ch0 value)
   from the arduino slave (id=1). It will then use this value to adjust the brightness
   of an led on pin 9 using PWM.
   It will then use packet2 to write a register (its own adc ch0 value) to address 1
   on the arduino slave (id=1) adjusting the brightness of an led on pin 9 using PWM.
*/

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 100 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 30

#define LED 13

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 1

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
  Serial.begin(9600);
  // Initialize each packet
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 2, 2, 0);
 // modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
  
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial1, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
  
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
 
  Serial.println( DATA FROM THE SENSOR )) ---- Please Help !!
  //regs[0] = analogRead(0); // update data to be written to arduino slave
  
  //analogWrite(LED, regs[0]>>2); // constrain adc value from the arduino slave to 255
}

How can I get the Data of the Sensor?? Which Variable(s) tranfers the Data? To debug I would like to print the Data in Serial Monitor....
When I print the regs[0-10] it always displayed the same values not compares to the Data I would like to receive... 


Sorry for my bad English!!


Hope for some Help ...
Manu
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: AJITnayak on Nov 27, 2015, 09:53 am
I am using Modbus RTU library from Below link. This library will work on Indivual slave device without any issue.

https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino/blob/master/ModbusRtu.h (https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino/blob/master/ModbusRtu.h)

I have connected the Multiple slave with different device Id set. When I try to communicate with multiple device I.e 4+ more I get Modbus timeout error

Here I have attached complete code in zip file . Can someone suggest me how to sort out the error while connected multiple device.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: martyscorpion on Nov 28, 2015, 10:08 am
I am using Modbus RTU library from Below link. This library will work on Indivual slave device without any issue.

https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino/blob/master/ModbusRtu.h (https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino/blob/master/ModbusRtu.h)

I have connected the Multiple slave with different device Id set. When I try to communicate with multiple device I.e 4+ more I get Modbus timeout error

Here I have attached complete code in zip file . Can someone suggest me how to sort out the error while connected multiple device.
What is your hardware ? Are you using trancievers for multiple nodes. İf you are using a termination resistor just use only end of the line . I manage to communicate 10 devices for now (can be 256 slaves) with MCU Atmega328P and RS485 trancievers and 120Ohm termination resistor.

Now I am trying to connect all with 24v DC powerline .
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: AJITnayak on Nov 29, 2015, 05:24 am
Dear sir,

I have attached schematic for reference. Initially I didn't use terminator resistor. But Later I used Terminator resistor 100ohm .Initially I could able to connect 2 device , later I can connect 4 device. when I connect 5 th device same error occurring.

I am doubting on converter I am using Initially  I used china make where I can communicate 2 devices. when I brought new one I can connect 4 devices.

I heard in polling method there will be loss of data always. when PC send request for 1 device, I found response time from slave device is 800ms . Is it any way in this library I can reduce this time. Other than library I didn't use any delay in the program. How to get response time lower.

It can be done interrupt method. But I am new and I didn't have time to develop and analysis. unless this library function  is working.

Your help will be appreciable.


http://www.ebay.in/itm/like/131659048956?aff_source=Sok-Goog (http://www.ebay.in/itm/like/131659048956?aff_source=Sok-Goog)
with this I can connect only 4 device without any problem . if I connect 5th device , request going but no response from slave.

http://dir.indiamart.com/search.mp?ss=usb+to+rs485+converter

MEW820-A - USB to RS485/422 converter

With this I can communicate only 2 device at time.if I connect 3 device Modbus time out error, some time bad response will come



Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: soundmanu on Dec 03, 2015, 12:33 am
Hi Guys,

I've got good news! I made it!! Again I read this thread carefully, loaded the old SimpleModbusMaster library, and zoooom.... there are my Values hidden in readRegs[1] ...

Thx
Manu

 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Dec 03, 2015, 12:49 am
Good to hear Manu,
Most times, all it needs is time spent reading and studying the documentation and examples carefully.
There is enough proof here in this thread that the library works well.

Experiment and have fun  :)
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: monk_duck1 on Dec 04, 2015, 01:42 pm
Hi again!

One quick question:

does "modbus_update();" command update all the data,
or does "holdingRegs[ADC_VAL] = analogRead(A0);" update the data from ADC_VAL?

I have a situation, where I'll need to update some of the registers only once.

Maybe it works with something like this example below?
Code: [Select]
#include <SimpleModbusSlave.h>

int called_once = 0;

enum
{     
  UPDATE_ONCE,
  ADC_VAL,     
  PWM_VAL,       
  HOLDING_REGS_SIZE
};

unsigned int holdingRegs[HOLDING_REGS_SIZE];

void setup()
{
  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);
}

void loop()
{
  modbus_update();
 
  if (called_once == 0) call_once();
 
  holdingRegs[ADC_VAL] = analogRead(A0);
  analogWrite(LED, holdingRegs[PWM_VAL]>>2);
  }
 
  void call_once()
  {
    holdingRegs[0] = digitalRead(D3); //I need to update this data once to master
    called_once = 1;
  }


I don't want to make any unnecessary loads for my modbus.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: katragaddapurna on Dec 04, 2015, 02:43 pm
Hi Any one can help me
Iam using Arduino MEGA 2560 i connected the L&T meter fot capturing the KWH consumption. Its working fine.
Same program iam using Schneider electric EM1200 meter. But its not working. Pls share any one in Program or EM1200 Holding Registers values for capturing the KWH consumption and Run Hrs data

Pls help me
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Dec 04, 2015, 11:47 pm
Monk,

The code you present, you have a slave, which has no control over the what will be updated in terms of modbus registers, it will be the master that needs to be selective about requesting data from the slave.

The modbus_update() command for the slave simply checks for master requests and replies accordingly, returning any error codes.

You will need to make your master code such that write once only registers will be done at the point in time you need, either at startup or at some specific time.

The process of equating your variables to modbus registers or the other way around has no impact on what gets transferred at either end, master or slave. It is the packet configuration that determines this at the master end.

Check the modbus master documentation for how to do this.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: goms2394 on Dec 06, 2015, 03:31 am
I couldnt find simplemodbus library in that link, can anyone hep me with it plz....
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Dec 06, 2015, 04:46 am
This is link where i got this library so you can access it there!simple modbus RTU library (https://drive.google.com/folderview?id=0B0B286tJkafVSENVcU1RQVBfSzg&usp=drive_web)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: goms2394 on Dec 06, 2015, 06:44 am
Thanks yatin...!!!

Nw I have planned to test SimpleModbusMasterV2rev2  using arduino uno..
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: goms2394 on Dec 06, 2015, 07:46 am
Im trying to communicate with elmeasure and here s d result in attachment

I cant get the output, but meter is showing trans

Plz somebody help...

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Dec 06, 2015, 12:27 pm
I think you forgot to add your attachments, please attach your hardware connections and your code that you are using so some body can help you more.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: goms2394 on Dec 07, 2015, 05:39 pm
Oopss sorry it didnt upload...

here are the details
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Coding Badly on Dec 08, 2015, 01:16 am

Waylaid post merged.

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Dec 08, 2015, 05:47 am
goms2394,
Please use code quote to add code, images that you added with code are not properly visible!
 Please use proper quoting for message!
also add your schematic through which you connected hardware cause it could be a hardware problem too!
Thanks


Yatin
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: zhangjianjun327 on Dec 17, 2015, 10:54 am
Hi,JuanB,
i am new for arduino and MODBUS RTU communication, i use arduino 2560 with a TOUCH SCREEN communication use MODBUS RTU protocol, i use your simple MODBUS libary V12 for the master, the voltage between A line and B line is 320MV, i found the indicate light of MAX485 TX flshing fast but Rx light flashing to slow, the data i got from the TOUCH SCREEN and write to it both not right, i use serial monitor to see it, the data changed wihtin another scan, i do not know why?
 can you help me out ?

thank you very much.

zhangjianjun327   
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Benchem on Dec 17, 2015, 11:56 am
Hi everybody,

I currently tried to use simplemodbusmaster library to communicate with PROCON module PM8TCISO and PM16DO (PROCON modules (http://www.proconel.com/Industrial-Data-Acquisition-Products/PROMUX---I-O-Modules.aspx)).
First I tried successfully with modules using direct communication with Labview, then I would like to use my  M-DUINO as a master (Arduino mega with different shields) http://www.industrialshields.com/m-duino-plc-arduino-34R-i-os-relay_analog-digital (http://www.industrialshields.com/m-duino-plc-arduino-34R-i-os-relay_analog-digital)
I tried to use the A and B pin  (MAX-485 connect to serial 3 of arduino mega).

First, I would like to read holding register in PM8TCISO. ModBus address 30002 to 30009.
The communication of module is 9600,8 bits, no parity, 1 stop bits.
Here below the code that I tried to read the first register 30002. I defined in module slave ID as 32.

Code: [Select]
#include <SimpleModbusMaster.h>

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 300 // the scan rate
#define retry_count 50

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 14

#define LED 9

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 1

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
  // Initialize each packet
  modbus_construct(&packets[PACKET1], 32, READ_HOLDING_REGISTERS, 0, 1, 0);
  
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial3, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
  
  Serial.begin(9600);
  
}

void loop()
{
  modbus_update();
  
  Serial.println(regs[0]);
  Serial.println(packets[PACKET1].requests);

  delay(500);
      
  
}

 
The Rx Led in my proton don't blink which I can attribute to bad modes message sent. I connect A and B pins to my RS485 - UBS converter and I could see Rx led always on.

Could you say me if you find any mistakes in my code or advises?

I use simplemodbusmasterV2.rev2

thank you  a lot

benoit
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Dec 17, 2015, 01:13 pm
Benchem,
Address of holding register starts from 40001, but you need to read 30002, means you don't want to read holding registers but you have to read for input registers.
Quote
modbus_construct(&packets[PACKET1], 32, READ_HOLDING_REGISTERS, 0, 1, 0);
so here you have to make the change as replacing READ_HOLDING_REGISTER by READ_INPUT_REGISTER also you need to change that last 0 to 2 as you want to start from 30002 not from 30000.
Hope that will work!
Yatin
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Benchem on Dec 17, 2015, 02:41 pm
Thanks for your answer.
According to your answer I modified my code but nothing change.

Code: [Select]
#include <SimpleModbusMaster.h>

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 300 // the scan rate
#define retry_count 50

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 14

#define LED 9

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 1

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
  // Initialize each packet
  modbus_construct(&packets[PACKET1], 32, READ_INPUT_REGISTERS, 2, 1, 0);
 
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial3, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
  Serial.begin(9600);
 
}

void loop()
{
  modbus_update();
 
  Serial.println(regs[0]);
  Serial.println(packets[PACKET1].requests);

  delay(500);
       
 
}
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Benchem on Dec 17, 2015, 04:32 pm
When I used Labview to send a message on MobDus to request the previous I send (decimal visualisation) :

32 <-- slave ID
03 <-- fonction code
00 01 <-- register adress
00 01 <-- number of register to request
CRC code

When I read the message send from arduino it something very different :
in hex

00BB FFBB FFFD D322

Thank you

benoit
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Dec 18, 2015, 05:54 am
Benchem,
you need to check whether it is transmitting proper data and how it response to received so make a proteus circuit with lcd and check what data u getting yoc can check the tryal program that i used on my post #452!
20 03 00 01 00 01 D3 7B  this is what master should send for slave id 32 and starting address 30002, function 3 no of reg 1 and D37B is crc! it show some thing different on lcd due to ascii but yes you can try with proteus and if it runs there you can check lcd data over there and in actual at your hardware.
YATIN
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: ChrisR13 on Dec 21, 2015, 04:17 am
Good day to all,

I am using the simple modbus library and have implemented 1 master and 2 slaves with the arduino Mega boards. I am able to read slave registers successfully but when it comes to writing to slave registers I am having problems. My goal is basically for the master to send a packet to slave 2  setting the Pump register to a value for example say 150 and printing it to the screen to prove that it has in fact been changed by the master. My setup code for the master and slave 2 can be seen below. Any help would be greatly appreciated. Thanks.

Master setup code:

enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
  PACKET5,
  PACKET6,
  PACKET7,
  PACKET8,
  PACKET9,
  PACKET10,
  PACKET11,
  PACKET12,
  PACKET13,
  PACKET14,
  PACKET15,
  PACKET16,
  PACKET17,
  TOTAL_NO_OF_PACKETS
};
Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
packetPointer packet2 = &packets[PACKET2];
packetPointer packet3 = &packets[PACKET3];
packetPointer packet4 = &packets[PACKET4];
packetPointer packet5 = &packets[PACKET5];
packetPointer packet6 = &packets[PACKET6];
packetPointer packet7 = &packets[PACKET7];
packetPointer packet8 = &packets[PACKET8];
packetPointer packet9 = &packets[PACKET9];
packetPointer packet10 = &packets[PACKET10];
packetPointer packet11 = &packets[PACKET11];
packetPointer packet12 = &packets[PACKET12];
packetPointer packet13 = &packets[PACKET13];
packetPointer packet14 = &packets[PACKET14];
packetPointer packet15 = &packets[PACKET15];
packetPointer packet16 = &packets[PACKET16];
packetPointer packet17 = &packets[PACKET17];
unsigned int slave1Regs[12];
unsigned int slave2Regs[2];
unsigned int phRegs[5];

void setup()
{
  modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0, 1, slave1Regs);
  modbus_construct(packet2, 1, READ_HOLDING_REGISTERS, 0, 2, slave1Regs);
  modbus_construct(packet3, 1, READ_HOLDING_REGISTERS, 0, 3, slave1Regs);
  modbus_construct(packet4, 1, READ_HOLDING_REGISTERS, 0, 4, slave1Regs);
  modbus_construct(packet5, 1, READ_HOLDING_REGISTERS, 0, 5, slave1Regs);
  modbus_construct(packet6, 1, READ_HOLDING_REGISTERS, 0, 6, slave1Regs);
  modbus_construct(packet7, 1, READ_HOLDING_REGISTERS, 0, 7, slave1Regs);
  modbus_construct(packet8, 1, READ_HOLDING_REGISTERS, 0, 8, slave1Regs);
  modbus_construct(packet9, 1, READ_HOLDING_REGISTERS, 0, 9, slave1Regs);
  modbus_construct(packet10, 1, READ_HOLDING_REGISTERS, 0, 10, slave1Regs);
  modbus_construct(packet11, 1, READ_HOLDING_REGISTERS, 0, 11, slave1Regs);
  modbus_construct(packet12, 1, READ_HOLDING_REGISTERS, 0, 12, slave1Regs);
  modbus_construct(packet13, 2, READ_HOLDING_REGISTERS, 0, 1, slave2Regs);
  modbus_construct(packet14, 2, READ_HOLDING_REGISTERS, 0, 2, slave2Regs);
  modbus_construct(packet15, 2, PRESET_MULTIPLE_REGISTERS, 1, 1, phRegs);
  Serial.begin(9600);
  modbus_configure(&Serial1,baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
pinMode(8, OUTPUT);

}

Slave 2 setup code:

#include <SimpleModbusSlave.h>
#include<stdlib.h>

enum
{     
  T1,
  T7,   
  Pump,         
  SIZE
};

unsigned int SlaveTwo[SIZE];

void setup()
{
  Serial.begin(9600);
  modbus_configure(&Serial1,9600, SERIAL_8N2, 2, 2, SIZE, SlaveTwo);   
 
}

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Dec 21, 2015, 02:18 pm
Welcome to the forum ChrisR13.
A couple of things.
First, please present any code in code tags as is so often asked on this forum.

Secondly, insert the slave code in its own code tags, as I first thought it was the same code and wondered how on Earth you could get such code to compile with two functions called setup().

It is always a good idea to provide all your code, not just a part or a part where you may think the problem is.

You say
Quote
but when it comes to writing to slave registers I am having problems
, but it may not be with the writing, which is at the master end, but rather, at the slave end, of which we can not see all the code.
_____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: ChrisR13 on Dec 21, 2015, 06:11 pm
Hi Paul,
Thanks alot for replying and I apologize this is the first time I am posting on any forum. I hope this post is better. Now that I have posted the entire code, what I want to do is take the value stored in phRegs[0] on the master and write it to the slave 2 register called Pump. I hope you understand and thanks in advance.

Master code

Code: [Select]
#include <SimpleModbusMaster.h>
#include<stdlib.h>
#define baud 9600
#define timeout 1000
#define polling 100
#define retry_count 5
#define TxEnablePin 2
//#define LED 13

enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
  PACKET5,
  PACKET6,
  PACKET7,
  PACKET8,
  PACKET9,
  PACKET10,
  PACKET11,
  PACKET12,
  PACKET13,
  PACKET14,
  PACKET15,
  PACKET16,
  PACKET17,
  TOTAL_NO_OF_PACKETS
};
Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
packetPointer packet2 = &packets[PACKET2];
packetPointer packet3 = &packets[PACKET3];
packetPointer packet4 = &packets[PACKET4];
packetPointer packet5 = &packets[PACKET5];
packetPointer packet6 = &packets[PACKET6];
packetPointer packet7 = &packets[PACKET7];
packetPointer packet8 = &packets[PACKET8];
packetPointer packet9 = &packets[PACKET9];
packetPointer packet10 = &packets[PACKET10];
packetPointer packet11 = &packets[PACKET11];
packetPointer packet12 = &packets[PACKET12];
packetPointer packet13 = &packets[PACKET13];
packetPointer packet14 = &packets[PACKET14];
packetPointer packet15 = &packets[PACKET15];
packetPointer packet16 = &packets[PACKET16];
packetPointer packet17 = &packets[PACKET17];
unsigned int slave1Regs[12];
unsigned int slave2Regs[2];
unsigned int phRegs[5];

void setup()
{
  modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0, 1, slave1Regs);
  modbus_construct(packet2, 1, READ_HOLDING_REGISTERS, 0, 2, slave1Regs);
  modbus_construct(packet3, 1, READ_HOLDING_REGISTERS, 0, 3, slave1Regs);
  modbus_construct(packet4, 1, READ_HOLDING_REGISTERS, 0, 4, slave1Regs);
  modbus_construct(packet5, 1, READ_HOLDING_REGISTERS, 0, 5, slave1Regs);
  modbus_construct(packet6, 1, READ_HOLDING_REGISTERS, 0, 6, slave1Regs);
  modbus_construct(packet7, 1, READ_HOLDING_REGISTERS, 0, 7, slave1Regs);
  modbus_construct(packet8, 1, READ_HOLDING_REGISTERS, 0, 8, slave1Regs);
  modbus_construct(packet9, 1, READ_HOLDING_REGISTERS, 0, 9, slave1Regs);
  modbus_construct(packet10, 1, READ_HOLDING_REGISTERS, 0, 10, slave1Regs);
  modbus_construct(packet11, 1, READ_HOLDING_REGISTERS, 0, 11, slave1Regs);
  modbus_construct(packet12, 1, READ_HOLDING_REGISTERS, 0, 12, slave1Regs);
  modbus_construct(packet13, 2, READ_HOLDING_REGISTERS, 0, 1, slave2Regs);
  modbus_construct(packet14, 2, READ_HOLDING_REGISTERS, 0, 2, slave2Regs);
  modbus_construct(packet15, 2, PRESET_MULTIPLE_REGISTERS, 1, 1, phRegs);
  Serial.begin(9600);
  modbus_configure(&Serial1,baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
pinMode(8, OUTPUT);

}

void loop()
{//analogWrite(8,127);
float pumpData = 0;
float heaterData=0;
float t7SP=0;
float t1SP=0;
float pump = 0;
float heater =0;

if (Serial.available() > 0) {
          if (Serial.peek()=='p'){
            Serial.read();
         
                // read the incoming byte:
                pumpData = Serial.parseFloat();
                phRegs[0] = pumpData;
                pump = ((pumpData/300)*255);
                analogWrite(8, pump);
                // say what you got:
                //Serial.print("I received: ");
                //Serial.println(pumpData);
                }

                if (Serial.peek()=='h'){
            Serial.read();
         
                // read the incoming byte:
                heaterData = Serial.parseFloat();
                phRegs[1]= heaterData;
                heater = ((heaterData/2000)*255);
                analogWrite(9, heater);
                // say what you got:
                //Serial.print("I received: ");
                //Serial.println(heaterData);
                }

                 if (Serial.peek()=='a'){
            Serial.read();
         
                // read the incoming byte:
                t7SP = Serial.parseFloat();
                phRegs[2] = t7SP;
               
                // say what you got:
                //Serial.print("I received: ");
                //Serial.println(t7SP);
                }

                 if (Serial.peek()=='b'){
            Serial.read();
         
                // read the incoming byte:
                t1SP = Serial.parseFloat();
                phRegs[3] = t1SP;
               
                // say what you got:
                //Serial.print("I received: ");
                //Serial.println(t1SP);
                }
               
          while (Serial.available() > 0) {
                Serial.read();
          }
       }

 
  modbus_update();
  char str[10];
  float num = slave2Regs[0];
 float T1;
 T1 = ((num/1024)*150);
 
   modbus_update();
float num1 = slave1Regs[0];
 float T2;
 T2 = ((num1/1024)*150);
 
modbus_update();
    float num2 = slave1Regs[1];
 float T3;
 T3 = ((num2/1024)*150);
 
modbus_update();
    float num3 = slave1Regs[2];
 float T4;
 T4 = ((num3/1024)*150);
 
modbus_update();
    float num4 = slave1Regs[3];
 float T5;
 T5 = ((num4/1024)*150);
 
modbus_update();
    float num5 = slave1Regs[4];
 float T6;
 T6 = ((num5/1024)*150);
 
modbus_update();
    float num6 = slave2Regs[1];
 float T7;
 T7 = ((num6/1024)*150);
 
modbus_update();
    float num7 = slave1Regs[5];
 float T8;
 T8 = ((num7/1024)*150);
 
modbus_update();
    float num8 = slave1Regs[6];
 float T9;
 T9 = ((num8/1024)*150);
 
modbus_update();
    float num9 = slave1Regs[7];
 float T10;
 T10 = ((num9/1024)*150);
 
modbus_update();
    float num10 = slave1Regs[8];
 float T11;
 T11 = ((num10/1024)*150);
 
modbus_update();
    float num11 = slave1Regs[9];
 float T12;
 T12 = ((num11/1024)*150);
 
modbus_update();
float num12 = slave1Regs[10];
 float T13;
 T13 = ((num12/1024)*150);
 
  modbus_update();
    float num13 = slave1Regs[11];
 float T14;
 T14 = ((num13/1024)*150);
 
   modbus_update();
 
 
   
    const unsigned long fiveMinutes =  3 * 1000UL;
 static unsigned long lastSampleTime = 0 - fiveMinutes;  // initialize such that a reading is due the first time through loop()

 unsigned long now = millis();
 if (now - lastSampleTime >= fiveMinutes)
 {
    lastSampleTime += fiveMinutes;
    // add code to take temperature reading here
    //Serial.print ("T1 ");
    Serial.println(dtostrf(T1,4,1,str));
    //Serial.print ("T2 ");
    Serial.println(dtostrf(T2,4,1,str));
    //Serial.print ("T3 ");
    Serial.println(dtostrf(T3,4,1,str));
    //Serial.print ("T4 ");
    Serial.println(dtostrf(T4,4,1,str));
    //Serial.print ("T5 ");
    Serial.println(dtostrf(T5,4,1,str));
    //Serial.print ("T6 ");
    Serial.println(dtostrf(T6,4,1,str));
    //Serial.print ("T7 ");
    Serial.println(dtostrf(T7,4,1,str));
    //Serial.print ("T8 ");
    Serial.println(dtostrf(T8,4,1,str));
    //Serial.print ("T9 ");
    Serial.println(dtostrf(T9,4,1,str));
    //Serial.print ("T10 ");
    Serial.println(dtostrf(T10,4,1,str));
    //Serial.print ("T11 ");
    Serial.println(dtostrf(T11,4,1,str));
    //Serial.print ("T12 ");
    Serial.println(dtostrf(T12,4,1,str));
    //Serial.print ("T13 ");
    Serial.println(dtostrf(T13,4,1,str));
    //Serial.print ("T14 ");
    Serial.println(dtostrf(T14,4,1,str));

   
   
 }
 // add code to do other stuff here
 
}


Slave 2 code:

Code: [Select]
#include <SimpleModbusSlave.h>
#include<stdlib.h>

enum
{     
  T1,
  T7,   
  Pump,         
  SIZE
};

unsigned int SlaveTwo[SIZE];

void setup()
{
  Serial.begin(9600);
  modbus_configure(&Serial1,9600, SERIAL_8N2, 2, 2, SIZE, SlaveTwo);   
 
}

void loop()
{
 
  modbus_update();
 
  SlaveTwo[T1] = analogRead(A0);
  SlaveTwo[T7] = 600;
 

   modbus_update();
   Serial.println(SlaveTwo[T1]);
   Serial.println(SlaveTwo[T7]);
  Serial.println(SlaveTwo[Pump]);
modbus_update();
}
}
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Benchem on Dec 22, 2015, 09:43 am
Hi everybody,

I solved my issue next to a feedback from industrialshields. I had to use a modified simplemodbus library and carefully define my RS485 pins and defined it in modbusconstruct.
Here you can find now if it can help someone my code to read input registers and write single register to my 5 Promux slaves.
Code: [Select]
#include <SimpleModbusMasterSoftwareSerial.h>
#include <SoftwareSerial.h>

#define baud 9600
#define timeout 1000
#define polling 10 // the scan rate
#define retry_count 10


int SSerialRX =11 ;// RO  //RS485 Receive pin
int SSerialTX=10; // DI  //RS485 Transmit pin
int  SSerialTxControl=14;  // DE  //RS485 Direction pin
int GroundRE=15 ; // RE
SoftwareSerial RS485Serial(SSerialRX, SSerialTX);
enum
{
PACKET1,
//PACKET2,
//PACKET3,
//PACKET4,
//PACKET5,
//PACKET6,
//PACKET7,
//PACKET8,
PACKET9,
//PACKET10,
//PACKET11,
//PACKET12,
//PACKET13,
//PACKET14,
//PACKET15,
//PACKET16,
PACKET17,
//PACKET18,
//PACKET19,
//PACKET20,
//PACKET21,
//PACKET22,
//PACKET23,
//PACKET24,
PACKET25,
//PACKET26,
//PACKET27,
//PACKET28,
//PACKET29,
//PACKET30,
//PACKET31,
//PACKET32,
PACKET33,

TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
#define TOTAL_NO_OF_REGISTERS 33
unsigned int regs[TOTAL_NO_OF_REGISTERS];





void setup()
{
  Serial.begin(38400);
  pinMode(SSerialTxControl, OUTPUT); 
  pinMode(GroundRE, OUTPUT);
  digitalWrite(GroundRE,LOW);
  /////module promux TC slave 32
  modbus_construct(&packets[PACKET1], 32, READ_INPUT_REGISTERS, 1, 8, 0);
//  modbus_construct(&packets[PACKET2], 32, READ_INPUT_REGISTERS, 2, 1, 1);
//  modbus_construct(&packets[PACKET3], 32, READ_INPUT_REGISTERS, 3, 1, 2);
//  modbus_construct(&packets[PACKET4], 32, READ_INPUT_REGISTERS, 4, 1, 3);
//  modbus_construct(&packets[PACKET5], 32, READ_INPUT_REGISTERS, 5, 1, 4);
//  modbus_construct(&packets[PACKET6], 32, READ_INPUT_REGISTERS, 6, 1, 5);
//  modbus_construct(&packets[PACKET7], 32, READ_INPUT_REGISTERS, 7, 1, 6);
//  modbus_construct(&packets[PACKET8], 32, READ_INPUT_REGISTERS, 8, 1, 7);
  /////module promux TC slave 33
  modbus_construct(&packets[PACKET9], 33, READ_INPUT_REGISTERS, 1, 8, 8);
//  modbus_construct(&packets[PACKET10], 33, READ_INPUT_REGISTERS, 2, 1, 9);
//  modbus_construct(&packets[PACKET11], 33, READ_INPUT_REGISTERS, 3, 1, 10);
//  modbus_construct(&packets[PACKET12], 33, READ_INPUT_REGISTERS, 4, 1, 11);
//  modbus_construct(&packets[PACKET13], 33, READ_INPUT_REGISTERS, 5, 1, 12);
//  modbus_construct(&packets[PACKET14], 33, READ_INPUT_REGISTERS, 6, 1, 13);
//  modbus_construct(&packets[PACKET15], 33, READ_INPUT_REGISTERS, 7, 1, 14);
//  modbus_construct(&packets[PACKET16], 33, READ_INPUT_REGISTERS, 8, 1, 15);
  /////module promux TC slave 34
  modbus_construct(&packets[PACKET17], 34, READ_INPUT_REGISTERS, 1, 8, 16);
//  modbus_construct(&packets[PACKET18], 34, READ_INPUT_REGISTERS, 2, 1, 17);
//  modbus_construct(&packets[PACKET19], 34, READ_INPUT_REGISTERS, 3, 1, 18);
//  modbus_construct(&packets[PACKET20], 34, READ_INPUT_REGISTERS, 4, 1, 19);
//  modbus_construct(&packets[PACKET21], 34, READ_INPUT_REGISTERS, 5, 1, 20);
//  modbus_construct(&packets[PACKET22], 34, READ_INPUT_REGISTERS, 6, 1, 21);
//  modbus_construct(&packets[PACKET23], 34, READ_INPUT_REGISTERS, 7, 1, 22);
//  modbus_construct(&packets[PACKET24], 34, READ_INPUT_REGISTERS, 8, 1, 23);
  /////module promux TC slave 35
  modbus_construct(&packets[PACKET25], 35, READ_INPUT_REGISTERS, 1, 8, 24);
//  modbus_construct(&packets[PACKET26], 35, READ_INPUT_REGISTERS, 2, 1, 25);
//  modbus_construct(&packets[PACKET27], 35, READ_INPUT_REGISTERS, 3, 1, 26);
//  modbus_construct(&packets[PACKET28], 35, READ_INPUT_REGISTERS, 4, 1, 27);
//  modbus_construct(&packets[PACKET29], 35, READ_INPUT_REGISTERS, 5, 1, 28);
//  modbus_construct(&packets[PACKET30], 35, READ_INPUT_REGISTERS, 6, 1, 29);
//  modbus_construct(&packets[PACKET31], 35, READ_INPUT_REGISTERS, 7, 1, 30);
//  modbus_construct(&packets[PACKET32], 35, READ_INPUT_REGISTERS, 8, 1, 31);
  /////module promux DO slave 36
  modbus_construct(&packets[PACKET33], 36, PRESET_SINGLE_REGISTER, 2, 1, 32); 

 
  modbus_configure(&RS485Serial, baud, SERIAL_8N1, timeout, polling, retry_count, SSerialTxControl, packets, TOTAL_NO_OF_PACKETS, regs);
}

void loop()
{
  modbus_update();

Serial.print(regs[0]);
Serial.print("//");
Serial.print(regs[1]);
Serial.print("//");
Serial.print(regs[2]);
Serial.print("//");
Serial.print(regs[3]);
Serial.print("//");
Serial.print(regs[4]);
Serial.print("//");
Serial.print(regs[5]);
Serial.print("//");
Serial.print(regs[6]);
Serial.print("//");
Serial.println(regs[7]);
Serial.print("//");
Serial.print(regs[8]);
Serial.print("//");
Serial.print(regs[9]);
Serial.print("//");
Serial.print(regs[10]);
Serial.print("//");
Serial.print(regs[11]);
Serial.print("//");
Serial.print(regs[12]);
Serial.print("//");
Serial.print(regs[13]);
Serial.print("//");
Serial.print(regs[14]);
Serial.print("//");
Serial.print(regs[15]);
Serial.print("//");
Serial.print(regs[16]);
Serial.print("//");
Serial.print(regs[17]);
Serial.print("//");
Serial.print(regs[18]);
Serial.print("//");
Serial.print(regs[19]);
Serial.print("//");
Serial.print(regs[20]);
Serial.print("//");
Serial.print(regs[21]);
Serial.print("//");
Serial.print(regs[22]);
Serial.print("//");
Serial.print(regs[23]);
Serial.print("//");
Serial.print(regs[24]);
Serial.print("//");
Serial.print(regs[25]);
Serial.print("//");
Serial.print(regs[26]);
Serial.print("//");
Serial.print(regs[27]);
Serial.print("//");
Serial.print(regs[28]);
Serial.print("//");
Serial.print(regs[29]);
Serial.print("//");
Serial.print(regs[30]);
Serial.print("//");
Serial.println(regs[31]);
}


You can also download a free modbus slave simulator (http://peakhmi.com) if you have a RS485 converter to PC.

benoit
 
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: migue2 on Dec 22, 2015, 03:10 pm
Hi. I'm newbie. Sorry for my english.

I'm using Arduino Uno with 485 modules as master and slave.

I managed to talk to each other with the example of #350 ( http://forum.arduino.cc/index.php?topic=176142.msg2177559#msg2177559).
For simplicity, only use a package such that the master reads the status of the slave input 8. I had many problems to achieve communication, because the master did not get good answers, but I solved with large pull-up and pull-down on lines A and B bus.
It works when I connect pin 8 of the slave master LED lights. But when I disconnect pin 8 on the slave, the master initially off the led, but then back on 2 or 3 times, erratically, and finally leaves off, as it should be. What can be caused this?

From already thank you very much.

Cheers.

mig
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Dec 28, 2015, 05:05 am
Migue,
If you post your schematic and code here, then we can tell you exactly where is problem, but we cant tell you any improvement just from your problem, because it can be due to hardware or even because of software!
So please provide more details about it!
Yatin
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: nikeroy on Jan 04, 2016, 11:56 am
Hello all,

I am Nike, working with an energy meter (Schneider Conzerv EM 6436), and trying to read the register values using modbus. I saw the post http://forum.arduino.cc/index.php?topic=176142.15 and went through the entire thread (took nearly 2 days).

I followed the schematic at https://aglasspool.files.wordpress.com/2010/03/diagram1rev3.jpeg. I modified the connections with necessary resistors and Arduino Yun is master and conzerv meter is slave.

I tried with the simpleModbusMaster example with necessary baud rate, slave ID and couldn't get any response. Please help me out. I am here by attaching the manual of energy meter.

Manual : http://www.powertechinternational.in/catalouges/SCHNEIDER-CONZERV-EM-6400.pdf


Thanks in advance
Nike
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Jan 05, 2016, 06:10 am
Hi Nikeroy,
Please post your exact code (with your changes) And also your schematic so we can check where the exact fault is and can help you further!
Thanks!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: nikeroy on Jan 05, 2016, 09:02 am
Hi Yatin,

I have attached both my code and the configuration schematic. Here Uno/Yun is master and Conzerv energy meter is slave. (Manual of meter Manual : http://www.powertechinternational.in/catalouges/SCHNEIDER-CONZERV-EM-6400.pdf)

I have changed the register addresses from 3900 to 43900 or 0x0F3C etc. But, couldn't succeed. I am using SimpleModbusMasterV12 (their *.cpp and *.h files are attached).

I am using both the schematics with and without capacitors, and also changing the resistors from 680 ohm to 510 ohm (according to JuanB's manual)

Let me know which part am I missing.

BR
Nike



Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: nikeroy on Jan 06, 2016, 08:58 am
Hello all,

I am trying different techniques, like with and without resistors, with and without capacitors but no success.

Any inputs !!

--
Nike
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: nikeroy on Jan 11, 2016, 07:05 am
Hi all,

Any inputs on my previous requests ?

--
Nike
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: soundmanu on Jan 11, 2016, 11:36 pm
Hi again,

new question:  My slave sends a 32BitFloat Value. I've got Integer Values in 2 Registers. How to convert the 2 Integer Values to a 32BItFloat ?? Thanks for your Help!

Manu
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jan 12, 2016, 01:30 am
Nike,
Looking at your code I notice something that I am surprised you haven't picked up if you read the whole thread, where it is mentioned on more than a few occasions that with a small Arduino, such as an UNO, there is only one hardware serial port to use.

From looking at your code, you are trying to use that one serial port for both Modbus and to do your serial prints.
Additionally, when you use a serial port for sending of data, you first need to initialise the port with a serial.begin(...), which you don't have in case you were wanting to use the serial port for serial.print(...).

But remember, if you are using this on an UNO, you can only connect the hardware serial port to only one device, either your computer, via USB or to the MAX-485 chip that then talks Modbus to the Modbus slave.

The other thing to test, once you get that sorted out, is to swap the IEA-485 lines, that is swap the A and B lines, as I recall there was mention that some MAX-485 chips had the pins swapped. You need to confirm and clarify this claim, though swapping those lines should cause no ill effects anyhow.

____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jan 12, 2016, 01:33 am
soundmanu, please look and read the documentation for SimpleModbus, I believe it is detailed clearly enough in there to do these sorts of things.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jan 12, 2016, 01:40 am
Nike,

Again, looking at your code in a test editor, I don't believe that code you supplied at post #534 will even compile.
You have:
Code: [Select]
modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 3901, 2, readRegsVolt);But you don't declare readRegsVolt anywhere, so it could not possibly compile.
You only ever declare readRegs and use that in your serial.prints(...).

____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: soundmanu on Jan 12, 2016, 09:08 am
Dear Paul,

yes, it is....  :o
Found it!  thx

Manu
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: scuta on Jan 16, 2016, 06:25 pm
Hi All ! :smiley-lol:

Thank you for the wonderful library and great community. I've try is Simple Modbus and it works every well, but i have a question. Can I do something like this...(as the attachment)
- Arduino Mega 2560 as Modbus Master connect with RF433MHz Module(Serial 1), RS485 Module (Serial2)
- Device 1 as Modbus Slave 1, with RF433MHz
- Device 2 as Modbus Slave 2, with RS485

Thanks

ps. I've tried with separate device and it work fine, but when I put all together I can get only one device.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: itzdipu on Jan 21, 2016, 11:08 am
Hello Guys.

I am trying to communicate between arduino uno (as Master) and PC (as Slave) via modbus (RS-485). I am using  am trying to communicate between arduino uno and PC via modbus (RS-485). I am using Simple Modbus Master
library which I think very easy to understand. First I communicate Arduino to PC through a USB to TTL converter. Here I use Multiway V10 software (Its a virtual modbus simulator) in Slave mode. And I was successful. But when I use MAX485 for RS-485 communication through A & B node , I am unable to communicate. Arduino sent signal to PC.... and PC reply back also.....But Arduino did not get it. I did not get anything in my LCD Display which I connect for Showing the modbus data. i have used two MAX 485 Transceiver.

So my setup now

Arduino - MAX485- MAX485 - USB to TTL converter - PC (Multiway)

Plz see this link. Multiway

Here is my code:

Code: [Select]


#include <SimpleModbusMaster.h>

#include <LiquidCrystal.h>

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 100 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 6

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 25

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
PACKET1,
PACKET2,
PACKET3,
PACKET4,
PACKET5,
PACKET6,
PACKET7,
PACKET8,
PACKET9,
PACKET10,
PACKET11,
PACKET12,
PACKET13,
PACKET14,
PACKET15,
PACKET16,
PACKET17,
PACKET18,
PACKET19,
PACKET20,
PACKET21,
PACKET22,
PACKET23,
PACKET24,
PACKET25,
TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

LiquidCrystal lcd(9, 8, 5, 4, 3, 2);

void setup()
{
// Initialize each packet

modbus_construct(&packets[PACKET1], 1, READ_INPUT_REGISTERS, 284, 1, 0);
modbus_construct(&packets[PACKET2], 1, READ_INPUT_REGISTERS, 226, 1, 1);
modbus_construct(&packets[PACKET3], 1, READ_INPUT_REGISTERS, 271, 1, 2);
modbus_construct(&packets[PACKET4], 1, READ_INPUT_REGISTERS, 272, 1, 3);
modbus_construct(&packets[PACKET5], 1, READ_INPUT_REGISTERS, 273, 1, 4);
modbus_construct(&packets[PACKET6], 1, READ_INPUT_REGISTERS, 241, 1, 5);
modbus_construct(&packets[PACKET7], 1, READ_INPUT_REGISTERS, 242, 1, 6);
modbus_construct(&packets[PACKET8], 1, READ_INPUT_REGISTERS, 530, 1, 7);
modbus_construct(&packets[PACKET9], 1, READ_INPUT_REGISTERS, 0, 1, 8 );
modbus_construct(&packets[PACKET10], 1, READ_INPUT_REGISTERS, 247, 1, 9);
modbus_construct(&packets[PACKET11], 1, READ_INPUT_REGISTERS, 0, 1, 10);
modbus_construct(&packets[PACKET12], 1, READ_INPUT_REGISTERS, 205, 1, 11);
modbus_construct(&packets[PACKET13], 1, READ_INPUT_REGISTERS, 203, 1, 12);
modbus_construct(&packets[PACKET14], 1, READ_INPUT_REGISTERS, 207, 1, 13);
modbus_construct(&packets[PACKET15], 1, READ_INPUT_REGISTERS, 209, 1, 14);
modbus_construct(&packets[PACKET16], 1, READ_INPUT_REGISTERS, 214, 1, 15);
modbus_construct(&packets[PACKET17], 1, READ_INPUT_REGISTERS, 216, 1, 16);
modbus_construct(&packets[PACKET18], 1, READ_INPUT_REGISTERS, 0, 1, 17);
modbus_construct(&packets[PACKET19], 1, READ_INPUT_REGISTERS, 0, 1, 18);
modbus_construct(&packets[PACKET20], 1, READ_INPUT_REGISTERS, 0, 1, 19);
modbus_construct(&packets[PACKET21], 1, READ_INPUT_REGISTERS, 0, 1, 20);
modbus_construct(&packets[PACKET22], 1, READ_INPUT_REGISTERS, 0, 1, 21);
modbus_construct(&packets[PACKET23], 1, READ_INPUT_REGISTERS, 0, 1, 22);
modbus_construct(&packets[PACKET24], 1, READ_INPUT_REGISTERS, 0, 1, 23);
modbus_construct(&packets[PACKET25], 1, READ_INPUT_REGISTERS, 0, 1, 24);
 
// Initialize the Modbus Finite State Machine
modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
}

void loop()
{
modbus_update();

lcd.begin(16, 2);
lcd.print("Op. Hrs:     Hrs");
lcd.setCursor(0, 1);
lcd.print(regs[0]);
delay(500);

lcd.begin(16, 2);
lcd.print("Actual Power: KW");
lcd.setCursor(0, 1);
lcd.print(regs[1]);
delay(500);

lcd.begin(16, 2);
lcd.print("Winding T. U:  C");
lcd.setCursor(0, 1);
lcd.print(regs[2]);
delay(500);

lcd.begin(16, 2);
lcd.print("Winding T. V:  C");
lcd.setCursor(0, 1);
lcd.print(regs[3]);
delay(500);

lcd.begin(16, 2);
lcd.print("Winding T. W:  C");
lcd.setCursor(0, 1);
lcd.print(regs[4]);
delay(500);

lcd.begin(16, 2);
lcd.print("HT In Temp:    C");
lcd.setCursor(0, 1);
lcd.print(regs[5]);
delay(500);

lcd.begin(16, 2);
lcd.print("HT Out Temp:   C");
lcd.setCursor(0, 1);
lcd.print(regs[6]);
delay(500);

lcd.begin(16, 2);
lcd.print("HT Out Pr.:  bar");
lcd.setCursor(0, 1);
lcd.print(regs[7]);
delay(500);
 
lcd.begin(16, 2);
lcd.print("LT In Temp:    C");
lcd.setCursor(0, 1);
lcd.print(regs[9]);
delay(500);

lcd.begin(16, 2);
lcd.print("LubeOil Temp:  C");
lcd.setCursor(0, 1);
lcd.print(regs[11]);
delay(500);

lcd.begin(16, 2);
lcd.print("LubeOil Pr.: bar");
lcd.setCursor(0, 1);
lcd.print(regs[12]);
delay(500);

lcd.begin(16, 2);
lcd.print("LubeOil Lvl: Per");
lcd.setCursor(0, 1);
lcd.print(regs[13]);
delay(500);

lcd.begin(16, 2);
lcd.print("Crank Pr.:  mbar");
lcd.setCursor(0, 1);
lcd.print(regs[14]);
delay(500);
 
lcd.begin(16, 2);
lcd.print("IntakeAir T.:  C");
lcd.setCursor(0, 1);
lcd.print(regs[15]);
delay(500);

lcd.begin(16, 2);
lcd.print("Receiver T.:   C");
lcd.setCursor(0, 1);
lcd.print(regs[16]);
delay(500);


}



I am connecting MAX485 to arduino as

Max 485 ------ Arduino UNO

Pin 1--------------- RX; Pin 0
Pin 2--------------- TX; Pin 1
Pin 3 & 4 ---------- Tied and connected to D6 (Tx/Rx EnablePin)
Pin 5 --------------- GND
Pin 6 --------------- A
Pin 7 --------------- B
Pin 8 --------------- VCC

Problem is:

1) master send request to slave,
2) slave gets request,
3) slave process request,
4) slave returns answer to master
5) master gets answer
6) master do not process slave answer

Could you guys plz help me to short out the problem. Any assistance will be appreciated....Thanks in advance.

- DIPU
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Jan 21, 2016, 06:29 pm
I faced this type of problem too, just try a simple usb cable and use your same hardware and software, as this will take you too rs232 protocol and should run properly!
(Hope you are not connected arduino with max 485 and usb both at same time as i did that before and suffer a lot! cause it conflicts and receiver dont responce to it but it do transmit though!)
And try with serial.h so if there is that problem which I faced will be sorted out!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jan 22, 2016, 12:15 am
yatin wrote:
Quote
this will take you too rs232 protocol
Yatin, there is no such thing as a Rs-232 protocol, not in the way you mean at least.

RS-232 is an electrical specification only, nothing to do with data at all.

In addition, there is no RS-232 port on the Arduino at all, only USB or standard TTL async serial.
____
Paul
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: aditpc on Jan 25, 2016, 04:46 am
hello i have question about modbus RTU i cant communication my hardware with my arduino uno, my hardware Power Meter Schneider PM1200 with RS485 communication. Please tell me the process for communication i dont understand thanks
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JPrust on Jan 28, 2016, 06:18 pm
Hello! After sucessfully comunicate one arduino with other(with the SimpleModbus library),
i am trying to make communication between a HMI Delta (model DOP-B03E211) as master and a arduino(slave) with SimpleModbus library. The code of the arduino:
Code: [Select]

#include <LiquidCrystal.h>
#include <SimpleModbusSlave.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#define  LED 9

const long intervalo = 10;
unsigned long tempoAnterior = 0;

enum {     
  VAL_LED,
  VAL_POT,         
  HOLDING_REGS_SIZE
};

unsigned int holdingRegs[HOLDING_REGS_SIZE];

void setup(){
 
  lcd.begin(16, 2);
  lcd.print("Modbus - Slave");
 
  modbus_configure(&Serial, 9600, SERIAL_8N2, 3, 7, HOLDING_REGS_SIZE, holdingRegs);
 
  pinMode(LED, OUTPUT);
}

void loop() {
  modbus_update();

  analogWrite(LED, holdingRegs[VAL_LED] / 4);

  holdingRegs[VAL_POT] = analogRead(0);

  unsigned long tempoAtual = millis();

  if (tempoAtual - tempoAnterior >= intervalo){
    tempoAnterior = tempoAtual;
   
    lcd.setCursor(0, 1);
    lcd.print("                  ");
    lcd.setCursor(0, 1);
    lcd.print(holdingRegs[VAL_LED]);
   
    lcd.setCursor(6, 1);
    lcd.print(holdingRegs[VAL_POT]);
  }
}


And attached some screenshots of dopsoft program(to configure HMI).

How can i access the registers of the arduino(val_led and val_pot) with the HMI?

Excuse-me for my bad english.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: caddish12 on Feb 01, 2016, 03:38 am
Hello! After sucessfully comunicate one arduino with other(with the SimpleModbus library),
i am trying to make communication between a HMI Delta (model DOP-B03E211) as master and a arduino(slave) with SimpleModbus library. The code of the arduino:
Code: [Select]

#include <LiquidCrystal.h>
#include <SimpleModbusSlave.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#define  LED 9

const long intervalo = 10;
unsigned long tempoAnterior = 0;

enum {     
  VAL_LED,
  VAL_POT,         
  HOLDING_REGS_SIZE
};

unsigned int holdingRegs[HOLDING_REGS_SIZE];

void setup(){
 
  lcd.begin(16, 2);
  lcd.print("Modbus - Slave");
 
  modbus_configure(&Serial, 9600, SERIAL_8N2, 3, 7, HOLDING_REGS_SIZE, holdingRegs);
 
  pinMode(LED, OUTPUT);
}

void loop() {
  modbus_update();

  analogWrite(LED, holdingRegs[VAL_LED] / 4);

  holdingRegs[VAL_POT] = analogRead(0);

  unsigned long tempoAtual = millis();

  if (tempoAtual - tempoAnterior >= intervalo){
    tempoAnterior = tempoAtual;
   
    lcd.setCursor(0, 1);
    lcd.print("                  ");
    lcd.setCursor(0, 1);
    lcd.print(holdingRegs[VAL_LED]);
   
    lcd.setCursor(6, 1);
    lcd.print(holdingRegs[VAL_POT]);
  }
}


And attached some screenshots of dopsoft program(to configure HMI).

How can i access the registers of the arduino(val_led and val_pot) with the HMI?

Excuse-me for my bad english.
Hi JPrust,

Maybe you will need this line of code:
Code: [Select]

modbus_configure(&Serial, 19200, SERIAL_8N2, DEVICE_ID, TxEnablePin, HOLDING_REGS_SIZE, holdingRegs);
// modbus_update_comms(baud, byteFormat, id) is not needed but allows for easy update of the
// port variables and slave id dynamically in any function.
modbus_update_comms(19200, SERIAL_8N2, 1);


As you declared in your code, register of VAL_LED is READ register (address 0) and VAL_POT(address 1) is WRITE register. So, in HMI you can access with address 40001 for VAL_LED (HMI write value into this register such as button input) and 40002 for VAL_POT(HMI will read from this register such as number display?).

Why 40001 and 40002? Because in Delta HMI register address, address 0 will be 40001, so if you need to access register 10, it will be 40011 in Delta HMI. and the data will be WORD.

Hop it will help.

Thanh Nguyen
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: JPrust on Feb 01, 2016, 02:09 pm
Thanks for your help Caddish12!

I released my code and it is ok, the problem was on the electronic connections.

I am happy with this progress, and happy with the library and the help of this fórum.

Thanks!

Brasil - JPrust
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Jame_Ji on Feb 11, 2016, 03:37 pm
Hi everybody,

I want to ON,OFF with faction 05.
Please help
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Feb 12, 2016, 05:25 am
Hi Jame_ji,
With that minimum inputs its hard for us to help you or guide you!
So can you briefly tell us what exactly you want to make and what you planned of how to make it, also what is your code and schematic?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Tayo on Feb 12, 2016, 10:07 am
Hello !

At first thanks to Paul and JuanB, thanks for your answers

I'm working  on a project, with my Arduino Due is to retrieve information from a Modbus communication, this information will be storage on an SD card and that every second (for this interruption I use TC0).
Well I have a code and it works, I can retrieve the data and to save them.

The trouble is that it is too slow, the succesfull request for my 14 variables increase by one in about 20 seconds.
I also change the baud rate of the Arduino as on hardware wich sends me this information and eliminate all unnecessary delays which take time but nothing, it's not going fast enough.
I put the code copy, I do not know if I was clear enough.

Thank you in advance for your help!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: migue2 on Feb 12, 2016, 04:09 pm
Migue,
If you post your schematic and code here, then we can tell you exactly where is problem, but we cant tell you any improvement just from your problem, because it can be due to hardware or even because of software!
So please provide more details about it!
Yatin
Hello again.

In principle, thank Yatin your answer and the entire community that brings in this forum.

With your help I managed to run the assembly. The problem that generated the erratic response was the lack of a pulldown resistor at the input. I solved it by putting a 10k pulldown resistor, as suggested several posts.

In short, and waiting will be useful to someone else:
- Resistors of 690ohm line A-> Vcc line and B-> Gnd.
- 10k resistors -> Vcc, the Rx pin of Arduino Master and Slave.
- Resistance 10k pulldown -> Gnd at the entrance of the Slave, which stabilizes the input value and avoid erratic responses.

Moraleja (mainly for myself :) ): Do not underestimate the importance of the pullup and pulldown resistors in the assemblies.

Thanks again to all.

Cheers

mig
Title: cannot compile
Post by: seand168 on Feb 12, 2016, 06:18 pm
Hello all,

thanks for great support and vast amount of useful information. I am new to the ModBus RTU and need to program a simple plating rectifier. I am starting first to try to read the input registers (which the attached documentation named Monitoring Zone). I can't even compile the sketch. can someone tell me what is missing? the error code I have is "Packet" does name a type.

#include <SimpleModbusMaster.h>
#define baud 9600
#define timeout 1000
#define polling 2
#define retry_count 50

#define TxEnablePin 2
#define LED 13

enum
{
 PACKET1,
 TOTAL_NO_OF_PACKETS
};

Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
unsigned int readRegs[3];
void setup()
{
  /// Volteq Modbus Slave Id 1 and start register 1 and length 2
 modbus_construct(packet1, 1, READ_INPUT_REGISTERS, 0, 3, readRegs);
 ///// Starting serial for Arduino
 Serial.begin(9600);
 while (!Serial) { ; }
 
 modbus_configure(&Serial1, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
 pinMode(LED, OUTPUT);
}

void loop()
{
 modbus_update();
 
 //if (Serial1.available()){
   /// Write the received data from Serial 1 to Serial
    Serial.println(packet1->requests);
    Serial.println(packet1->successful_requests);
    Serial.println(packet1->failed_requests);
    Serial.println(packet1->exception_errors);
   
  //Serial.print("Status Word=");
 //Serial.println(readRegs[0]); 
 // Serial.print("Output Current=");
 // Serial.println(readRegs[1]);
  //Serial.print("Output Voltage=");
 // Serial.println(readRegs[2]);

   delay(1000);
 }
 analogWrite(LED, readRegs[0]>>2);
}
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: lolhun1988 on Feb 12, 2016, 10:09 pm
Hello all,

I am sorry I did not write in this topic about my Modbus problem. :) I created a new one, ups... Could you help me with my issue here?  :o

Link: https://forum.arduino.cc/index.php?topic=378532.0

Best Regards,
Adam
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: seand168 on Feb 13, 2016, 05:58 am
I figured out the issue with Packet, but now it is saying packetPointer does not name a type.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: OB01 on Feb 25, 2016, 04:29 pm
Hello everyone and sorry for my english,
I need to interface a counter enegia Schneider iEN3255 with ModBus output 485 with my Arduino UNO.
I have some doubts about connections and hardware to interface.
I read on some posts that to get the communication between Arduino and the counter requires a MAX485 chip, I bought this (attach links and photos).

Link:  http://www.amazon.it/MAX485-Modul-RS-485-Modul-TTL-RS-485/dp/B00JWKJHXA/ref=sr_1_1?ie=UTF8&qid=1456413968&sr=8-1&keywords=max485

I wanted to know if it's okay.
My doubt is on the chip, from the photo reads MAX485 ESA +1418 okay ??

My second doubt is on the links I wanted to know whether the connections that I have made are good. (Diagram attached).
I wanted to know when the resistor is needed, and if they fit as entered.

Thank you all for your attention
Claudio.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: jose_francisco on Feb 27, 2016, 12:30 am
Hello.

I'm using this library in mi master device but I want to implement dynamic slave addition and removal (on run time). I think that the solution relies on memory allocation but I'm not sure. I'm working on chipkit max32 with 128k RAM. I doubt if this RAM will be large enough to manage 256 slaves.
Has anyone worked in this feature?

Thanks in advance.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: LeeOutram on Feb 28, 2016, 05:24 pm
Hello All,

I'm using Mega as Master (serial1) and an Uno as Slave.
I've got the latest versions of the master and slave libraries and I'm attempting to use the examples posted with the libraries for lighting up LED's via PWM's by changing A0 on the opposite unit.

The issue I have is that I can change A0 on the Master, I can see the result on the slave fine
However, If I change A0 on the slave I do not see a result on the master. I've seen references to this occuring in the past on this thread but the solutions all appear to be hardware related.

I am using an RS485 setup for the transfers using MAX485 chips BUT just to prove this issue isn't hardware I removed my 485 hardware and just connected both arduino's using TTL and I got the same results so I believe the issue is software related.

I've printed "Regs[0]" to the serial port on the master, which I believe is the parameter i'm attempting to influence from the slave and I just get a value of "769" which doesn't change.

On the slave I've also attempted to write a constant value to ensure it's not an issue with my analog circuit but again it doesnt appear to have any effect.

Can someone have a look at this and let me know where I'm going wrong?

Best Regards,

Lee

Master Code:
Code: [Select]
#include <SimpleModbusMaster.h>

/*
   The example will use packet1 to read a register from address 0 (the adc ch0 value)
   from the arduino slave (id=1). It will then use this value to adjust the brightness
   of an led on pin 9 using PWM.
   It will then use packet2 to write a register (its own adc ch0 value) to address 1
   on the arduino slave (id=1) adjusting the brightness of an led on pin 9 using PWM.
*/

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 500 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

#define LED 9

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 1

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
  Serial.begin(9600); //initialise serial port
  // Initialize each packet
  modbus_construct(&packets[PACKET1], 1,    READ_HOLDING_REGISTERS, 0, 1, 0);
  modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
 
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial1, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
 
  regs[0] = analogRead(0); // update data to be written to arduino slave
 
  analogWrite(LED, regs[0]>>2); // constrain adc value from the arduino slave to 255

Serial.println (regs[1]);


Slave Code:
Code: [Select]
#include <SimpleModbusSlave.h>

/*
   SimpleModbusSlaveV10 supports function 3, 6 & 16.
   
   This example code will receive the adc ch0 value from the arduino master.
   It will then use this value to adjust the brightness of the led on pin 9.
   The value received from the master will be stored in address 1 in its own
   address space namely holdingRegs[].
   
   In addition to this the slaves own adc ch0 value will be stored in
   address 0 in its own address space holdingRegs[] for the master to
   be read. The master will use this value to alter the brightness of its
   own led connected to pin 9.
   
   The modbus_update() method updates the holdingRegs register array and checks
   communication.

   Note: 
   The Arduino serial ring buffer is 64 bytes or 32 registers.
   Most of the time you will connect the arduino to a master via serial
   using a MAX485 or similar.
 
   In a function 3 request the master will attempt to read from your
   slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES
   and two BYTES CRC the master can only request 58 bytes or 29 registers.
 
   In a function 16 request the master will attempt to write to your
   slave and since a 9 bytes is already used for ID, FUNCTION, ADDRESS,
   NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write
   54 bytes or 27 registers.
 
   Using a USB to Serial converter the maximum bytes you can send is
   limited to its internal buffer which differs between manufactures.
*/

#define  LED 9 

// Using the enum instruction allows for an easy method for adding and
// removing registers. Doing it this way saves you #defining the size
// of your slaves register array each time you want to add more registers
// and at a glimpse informs you of your slaves register layout.

//////////////// registers of your slave ///////////////////
enum
{     
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  ADC_VAL,  //reg 0   
  PWM_VAL,  //reg 1     
  HOLDING_REGS_SIZE // leave this one
  // total number of registers for function 3 and 16 share the same register array
  // i.e. the same address space
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array
////////////////////////////////////////////////////////////

void setup()
{
  /* parameters(HardwareSerial* SerialPort,
                long baudrate,
unsigned char byteFormat,
                unsigned char ID,
                unsigned char transmit enable pin,
                unsigned int holding registers size,
                unsigned int* holding register array)
  */
 
  /* Valid modbus byte formats are:
     SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
     SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
     SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
     
     You can obviously use SERIAL_8N1 but this does not adhere to the
     Modbus specifications. That said, I have tested the SERIAL_8N1 option
     on various commercial masters and slaves that were suppose to adhere
     to this specification and was always able to communicate... Go figure.
     
     These byte formats are already defined in the Arduino global name space.
  */

  modbus_configure(&Serial, 9600, SERIAL_8N1, 1, 2, HOLDING_REGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, byteFormat, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(9600, SERIAL_8N1, 1);
 
  pinMode(LED, OUTPUT);
}

void loop()
{
  // modbus_update() is the only method used in loop(). It returns the total error
  // count since the slave started. You don't have to use it but it's useful
  // for fault finding by the modbus master.
 
  modbus_update();
 
  holdingRegs[ADC_VAL] = 100; //analogRead(A1); // update data to be read by the master to adjust the PWM
 
  analogWrite(LED, holdingRegs[PWM_VAL]>>2); // constrain adc value from the arduino master to 255
 
  /* Note:
     The use of the enum instruction is not needed. You could set a maximum allowable
     size for holdinRegs[] by defining HOLDING_REGS_SIZE using a constant and then access
     holdingRegs[] by "Index" addressing.
     I.e.
     holdingRegs[0] = analogRead(A0);
     analogWrite(LED, holdingRegs[1]/4);
  */
 
}


Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: yatin on Mar 05, 2016, 07:06 pm
Can u tell us that is packets are getting acknowledged or not?
Means if masters message is getting delivered to slave properly slave should send acknowledge to it by replying it with comparing crc!
 Means if you could use any mod bus slave and master simulator on computer and could give us thst info it could be handy for us to debug, thanks!
Also even though you think its not hardware problem still can u share your hardware details also?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: jose_francisco on Mar 07, 2016, 10:17 am
Sorry about my insistence.
I'm looking for help about dynamic (on run time) addition and removal of slaves.
I also want to know about experiences with large number of slaves and SRAM memory issues.
Thanks again.



Hello.

I'm using this library in mi master device but I want to implement dynamic slave addition and removal (on run time). I think that the solution relies on memory allocation but I'm not sure. I'm working on chipkit max32 with 128k RAM. I doubt if this RAM will be large enough to manage 256 slaves.
Has anyone worked in this feature?

Thanks in advance.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: Parker_ on Mar 08, 2016, 06:32 pm
Hello everyone, I am working on a project that involves a Powerflex 4 VFD and an Arduino Uno. I have a DFRobot RS485 shield. I am looking to control the start, stop and speed settings of the VFD using Modbus communication. The Powerflex supports function codes 3 and 6. I am unsure of which bits to send in order to control the VFD. As of right now, I am just sending the value of 100 as a speed setting for the VFD. Later, I am hoping to include pushbuttons to allow a user to increase or decrease this speed. Here is the code that I have currently:
Code: [Select]

#include <SimpleModbusMaster.h>
#include <TimerOne.h>
#include <SoftwareSerial.h>
//#include <genieArduino.h>

//////////////////// Port information ///////////////////

#define baud 19200      
#define timeout 1000      
#define polling 100      
#define retry_count 10  
#define TxEnablePin 20  
#define TOTAL_NO_OF_REGISTERS 1
float x;
//////////////////// Assembly of the Modbus packets ///////////////

// We have 1 read to do from the VSD and two 2 writes, a total of 3 packets need to be defined to carry the data over Modbus.

enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  TOTAL_NO_OF_PACKETS // Leave this last entry. It tells the library how many packets are to be sent out.
};

Packet packets[TOTAL_NO_OF_PACKETS]; //Leave this line in here.

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

/////////////////////////VSD READS//////////////////////////////
Packet* statusWordVSD = &packets[PACKET1];

/////////////////////////VSD WRITES/////////////////////////////
Packet* commandWordVSD = &packets[PACKET2];
Packet* userSetSpeedVSD = &packets[PACKET3];

////////VFD READ VARIABLES///////////
unsigned int readStatusWordVSD = 1;
unsigned int readRegs[2];

////////VFD WRITE VARIABLES//////////
unsigned int writeControlWordVSD = 2 ;
unsigned int writeUserSetSpeedVSD = 100; //A decimal "100" equals 10 Hz


void setup()
{
 Serial.begin(19200); // Start the Arduino IDE terminal in case we need it for debugging.
  
  
  modbus_construct(statusWordVSD, 2, READ_HOLDING_REGISTERS, 8449, 1, readStatusWordVSD);
  modbus_construct(commandWordVSD, 2, PRESET_SINGLE_REGISTER, 8193, 1, writeControlWordVSD);
  modbus_construct(userSetSpeedVSD, 2, PRESET_SINGLE_REGISTER, 8194, 1, writeUserSetSpeedVSD);
 
 modbus_configure(&Serial, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 }

void loop()
{
  modbus_update();
}


I am not really sure where to go from here. I will also attach the Powerflex manual. The Modbus communication settings start on page 93.  Any help would be greatly appreciated.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: hajihosseinlu on Mar 09, 2016, 10:40 pm
Hello Everyone,

I am trying to read data from a Modbus sensor. I have purchased "RS485 Shield V2". I am sort of new to arduino programing and I am trying to learn modbus libraries (ex: Modbus master), but I can not find a good way to start and learning the commands to read holding registers from the device.
Can anybody help? Which code I can use?

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: LeeOutram on Mar 13, 2016, 10:27 am
Can u tell us that is packets are getting acknowledged or not?
Means if masters message is getting delivered to slave properly slave should send acknowledge to it by replying it with comparing crc!
 Means if you could use any mod bus slave and master simulator on computer and could give us thst info it could be handy for us to debug, thanks!
Also even though you think its not hardware problem still can u share your hardware details also?
Hi Yatin, Many thanks for your reply and appologies for the late response. I probably posted for help too soon and I solved this a few weeks ago it was just my registry mapping that was bad in the code. I'm now looking at multiple slaves but having issues with that too as only one slave tends to reply. If I comment out the code for either slave in the master the alternative slave one works fine. I'll spend some more time playing with this and post again when I get bored of trying!

Best Regards,

Lee
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: kgyd on Apr 08, 2016, 12:14 pm
Hello. I attach a scheme with the topology of my project. I have a PC which I would like to act as Modbus master and 3 (maybe 4) Arduinos connected over RS485. I would like them to act as Modbus slaves. Originally I planned to use an USB-RS485 stick in the PC. Is it necessary? Can I do it over USB as in the attached scheme? If yes, what would be the connection with question mark in the scheme? I mean, can I just connect somehow the UART over which the USB communication goes to the MAX485?

I tend to prefer if the Modbus master software runs on the PC and the PC takes care of all the polling and processing the input.

(https://forum.arduino.cc/index.php?action=dlattach;topic=176142.0;attach=162286)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: minida28 on Apr 10, 2016, 02:31 pm
Hi guys,

Greetings from Indonesia!

First of all thank you for this nice library by JuanB.

I want to report that I managed to draw some data from a modbus-enabled kWh meter using only an ESP8266 and an RS485 module.

(http://s18.postimg.org/4vhkmebw9/espmodbus.jpg)


The kWH meter is a GAHE GHDS100E single phase kWH meter (modbus RTU).
The esp unit is a Wemos D1 mini.

Library I used is the version 2 ref2 (SimpleModbusMasterV2rev2) - with small modification, read below.


Prior to using the esp unit, I have tested this library on arduino UNO with no problems. But when I change the UNO to esp unit (Wemos), the sketch won't compile, with following errors:

Code: [Select]
D:\minida28\Dropbox\Arduino\Sketch\libraries\SimpleModbusMasterV2rev2\SimpleModbusMaster.cpp: In function 'void modbus_configure(HardwareSerial*, long int, unsigned char, long int, long int, unsigned char, unsigned char, Packet*, unsigned int, unsigned int*)':

D:\minida28\Dropbox\Arduino\Sketch\libraries\SimpleModbusMasterV2rev2\SimpleModbusMaster.cpp:450:38: error: invalid conversion from 'unsigned char' to 'SerialConfig' [-fpermissive]

  (*ModbusPort).begin(baud, byteFormat);

                                      ^

In file included from C:\Users\iqbal_000\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.1.0\cores\esp8266/Arduino.h:246:0,

                 from D:\minida28\Dropbox\Arduino\Sketch\libraries\SimpleModbusMasterV2rev2\SimpleModbusMaster.h:83,

                 from D:\minida28\Dropbox\Arduino\Sketch\libraries\SimpleModbusMasterV2rev2\SimpleModbusMaster.cpp:1:

C:\Users\iqbal_000\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.1.0\cores\esp8266/HardwareSerial.h:77:10: error:   initializing argument 2 of 'void HardwareSerial::begin(long unsigned int, SerialConfig)' [-fpermissive]

     void begin(unsigned long baud, SerialConfig config)

          ^

exit status 1
Error compiling for board WeMos D1 R2 & mini.


I was able to make it work by replacing this line on SimpleModbusMaster.cpp file. line 450:

from
(*ModbusPort).begin(baud, byteFormat);


to
(*ModbusPort).begin(baud, SERIAL_8N1);

So if you want to use this library on ESP8266, you have to make small modification as mentioned above.

I am newbie in arduino, so I hope any gurus here are willing to help to update this library so it will be compatible to both arduino and esp8266.

Right now the ESP unit is reading 11 register values from the kWh meter, serial printing useful registers value (voltage, amp, wattage, Hz, PF etc) via debug UART, and sending MQTT data to a local MQTT broker.
To upload new firmware to the esp, I use OTA - with necessary library offcourse.

To anyone interested in my sketch, I have attached my sketch. Please be informed I have used BOJAN's sketch as a basis (thanks to him also) - posted in this thread as well, and then I modified it little by little and combine with some others sketchs.

If you found any errors please do let me know.

What the sketch do:
- reading input registers (11 registers to be exact)
- transform the 'read' value to float data type
- serial printing the readings to debug UART port of esp8266
- sending the readings to a local MQTT broker (I use PubSubClient library)
- OTA update capable (using necessary library) - I used OTA basic sketch as the template.

Cheers,

(https://forum.arduino.cc/index.php?action=dlattach;topic=176142.0;attach=162572)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: gr8going on Apr 12, 2016, 09:33 am
Hi mindia28

i'm using cc3200 (TI launchpad)
I've energy meter (Slave) which has rs485 output
I'm trying to read value from reg 3911 = voltage LN  (as per the product UG)
Also I've installed "Modbus Slave" software and allocated address with some regs


Now,
I've flashed the MODBUS master code with couple of modification in SimpleModbusMaster.cpp which (i think) supports cc3200

1) (*ModbusPort).begin(baud, SERIAL_8N1); => to => (*ModbusPort).begin(baud);
// since cc3200 does not support SERIAL_* the syntax is Serial(<baud>)

Now the code is error free/compiled and flashed in cc3200

After this my cc3200 can act as MASTER!!


Result:

>> I'm unable to see the values read by cc3200 from my Modbus slave software

//----------------code snippet for construct  //----------------
Code: [Select]
//  modbus_construct(&packets[PACKET1], ID, READ_INPUT_REGISTERS, Addr, Size, allocate Reg address to be stored);    // read Voltage
 modbus_construct(&packets[PACKET1], 1, READ_INPUT_REGISTERS, 3911, 2, 10);    // read Voltage



Code: [Select]

float Voltage;
 temp = (unsigned long) regs[10] << 16 | regs[11];
 Voltage = *(float*)&temp;




Code: [Select]

 Serial1.print("V:");
 Serial1.print(Voltage, 1);


-------------------//

I can only see values in Real Term which reads my Serial1 as
V:0.0

Next what I tried

>> I'm unable to see values when I connect my energy meter "directly" to Modbus master software (through RS485/USB converter) and poll the address 3911 in function 04


can you please explain how to get the data from energy meter <either> to Modbus Master software
or
Modbus slave software to my cc3200

I feel the data is missing due to
1)  Not proper assignment of address bit in Slave (computer)
2) Not proper assignment of address to be read in Master (cc3200)
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: minida28 on Apr 12, 2016, 05:12 pm
Hi gr8going,

I just have played with this "Modbus" and stuffs since one week ago, but I will try to help based on my short experience  :)

I've energy meter (Slave) which has rs485 output
There are several transmission modes of Modbus (RTU, ASCII, etc). Since the library is for Modbus RTU, can you confirm your Modbus unit is also an RTU?

I feel the data is missing due to
1)  Not proper assignment of address bit in Slave (computer)
2) Not proper assignment of address to be read in Master (cc3200)
I suggest better first make sure you can read the data from your energy meter using your favorite Modbus software installed on your PC/laptop. By doing that you can confirm:
- you have selected the correct function
- you have read the correct the address register
- you have chosen the correct size of register
- confirm the data type (normally 16 bit unsigned long)

I have tried several free Modbus RTU software I could find on the net, but I have great success with this software -> ShortBus Modbus Scanner (https://sourceforge.net/projects/shortbusmodbusscanner)
I tried play with all the settings in the software, and once I can confirm the above parameter are all correct, then I can start implement the parameter to my Arduino sketch.

Cheers,

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: gr8going on Apr 12, 2016, 10:37 pm
Hi mindia28,

Appreciate your time...

There are several transmission modes of Modbus (RTU, ASCII, etc). Since the library is for Modbus RTU, can
you confirm your Modbus unit is also an RTU?
ANS>> RTU

Yes you are right, the one which I had was using earlier was not helping me. Then I installed QMODBus master (https://sourceforge.net/projects/qmodmaster/?source=typ_redirect) everything was working as expected


I tried Read Input reg (Function 03) with direct address 3910 and - it worked perfectly!!  :)

Now I have a different issue

My cc3200 (Mobbus Master) which comes out of loop once it hit "retry_count" > specified value
I tried changing the higher value and it looks like even for 50 it's not getting to connect to my power meter

But the same code worked well when I simulated with QModBus Slave I did not see any breakage due to retry_count

That is, values from Slave were read into master through Serial com port and it was showing in Serial1 (com port)


Please note ONE change:

I'm forced to use Serial1 to communicate with my slave (power meter) and trying to snip what's going on through Serial - apart from that there is NO change)


Should I need to add more delays?? any suggestions

My circuit connection is:

cc3200 -> Serial1 -> TTl/232 converter -> 232/485 converter -> Power meter Rs485 port

I'm snipping o/p of Serial1 using Serial and it shows

Code: [Select]
V:0.0

requests: 1
successful_requests: 0
failed_requests: 1
exception_errors: 0
connection: 1
V:0.0
:
etc.,
:

V:0.0

requests: 20
successful_requests: 0
failed_requests: 19
exception_errors: 0
connection: 1
V:0.0
:
ect.,
:

V:0.0

requests: 50
successful_requests: 0
failed_requests: 50
exception_errors: 0
connection: 0
V:0.0
0
requests: 50
successful_requests: 0
failed_requests: 50
exception_errors: 0
connection: 0



Thanks
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: minida28 on Apr 13, 2016, 06:16 am
Hi gr8going,

Well.. I am not sure what is the cause of your problem

How many register address are you reading at once?

Maybe you can try increase the scan rate; change this line:

#define polling 40 // the scan rate


Initially it was 200. It is too slow for my need because I am reading 11 address at once and I want all values be updated at least once every second.

But If I go lower than 40, then I start experience increasing failed_requests count.

Cheers,
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: gr8going on Apr 13, 2016, 08:15 pm
Thanks for your time!

Well.. I figured out the problem, it was due to wrong address range - was surprised to know as per specification the address defined was 3911 (2x 8 bit) to fetch Voltage but when I give  3910 as staring address and with range 2 ... it worked fine!

Now seeing different issue

The values displayed are ambiguous, I have ~210 V  displayed in meter but I'm getting "-4294967295.2147483647" and some times "-0.0" when connected to device.

Please note: when I tried with simulator the displayed values are perfectly matching with what simulator but not when I connect with my power meter.

Is this due to the line
Code: [Select]

unsigned long temp, Vln1;

  float Voltage;
  temp = (unsigned long) regs[10] << 16 | regs[11];
  Voltage = *(float*)&temp;


I guess 16 bit left shift should be done for both reg1 and reg2 (here regs[10] and regs[11])

can you please explain above lines in the code?

Please note:
All parameter values in my power meter device are stored in "float"
During simulation my device returns following Hex value for voltage LN parameter (expected is 220)
regs[10] = 4D_21
regs[11] = 43_52

What I need to do is to bit-order reversal of above to

 52_43 concatenate with  21_4D

Voltage in Hex = 5243214D

The above Hex value shall return below float

210136......480.00000 (some big number)

Thus Finally I should divide that by 10^9 to get my voltage ...

can you please suggest how to achieve this..

Thanks a lot!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: gr8going on Apr 14, 2016, 10:32 am
Hi minidia...

The problem published

Now seeing different issue

The values displayed are ambiguous, I have ~210 V  displayed in meter but I'm getting "-4294967295.2147483647" and some times "-0.0" when connected to device.

is now resolved

It was very simple.. I just need to swap the order of registers.. :) that is regs[10] | regs[11] ==> to ==> regs[11] | regs[10]

Now I can understand what "<< 16" does ...

Code: [Select]

modbus_construct(&packets[PACKET1], 1 , READ_HOLDING_REGISTERS, 3910, 2, 10);    // read Voltage  To access 3911 <IMPT>
:
etc.,
:
unsigned long temp;
 float Voltage;
 temp = (unsigned long) regs[11] << 16 | regs[10];
 Voltage = *(float*)&temp;
 :
etc.,
:
 
Serial.print("Line to neutral voltage VLN:");
    //Serial.print(regs[11], HEX);
    //Serial.println(regs[10], HEX);
    Serial.println(Voltage, 1);



Resulted in proper values as that of what was being displayed in meter :)

Great!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: minida28 on Apr 14, 2016, 10:39 am
Hi gr8going,

Nice to read that you solve your problem!

That method (swapping register address) was also mentioned and suggested in JuanB's documentation (creator of this library).

Keep hacking!

Cheers,
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: lvino on Apr 22, 2016, 09:49 am
Hi guys,

Greetings from Indonesia!

First of all thank you for this nice library by JuanB.

I want to report that I managed to draw some data from a modbus-enabled kWh meter using only an ESP8266 and an RS485 module.

(http://s18.postimg.org/4vhkmebw9/espmodbus.jpg)


The kWH meter is a GAHE GHDS100E single phase kWH meter (modbus RTU).
The esp unit is a Wemos D1 mini.

Library I used is the version 2 ref2 (SimpleModbusMasterV2rev2) - with small modification, read below.


Prior to using the esp unit, I have tested this library on arduino UNO with no problems. But when I change the UNO to esp unit (Wemos), the sketch won't compile, with following errors:

Code: [Select]
D:\minida28\Dropbox\Arduino\Sketch\libraries\SimpleModbusMasterV2rev2\SimpleModbusMaster.cpp: In function 'void modbus_configure(HardwareSerial*, long int, unsigned char, long int, long int, unsigned char, unsigned char, Packet*, unsigned int, unsigned int*)':

D:\minida28\Dropbox\Arduino\Sketch\libraries\SimpleModbusMasterV2rev2\SimpleModbusMaster.cpp:450:38: error: invalid conversion from 'unsigned char' to 'SerialConfig' [-fpermissive]

  (*ModbusPort).begin(baud, byteFormat);

                                      ^

In file included from C:\Users\iqbal_000\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.1.0\cores\esp8266/Arduino.h:246:0,

                 from D:\minida28\Dropbox\Arduino\Sketch\libraries\SimpleModbusMasterV2rev2\SimpleModbusMaster.h:83,

                 from D:\minida28\Dropbox\Arduino\Sketch\libraries\SimpleModbusMasterV2rev2\SimpleModbusMaster.cpp:1:

C:\Users\iqbal_000\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.1.0\cores\esp8266/HardwareSerial.h:77:10: error:   initializing argument 2 of 'void HardwareSerial::begin(long unsigned int, SerialConfig)' [-fpermissive]

     void begin(unsigned long baud, SerialConfig config)

          ^

exit status 1
Error compiling for board WeMos D1 R2 & mini.


I was able to make it work by replacing this line on SimpleModbusMaster.cpp file. line 450:

from
(*ModbusPort).begin(baud, byteFormat);


to
(*ModbusPort).begin(baud, SERIAL_8N1);

So if you want to use this library on ESP8266, you have to make small modification as mentioned above.

I am newbie in arduino, so I hope any gurus here are willing to help to update this library so it will be compatible to both arduino and esp8266.

Right now the ESP unit is reading 11 register values from the kWh meter, serial printing useful registers value (voltage, amp, wattage, Hz, PF etc) via debug UART, and sending MQTT data to a local MQTT broker.
To upload new firmware to the esp, I use OTA - with necessary library offcourse.

To anyone interested in my sketch, I have attached my sketch. Please be informed I have used BOJAN's sketch as a basis (thanks to him also) - posted in this thread as well, and then I modified it little by little and combine with some others sketchs.

If you found any errors please do let me know.

What the sketch do:
- reading input registers (11 registers to be exact)
- transform the 'read' value to float data type
- serial printing the readings to debug UART port of esp8266
- sending the readings to a local MQTT broker (I use PubSubClient library)
- OTA update capable (using necessary library) - I used OTA basic sketch as the template.

Cheers,



hi, minida can i have ur contact i need u talk in personally , iam from indonesia too i am very interested with ur project that very same to me, pls answer hehe
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: hajihosseinlu on Apr 27, 2016, 04:44 pm
Hello everyone!

I am using RS485 Shield for Arduino Uno. When I run my program to read from a slave modbus sensor, I see the data being sent from TX pin but the output of RS485 shield does not make sense and it is only pulse.

My understanding is that they must be identical data except the voltage level is different, am I correct?
If the output is not right, I need a new RS485 shield?

Thanks in advance!


Here is a link to the RS485 shield I am using
http://store.linksprite.com/rs485-shield-for-arduino-v2-1/#ProductReviews



Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rexlee on May 03, 2016, 12:49 am
I have used SimpleModbus for a year or so on a 40 foot motor vessel.  Since then project creep has occurred and I am not getting enough transactions/second.  Cranking the baud rate up from 9600 to 250,00, did not improve the throughput at that much.  I noticed though that the reliability did not deteriorate.  Obviously there was "stuff" happening in the library that was holding things up.
I contemplated having multiple busses, but this presented problems with data sharing requiring some bridges.   Another solution was required!

In both the master & slave , I noticed that a long delay was executed every time after a character was read from the buffer.   I changed this so that a delay is only executed after the buffer is found empty just after fetching a character, and then testing once more before exiting the receive loop.
This avoids 10 X 750 uS of wasted time at both the slave & master so, slicing off an overhead of 15 ms./transaction.
Further more I changed the final so that it uses a computed T=1.5 rather than 750 uS for baud rates >19200, slicing off another 600uS at 250000 BAUD or another 1.2 mS/ transaction. giving a total saving of 16.2 mS.
In addition, in the master, I obviated the third state so that after a completed transaction it goes directly
back to IDLE slicing of some more time.

I have a test setup running with two slaves each being sent a READ & WRITE of one register.
I am getting 400 transaction/second without a problem.  Obviously this will reduce with longer packets
and when the slaves start doing other tasks.

Since getting this through put, I have changed my architecture so that I have my master implemented on a Mini Pro and doing nothing else but reading slaves & shuffling the data around to other slaves.
The master also does some scheduling so that slaves can be read at varying intervals rather than one after each other whether they need to be updated or not.

Lee VK3PK

   
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rexlee on May 03, 2016, 12:57 am
Hello everyone!

I am using RS485 Shield for Arduino Uno. When I run my program to read from a slave modbus sensor, I see the data being sent from TX pin but the output of RS485 shield does not make sense and it is only pulse.

My understanding is that they must be identical data except the voltage level is different, am I correct?
If the output is not right, I need a new RS485 shield?

Thanks in advance!


Here is a link to the RS485 shield I am using
http://store.linksprite.com/rs485-shield-for-arduino-v2-1/#ProductReviews

Pay attention to the termination resistor & bias resistors.  On one batch of boards I had to change the bias
resistors because they had values which were not biassing correctly.
It is hard to blow up a RS485 transceiver, so you should not need to replace them.

Lee VK3PK     




Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: hajihosseinlu on May 03, 2016, 06:47 pm
Hi Guys,


Why when connecting oscilloscope probe to the differential voltage (A B modbus rs485) it destructs the signal !??

What can be done that the probe shows actual voltage levels?

Thanks,
Amin
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: hajihosseinlu on May 04, 2016, 12:08 am
Hello All, please HELP I really need help with this project.


I have a sensor connected to the arudino. I have set up max485.

I want to read only one parameter (for now) form a modbus sensor. The modbus sensor is set up at

address=1
baud rate= 19200,
Odd parity,

I have used several codes I found in this forum, I can see the data is being send to the sensor but I do not receive any data.


I have used the following code;

I have tried other codes as well.
I have connected pin 2 of the arduino uno t RE DE. There is a 100 ohm resistor between A and B of the sensor. I just need to read a value from the sensor.



#include <SimpleModbusMaster.h>

 

// led to indicate that a communication error is present
#define connection_error_led 13

//////////////////// Port information ///////////////////
#define baud 19200
#define timeout 100
#define polling 200 // the scan rate

// If the packets internal retry register matches
// the set retry count then communication is stopped
// on that packet. To re-enable the packet you must
// set the "connection" variable to true.
#define retry_count 100000

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  PACKET2,
  // leave this last entry
  TOTAL_NO_OF_PACKETS
};

// Create an array of Packets for modbus_update()
Packet packets[TOTAL_NO_OF_PACKETS];

// Create a packetPointer to access each packet
// individually. This is not required you can access
// the array explicitly. E.g. packets[PACKET1].id = 2;
// This does become tedious though...
packetPointer packet1 = &packets[PACKET1];
packetPointer packet2 = &packets[PACKET2];

// The data from the PLC will be stored
// in the regs array
unsigned int regs[9];

void setup()
{
  // read 3 registers starting at address 0
  packet1->id = 1;
  packet1->function = READ_HOLDING_REGISTERS;
  packet1->address = 0;
  packet1->no_of_registers = 3;
  packet1->register_array = regs;
 
  // write the 9 registers to the PLC starting at address 3
  packet2->id = 1;
  packet2->function = PRESET_MULTIPLE_REGISTERS;
  packet2->address = 3;
  packet2->no_of_registers = 9;
  packet2->register_array = regs;
// 
  // P.S. the register_array entries above can be different arrays
 
  // Initialize communication settings etc...
  modbus_configure(baud, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
 
  pinMode(connection_error_led, OUTPUT);
}

void loop()
{
  unsigned int connection_status = modbus_update(packets);
 
  if (connection_status != TOTAL_NO_OF_PACKETS)
  {
    digitalWrite(connection_error_led, HIGH);
    // You could re-enable the connection by:
    //packets[connection_status].connection = true;
  }
  else
    digitalWrite(connection_error_led, LOW);
 
  // update the array with the counter data
  regs[3] = packet1->requests;
  regs[4] = packet1->successful_requests;
  regs[5] = packet1->total_errors;
  regs[6] = packet2->requests;
  regs[7] = packet2->successful_requests;
  regs[8] = packet2->total_errors;
}
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: jose_francisco on May 06, 2016, 11:37 am
Hi.
Where can I find latest versions of this libraries?
I can't find Juan Bester's libraries.
Thanks.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: fiete_02 on May 09, 2016, 09:43 pm
Hi,

this is no request for help - which is obviously rare for a newbie in this thread. I only would like to share my experiences with building up a network with several slaves and a master communicating via RS485 Simple Modbus protocoll.
After quite some hours of reading through these 39 pages with more than 570 postings I found it somehow confusing. In the first half of the postings I tried to learn from the posted examples but my IDE compiler came up with errors like " 'packetPointer' does not name a type " and other errors. It took me quite some time to sort out, that not all of the compiler errors came from my stupid programming. I fiqured out, that any posting in this thread before Sept,15 2014 have been build on libraries, which were not compatible with the latest SimpleModbus libraries (Master lib V2rev2 and Slave lib V10), which I downloaded und used in my IDE.

After this was understood, I concentrated on postings past Sept 2014 but JuanB very often referred to earlier postings, so I had to go back and forth, which was even more confusing, as it did explain things which didn't work with the latest libraries.

The wonderful illustrated posting #294 from "JUGmobile" as well as the posting #351 from "les_well" were finally eye opening for me as a newbie and I can only recommend for any newcomer to read through these two postings carefully as well as through the manual, which comes with the latest master library V2rev2. The manual from JuanB is excellent, no question. But it is most useful, if you have somehow some clue about the concept of the SimpleModbus library before.

I was struggling the most with the modbus_construct() function, especially with the last 3 parameters. Posting #351 clarified this for me and since then, the realization of my home automization project advanced without further issues. The FSM (finite state machine) within the SimpleModbus library is not really necessary for my application but I could work around by switching on and off the communication of each PACKET and could realize a system, which polls the slaves only, when the master needs to send data to or request data from the slaves. A nice feature is also, if you have several slaves, to ensure identical slave holdingRegs[] registers, so that you can broadcast to slaves and sending specific data to all of them at the same time. Very usefull to send e.g. 2 register integers who represent the unix-time from the master. One hint in this token : The integer in the holdingRegs[] are signed integer, so you have to convert them in unsigned integers before combining into an unsigned long. This took me a while to find the root cause for the wrong time, the slaves received from the master.

Not seeing, what is really transferred on the RS485 bus, I found my "Modbus Traffic Analyzer" very helpful. It is a Mega2560 "listening" to the SimpleModbus and posting the telegrams (packets) detected together with a timestamp (hh:mm:ss.millis) to the Serial Monitor.
With this tool, it is easy to adjust the polling variable and you can see, if responses were incorrect or missing.
If someone is interested in this tool, feel free to ask.

All in all I can really recommend using the latest SimpleModbus libraries. With 100 thousands of requests I had not a single "failed request" at 38400 baud RS485 communication. My master is a Mega256, the slaves are ProMini with software serial for monitoring and Serial Tx0, Rx1 for RS485.

I use the following RS485 breakout boards, which are widely available at very low cost (about 1€ each).
(http://i.ebayimg.com/t/MAX485-RS-485-TTL-MAX485CSA-AVR-Schnittstellen-Adapter-fuer-Arduino-Raspberry-pi-/00/s/NjYwWDgwMA==/z/KkQAAOSwwPhWlOY6/$_57.JPG)
but you have to remove the R7 resistor with 120 Ohm between A and B, which is unfortunately surface mounted on each breakout board and should only be used for the first and last device on the whole RS485 bus. Pullup/pulldown resistors with 1kOhm have to be used at the master side at A und B, if the RS485 bus is longer than a few feet.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: fiete_02 on May 12, 2016, 02:35 pm
Hi.
Where can I find latest versions of this libraries?
I can't find Juan Bester's libraries.
Thanks.
Hi Jose,

they are on google-drive posted by JuanB

https://drive.google.com/folderview?id=0B0B286tJkafVSENVcU1RQVBfSzg&usp=drive_web

Have fun !
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tobentobi on May 27, 2016, 01:58 pm
Dear All,

after days of trying i need help with this libary while reading out a max6675 via spi.
modbus is working well with my master and the spi function works, if i try it in serial monitor without modbus.
but both together, spi data will be read out once after startup. then no more actual values. no prob with other values, only with spi.

its "working" with both delays before and after modbus poll like this:
Code: [Select]

void loop() {

 delay(100);      
 modbus_update();
 delay(100);
                             
 holdingRegs[WMOD0_TEMP_EXTR]=Read_Extr();  
}
uint16_t Read_Extr(){
digitalWrite(CSEXTR, LOW);
 delayMicroseconds(20);        // zusätzliche Wartezeit, 100ns erforderlich
 SPI.begin();
 uint16_t reading = SPI.transfer16(0);
 
 digitalWrite(CSEXTR, HIGH);
 SPI.end();
 if (reading & 0x0004){// sensor disconnected
     reading = -1;
 }
 else {
     reading = (reading >>3)*25;  // the reading is in bits 14..03, get rid of bit 2,1,0
 }
 return reading;      
}


poll time in master is 500ms but this all makes transfer buggy and slow.

could anyone help me?

regard, Tobi
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on May 27, 2016, 02:19 pm
Welcome Tobi to the forums.

First, it is better if you provide all of your code so we can see that you have set initial parts correctly.

In your main loop() remove the delay(x) statements and use a non-blocking timing method to call your Read_Extr() function so that the Modbus state machine can be checked continuously.

Check also read up on the SPI usage here (https://www.arduino.cc/en/Reference/SPIBegin).
You will see that you will normally want to place the SPI.begin() at the start of your program, not in a function that gets called all the time.

Same with SPI.end(), in fact, you may remove this altogether.
I expect when you move SPI.begin() to the start up section of your program, you can also remove the additional delatMicroseconds(20), as it should not be needed, unless your SPI hardware the Arduino is talking to is slow.

Remember, the Modbus master will be expecting a response from the slave, and so if you place any significant delays in your program, the slave may not respond in a timely manner for the master.

For timing, look at simple examples like blink without delay, and make use of this concept in all your programs.
_____________
Paul - VK7KP
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tobentobi on May 27, 2016, 03:54 pm
Thanks for your reply, Paul!
Think i've already all that what you wrote.
I have just shortened my code with only the basic things.
Doesn't work at all. SPI will only read once at startup. Also if I call the modbys within the "delay".

Code: [Select]

#include <SimpleModbusSlave.h>
#include <SPI.h>

enum
{     
  WMOD0_TEMP_EXTR,                 
  HOLDING_REGS_SIZE
};
unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array           
unsigned long prevMillis = 0;        // will store last time LED was updated

int CSEXTR= 9; // D09: Chipselect MAX6675 Extruder
const long chktemp = 100;
/*
============
=  I N I T =
============
*/
void setup() {
  // Pins deklarieren                   
  pinMode(CSEXTR, OUTPUT);       // CS-Pin Extruder als Output
  digitalWrite(CSEXTR, HIGH);    // CS-Pin Extruder auf High
 
  // Init Modbus
  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);
  modbus_update_comms(9600, SERIAL_8N2, 1);
 
  // Init SPI 
  SPI.setClockDivider(SPI_CLOCK_DIV2);  // wären 8 MHz SPI Takt
  SPI.setDataMode(SPI_MODE0);           // DataMode 0
  SPI.begin(); 
}
/*
============
=  M A I N =
============
*/
void loop() {
  modbus_update();
 
  unsigned long actMillis = millis();
  if (actMillis - prevMillis >= chktemp) {
      prevMillis = actMillis;                             
      digitalWrite(CSEXTR, LOW);
      delayMicroseconds(0);        // zusätzliche Wartezeit, 100ns erforderlich
      uint16_t reading = SPI.transfer16(0);
      digitalWrite(CSEXTR, HIGH);
      reading = (reading >>3)*25;  // the reading is in bits 14..03, get rid of bit 2,1,0
      holdingRegs[WMOD0_TEMP_EXTR]=reading;    // READ MAX6675 1           
  }           
}


Maybe more ideas?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on May 27, 2016, 04:17 pm
Tobi, you wrote:
Quote
Think i've already all that what you wrote.
But it makes no sense to me.
Also, what do you mean when you say
Quote
Also if I call the modbys within the "delay".
Also what ?

Remove the line that is
Code: [Select]
modbus_update_comms(9600, SERIAL_8N2, 1);It is just replicating the line above. This statement is for when you need to change Modbus settings during run-time.

Use your diagnostic skills, get your SPI working by itself reliably first.
So, comment out the modbus_update() function and make your program get the SPI data every one second and send that out the serial port to your computer so you can see it is working. Make sure you set the serial_begin correctly and no modbus code.

One you have proved the SPI code to function, then re-insert your Modbus code.
_____________
Paul - VK7KPA
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tobentobi on May 27, 2016, 04:35 pm
But as I said: SPI function works, if i try it in serial monitor without modbus. No Prob!

that doesn't work:

Code: [Select]
void loop() {
   unsigned long actMillis = millis();
    if (actMillis - prevMillis >= chktemp) {
      prevMillis = actMillis; 
    modbus_update();
   }
 
                           
      digitalWrite(CSEXTR, LOW);
      delayMicroseconds(0);        // zusätzliche Wartezeit, 100ns erforderlich
      uint16_t reading = SPI.transfer16(0);
      digitalWrite(CSEXTR, HIGH);
      reading = (reading >>3)*25;  // the reading is in bits 14..03, get rid of bit 2,1,0
      holdingRegs[WMOD0_TEMP_EXTR]=reading;    // READ MAX6675 1           
           
}


Init looks now like this:

Code: [Select]
 
// Init Modbus
  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);
 // modbus_update_comms(9600, SERIAL_8N2, 1);



But It works like this (but slow and ugly):

Code: [Select]
void loop() {
   delay(100);
    modbus_update();
    delay(100);
   
 
                           
      digitalWrite(CSEXTR, LOW);
      delayMicroseconds(0);        // zusätzliche Wartezeit, 100ns erforderlich
      uint16_t reading = SPI.transfer16(0);
      digitalWrite(CSEXTR, HIGH);
      reading = (reading >>3)*25;  // the reading is in bits 14..03, get rid of bit 2,1,0
      holdingRegs[WMOD0_TEMP_EXTR]=reading;    // READ MAX6675 1
}


Hmmmm... Sorry, but I tried more than 2 days before asking stupid question. Im looking foreward for more ideas. Thanks!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on May 27, 2016, 04:57 pm
Okay, you did mention you tried SPI without Modbus code, sorry, I read too quickly.

The code at post #585 looks to me to be good.
You might like to try increasing the time period you read the SPI device, from 100mSec to 1000 or 2000mSec.

There is probably little point in reading it faster than what you are getting it with the Modbus master in reality.

I checked the MAX6675 specifications PDF, and it is not a complicated chip to work with, so it should work quite well.

But what ever you do, avoid using delay(x) where x is longer than 10mSec.
With good coding, you should not need to ever use delay(x), there is always something the CPU can do :)
__________
Paul - VK7KPA
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: mavinrya on May 27, 2016, 05:10 pm
Good day!

I am currently working on this set-up:
  - Arduino Mega as the modbus master (using RS 485)
  - several Eastron Meters as slaves (model: SDM630)

As an initial step, I tried to compile and upload the code provide by JuanB to Sbeghers (found in page 13 eastron_sdm320mv4.ino). Sbeghers confirmed that this code worked. A few modifications on the code would eventually make communication with SDM630 possible. However i am faced with the following errors even though i have not made any modifications yet on the original code. What i did was just to open the file and compile.

Code: [Select]

/Users/mcbathan/Documents/Arduino/Eastron_SDM320Mv4/Eastron_SDM320Mv4.ino: In function 'void setup()':
Eastron_SDM320Mv4:39: error: 'modbus_construct' was not declared in this scope
   modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0, 2, readRegs);
                                                                      ^
Eastron_SDM320Mv4:41: error: invalid conversion from 'HardwareSerial*' to 'long int' [-fpermissive]
   modbus_configure(&Serial1, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
                                                                                                                        ^
/Users/mcbathan/Documents/Arduino/Eastron_SDM320Mv4/Eastron_SDM320Mv4.ino:41:120: warning: large integer implicitly truncated to unsigned type [-Woverflow]
Eastron_SDM320Mv4:41: error: invalid conversion from 'int' to 'Packet*' [-fpermissive]
Eastron_SDM320Mv4:41: error: too many arguments to function 'void modbus_configure(long int, unsigned int, unsigned int, unsigned char, unsigned char, Packet*, unsigned int)'
In file included from /Users/mcbathan/Documents/Arduino/Eastron_SDM320Mv4/Eastron_SDM320Mv4.ino:1:0:
/Users/mcbathan/Documents/Arduino/libraries/SimpleModbusMaster/SimpleModbusMaster.h:143:6: note: declared here
 void modbus_configure(long baud, unsigned int _timeout, unsigned int _polling,

      ^
/Users/mcbathan/Documents/Arduino/Eastron_SDM320Mv4/Eastron_SDM320Mv4.ino: In function 'void loop()':
Eastron_SDM320Mv4:46: error: too few arguments to function 'unsigned int modbus_update(Packet*)'
   modbus_update();
                 ^
In file included from /Users/mcbathan/Documents/Arduino/Eastron_SDM320Mv4/Eastron_SDM320Mv4.ino:1:0:
/Users/mcbathan/Documents/Arduino/libraries/SimpleModbusMaster/SimpleModbusMaster.h:142:14: note: declared here
 unsigned int modbus_update(Packet* packets);

              ^
Multiple libraries were found for "SimpleModbusMaster.h"
 Used: /Users/mcbathan/Documents/Arduino/libraries/SimpleModbusMaster
 Not used: /Users/mcbathan/Documents/Arduino/libraries/SimpleModbusMasterV2rev2
exit status 1
'modbus_construct' was not declared in this scope



Im very new to programming and need your help to decipher what went wrong or what i did wrong. Below is the code provided by JuanB (eastron_sdm320mv4.ino):

Code: [Select]

#include <SimpleModbusMaster.h>


//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate

#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2

enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

packetPointer packet1 = &packets[PACKET1];

unsigned int readRegs[2];

unsigned long currentMillis;
long previousMillis = 0;
long interval = 1000;


void setup()
{
  // read 2 registers starting at address 0 
  // This is the Line to neutral voltage
  // The value received needs to be transposed to floating value
  modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0, 2, readRegs);
 
  modbus_configure(&Serial1, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
}

void loop()
{
  modbus_update();
 
  // shift and cast value to float
  float voltage;
  unsigned long temp = (unsigned long)readRegs[0] << 16 | readRegs[1];
  voltage = *(float*)&temp;
 
  // use the following code to avoid using delay()
  currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  {
    Serial.print("Low byte: ");
    Serial.println(readRegs[0]);
    Serial.print("High byte: ");
    Serial.println(readRegs[1]);
    Serial.print("Voltage: ");
    Serial.println(voltage);
    Serial.println("********");
    previousMillis = currentMillis;
  }
}


Would very much appreciate your help on these. Thank you in advance.

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tobentobi on May 27, 2016, 05:37 pm
Thanks once more for your reply rockwallaby,

I am not at home at the moment and can not try.
To be honest, i am new in C - in real live i am Siemens  PLC Programmer.
Quote
There is probably little point in reading it faster than what you are getting it with the Modbus master in reality 
I can adjust the poll time in the Master, but increasing from 25ms to 1000 makes no different at all. I also tried with enable/disable interrupts and with disabling, i get a receive timeout. Im not sure if there could be the problem  that spi uses interrupts?

Greetz, Tobi
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: tobentobi on May 27, 2016, 07:32 pm
@rockwallaby
Quote
You might like to try increasing the time period you read the SPI device, from 100mSec to 1000 or 2000mSec.
Yeeeeeaaaaah Dude - you made my day! Increasing the period to 300 (not less) works fine for me!
I don't know why and that is a little bit sad, but there are enough other problems with other things.
So, that should be good and i can live with that.

Many THX 4 support and greetings!!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on May 28, 2016, 01:34 am
Hi Tobi, you are welcome.
Yes, in my other life, I too am a industrial systems engineer, have designed with S7 PLCs, but mostly use Allen Bradley PLC, with SCADA.

Anyhow, I'm happy you have made some progress, I know it can be frustrating when things look correct, but do not work.
The same can happen with hardware as well.

Have fun with your project now :)
_____________
Paul - VK7KPA
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on May 28, 2016, 01:51 am
mavinrya, it appears to me you are using code that was developed for older libraries.

If so, you can use the code you have with the libraries of that time, or use up to date libraries with corrected code.
Please read the SimpleModbus manual, it is all explained in there.
___________
Paul - VK7KPA
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: lvino on May 28, 2016, 04:05 am
hi guys
i have power meter pm800 schneider i want to connect it with arduino using rs485 port in power meter, but  i have no idea to wiring (+) and (-) in communication port in power meter, port (+) to A or to B in max485

(https://mail.google.com/mail/u/0/?ui=2&ik=228d23ef32&view=att&th=154f528b9dee1921&attid=0.1&disp=safe&realattid=f_ioqj42mh1&zw)

i googling and then i found this in wattmetrics.com but still i dont understand

Agent COM1 or COM2     Color                              Function       PM800 (COM1)
485+                           white w/orange stripe       data (B) +    D1+ (20)
485-                            orange                           data (A) -     D0- (19)
GND                            brown                            common       [gnd symbol] (18)

thank you srry for my bad english....
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on May 28, 2016, 08:00 am
Ivino, you need help with understanding on how to search effectively online.

I simply put in my search the following:
Quote
RS-485 wiring schneider PM800
Then from the very first in the list I get the following link:RS-485 wiring PM800 (http://www2.schneider-electric.com/resources/sites/SCHNEIDER_ELECTRIC/content/live/FAQS/177000/FA177526/en_US/PM800%20DataSheet.pdf)

Start looking from page 13 and it details how to connect RS-485 to the PM800.

When giving details on this forum, please provide clear and detailed information about what you are actually using. We have no idea what Arduino or EIA-485 interface you are using.

Please spend a few extra minutes in making your post on this forum as detailed as you can, provide links or images to tell us what you have and are trying to do.

Also, do you see your table above, it's a mess, why do you not tidy it up so it looks readable ?
___________
Paul - VK7KPA
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: lvino on May 29, 2016, 06:04 am
Ivino, you need help with understanding on how to search effectively online.

I simply put in my search the following:Then from the very first in the list I get the following link:RS-485 wiring PM800 (http://www2.schneider-electric.com/resources/sites/SCHNEIDER_ELECTRIC/content/live/FAQS/177000/FA177526/en_US/PM800%20DataSheet.pdf)

Start looking from page 13 and it details how to connect RS-485 to the PM800.

When giving details on this forum, please provide clear and detailed information about what you are actually using. We have no idea what Arduino or EIA-485 interface you are using.

Please spend a few extra minutes in making your post on this forum as detailed as you can, provide links or images to tell us what you have and are trying to do.

Also, do you see your table above, it's a mess, why do you not tidy it up so it looks readable ?
___________
Paul - VK7KPA
thank you for ur answer

my project are :
-Arduino Mega 2560 act as Master
-Power Meter Schneider PM800 act as Schneider-i want to read Voltage in Input Register address 1120 and publish it in serial monitor (just for now) u can see register list in attachment

now my problem i cant read my register i just got value 0.0 like this :

Code: [Select]
test
0.0
requests: 1
successful_requests: 0
failed_requests: 0
exception_errors: 0
connection: 1


and this is my sketch

Code: [Select]
#include <SimpleModbusMaster.h>

/*
   The example will use packet1 to read a register from address 0 (the adc ch0 value)
   from the arduino slave (id=1). It will then use this value to adjust the brightness
   of an led on pin 9 using PWM.
   It will then use packet2 to write a register (its own adc ch0 value) to address 1
   on the arduino slave (id=1) adjusting the brightness of an led on pin 9 using PWM.
*/

//////////////////// Port information ///////////////////
#define baud 38400
#define timeout 1000
#define polling 400 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 3

#define LED 9

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 12

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
 // PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
  // Initialize each packet
  Serial1.begin(38400);
  Serial.begin(19200);
  modbus_construct(&packets[PACKET1], 1, READ_INPUT_REGISTERS, 1125, 1, 10);
 // modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
 
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial1, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
 
}

void loop()
{
  modbus_update();

 
  unsigned long temp;

  float Voltage;
  temp = (unsigned long) regs[10] << 16 | regs[11];
  Voltage = *(float*)&temp;
  Serial.println("test");
  Serial.println(Voltage, 1);

  Serial.print("requests: ");
    Serial.println(packets[PACKET1].requests);
    Serial.print("successful_requests: ");
    Serial.println(packets[PACKET1].successful_requests);
    Serial.print("failed_requests: ");
    Serial.println(packets[PACKET1].failed_requests);
    Serial.print("exception_errors: ");
    Serial.println(packets[PACKET1].exception_errors);
    Serial.print("connection: ");
    Serial.println(packets[PACKET1].connection);
 
}


u can see my schme in attachtment, maybe u want to fix my hardware

i buy rs485 to ttl like this :
(http://mlb-d2-p.mlstatic.com/en-eletronicos-798101-MLB20278798777_042015-Y.jpg)

and i also attach my power meter setting

thank you
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: fiete_02 on May 30, 2016, 09:27 pm
Ivino, according to your scheme1 you do not use additional pullup / pulldown resistors between line A, VCC and B, GND. Your breakoutboard has already 20k resistors, but it is highly recommended to go for somewhat like 1kOhm pullup and pulldown. See also https://en.wikipedia.org/wiki/RS-485

(https://upload.wikimedia.org/wikipedia/commons/thumb/9/96/Rs485-bias-termination.svg/300px-Rs485-bias-termination.svg.png)

I would try to put in addition (to the breakout board) 1kOhm between GND and B as well as 1kOhm between VCC and A.

Termination have been taken care by the breakout board (120 Ohm on board) as well as by your slave (most likely - better check in their specs).

If you have done this, at least you are sure, that there is no issue with the electrical specifications of the RS485 bus.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: lvino on May 31, 2016, 02:05 am
thank you fiete_02

i didnt do that, i will try it
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: lvino on May 31, 2016, 02:22 am
thank you fiete_02

i didnt do that, i will try it

edit :

so i must remove r5 and r6 ? and change it wit 1kohm resistor?

(http://www.sunrom.com/media/content/981/rs485-ttl-schematic.gif)



Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: fiete_02 on May 31, 2016, 10:43 pm
No, that wouldn't make much sense. According to Ohm's law, you can reduce a resistor by putting a resistor in parallel. So don't remove R5 and R6 but put additional 1kOhm in parallel between A -> VCC  and B -> GND which results in about 950 Ohm (much better than 20kOhm). This is much easier than repairing the SMD resistors.

If you like to be perfectly correct, put 750 Ohm in parallel to R5 and R6 which results in 722 Ohm which is really close to the optimal 680 Ohms.
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: juanluis3009 on Jun 07, 2016, 01:29 am
Hi all,
Congratulations for this library and for the support.
I read the previous (600  :o ) posts and I don't see answer to my question.

I will try to explain:

I have a unique slave (ID1), let call it "machine", reading address0 from master we can know if the machine is On or Off, sending a packet like:

Code: [Select]

 modbus_construct(&packets[PACKET0], 1, READ_HOLDING_REGISTERS, 0,1, 0);


The machine has a pannel, from where user can manually turn it On or Off, and this state  will be monitored in the master.

But also, from the master I want to turn the machine on or off writing in the bus a packet like:


Code: [Select]

 modbus_construct(&packets[PACKET1], 1, PRESET_MULTIPLE_REGISTERS, 0,1, 1);



I need send this last packet ONLY ONCE (when I want force the machine to On or Off).


Do someone know if is this supported by the library in some way?
In other words, read an address and eventually write the same address (in the same slave)

Thanks
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: fiete_02 on Jun 07, 2016, 01:23 pm
Hi Juanluis,

the reason, why you have not seen some answers to your issue (writing once) is pretty simple : The modbus library have been written mainly to frequently read sensors on a modbus thus there are routines in the library which make it easy to poll sensors and get their current readings.

But you can use the library to do what you want it to do :

* Use 2 packets for reading and writing (as you have done in your example).
* disconnect the packet1 as long as you don't need to write to the registers of your "machine"
* call modbus_update() at least once in your loop()
* if you want to write to your "machine", reconnect packet1 and check, if request was successful (successful_requests of packet1 increased by 1), then disconnect the packet1 again.

If you do not know, how to disconnect and reconnect, have a look at the SimpleModbusMaster manual, which comes with the latest library V2rev2.

Maro
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jun 07, 2016, 02:03 pm
Juanluis, welcome to the forum.

First, you say
Quote
I have a unique slave (ID1), let call it "machine", reading address0 from master we can know if the machine is On or Off, sending a packet like:
You are describing that the slave reads data from the master, this can not happen, only the master can initiate any form of data transfer, not the slave. So, only the master can send data from its address0 to the slave.

Try to remember that the master is in control of everything, with the slaves only existing as mail boxes, the master is the postman.

For what you want to do, you need the master to read the slave data and then combine the machine state with the master command machine state and send that back to another address in the slave. Then have some logic in the slave that reads the master command and act on that.

You need to work out which end, slave or master will have priority of control of machine state, which has nothing to do with Modbus and which is Modbus slave or master.

Maro, you write:
Quote
The modbus library have been written mainly to frequently read sensors on a modbus thus there are routines in the library which make it easy to poll sensors and get their current readings.
What utter rubbish, sorry to say.
The Modbus protocol was initially used in industrial automation, way back in the 1970's, which is what I do for many years now, and is used as a means to connect devices, whether that be PLCs or computers or remote I/O over a common and well defined and rugged data protocol. The Modbus protocol is now an open data protocol and has gained increasing attention and popularity in recent years, with many device manufactures now implementing some form of Modbus connectivity, usually RTU or TCP.

The use of Modbus in the Arduino world to achieve the same, and hence a Modbus library for Arduino style boards.
There are many Modbus libraries for all sorts of platforms and in many different languages, C, C++, Python, NodeJS, even PHP. There are even a number of Modbus libraries for Arduino boards, with this one being of the RTU variety.

It is not true or accurate to say it was written 'mainly' to read sensors. Sensors are sensors and on the whole, not many have this form of integrated communications as part of the sensor. Typically, you will connect a sensor to a device that accepts a sensor such as 4-20mA input and provides a communications channel, such as Modbus.
____________
Paul - VK7KPA
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: juanluis3009 on Jun 07, 2016, 04:27 pm
Hi Maro,
Thanks for answering.

* Use 2 packets for reading and writing (as you have done in your example).
* disconnect the packet1 as long as you don't need to write to the registers of your "machine"
* call modbus_update() at least once in your loop()
* if you want to write to your "machine", reconnect packet1 and check, if request was successful (successful_requests of packet1 increased by 1), then disconnect the packet1 again.

Eventually ,I will write a function for the library to do something like that ..

Regards
Juan
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: juanluis3009 on Jun 07, 2016, 04:50 pm
Hi rockwallaby, Thanks for your interest.

First, you sayYou are describing that the slave reads data from the master, this can not happen, only the master can initiate any form of data transfer, not the slave. So, only the master can send data from its address0 to the slave.
Sorry it was a misunderstanding,  I did not explain it properly.
I wanted to say

Quote
I have a unique slave (ID1), let call it "machine". 
Reading address0 from master we can know if the machine is On or Off, sending a packet like:
I meant master reads slave.



Quote
The modbus library have been written mainly to frequently read sensors on a modbus thus there are routines in the library which make it easy to poll sensors and get their current readings.
What utter rubbish, sorry to say.
I think Maro meant that this library (simpleModbusMaster) has been written mainly for read sensor. He was not blaming the Modbus itself.  ;)

Thanks again for your answer.
Regards
Juan


Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: rockwallaby on Jun 07, 2016, 05:01 pm
Juan,

No, that is not necessarily correct at all, you can not say that this Arduino library was written 'mainly for read sensor' or as Maro wrote, 'mainly to frequently read sensor'. Have you spoken to the library author to know why it was written ?

All anybod can say is that this Arduino was written to allow people to use the Modbus RTU protocol, regardless of devices used. It has nothing to do with sensor or sensors, although that may be what some people use it for, to transfer the data supplied by sensors. Others may use it for all sorts of other data, such as control of equipment, as in on/off or setpoint control to end devices.
____________
Paul - VK7KPA
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: juanluis3009 on Jun 11, 2016, 09:46 am
Hi,
I made some changes in the library for fit my needs.
Now I can send only one time the packet:
Code: [Select]

void setup(){
...
 modbus_construct(&packets[PACKET1], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 1);
  packet_Off(packets[PACKET1]);
...
}
void loop(){
  modbus_update();
if (something_happens) packet_Once(packets[PACKET1]);
...
}


every time we call packet_Once(packets[PACKET1])  it will be sent once and then it will be disable.

Besides I added a option for reentry forever a packet. Which means it will never be disable because of error transmission. So far, if master loses conection  with a slave for a wile, once the limit of retries are done, the conection is disable, and never try again (unless you reconnect from the master).

Code: [Select]

  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 1, 0);
  enable_retriesForever(packets[PACKET1]);



https://www.dropbox.com/sh/kup5ij0dwqb7dwe/AAATDdLqXia7kDuW7E9Ii0Sa?dl=0
 (https://www.dropbox.com/sh/1hn27wy0ao3rcv5/AAC9GEuXNOq0OKhFGMNV3o_ea?dl=0)
regards
Juan
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: lvino on Jun 12, 2016, 07:51 am
THANKSSS NOW IT WORKED !!

i just add external pullup/pulldown resistor 1kohm and then it show value what i need
but now my problem is i get 0 value before get value what i needed

liket this

Code: [Select]
Voltage L-N :0.00
0.00
0.00
Voltage L-N :225.00
0.00
0.00
Voltage L-N :225.00
0.00
0.00
Voltage L-N :225.00
0.00
0.00
Voltage L-N :225.00
225.00
0.00
Voltage L-N :225.00
225.00
0.00
Voltage L-N :225.00
225.00
0.00
Voltage L-N :225.00
225.00
225.00
Voltage L-N :225.00
225.00
225.00


and this is my sketch

Code: [Select]
#include <SimpleModbusMaster.h>
//////////////////// Port information ///////////////////
#define baud 19200
#define timeout 100
#define polling 10 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2
// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 13

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
 // PACKET2,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
  // Initialize each packet
  Serial.begin(19200);
  modbus_construct(&packets[PACKET1], 1, READ_INPUT_REGISTERS, 1123, 1, 10);
  modbus_construct(&packets[PACKET2], 1, READ_INPUT_REGISTERS, 1125, 1, 11);
  modbus_construct(&packets[PACKET4], 1, READ_INPUT_REGISTERS, 1127, 1, 12);
 // modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 0);
 
  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial1, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
 
}

void loop()
{
  modbus_update();
  unsigned long temp;
  float Voltage, Voltage1, Voltage2;
  Voltage = regs[10];
  Voltage1 = regs[11];
  Voltage2 = regs[12];
 Serial.print("Voltage L-N :");
 Serial.println(Voltage);
 Serial.println(Voltage1);
 Serial.println(Voltage2);
  //Serial.println(regs[13]);
  delay(1000);
 

 // Serial.print("requests: ");
   // Serial.println(packets[PACKET1].requests);
    //Serial.print("successful_requests: ");
    //Serial.println(packets[PACKET1].successful_requests);
   // Serial.print("failed_requests: ");
   // Serial.println(packets[PACKET1].failed_requests);
   // Serial.print("exception_errors: ");
   // Serial.println(packets[PACKET1].exception_errors);
   // Serial.print("connection: ");
   // Serial.println(packets[PACKET1].connection);
 
}


EDITED :
Sry i didnt read previous post now it resolved , just change delay()
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: berbe01 on Jun 17, 2016, 08:14 pm
(http://i.ebayimg.com/t/MAX485-RS-485-TTL-MAX485CSA-AVR-Schnittstellen-Adapter-fuer-Arduino-Raspberry-pi-/00/s/NjYwWDgwMA==/z/KkQAAOSwwPhWlOY6/$_57.JPG)

Hi all..

How can i found this rs485 modul's fritzing part file? (.fzp or .fzpz)

Can u give download link or share from here?

Thanx..
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: imam22ii on Jun 27, 2016, 09:39 am
hi all,
im newbie here, i need help please,

i have a tools energy meter SPM91 DIN Rail single phase energy meter with specification like this :
1. 35mm DIN installing, in accordance with standard DIN ED50022
2. high accuracy, active energy accuracy up to class 1
3. measure and display V,I,P,kWh value
4. 6+1 digits LCD display (999999.9 kWh)
5. passive pulse output, output signal is in accordance with standard DIN43864
6. LED indicates pulse
7. key-press for local prameter setting
8. RS485 communication port, modbus-rtu protocol


I want to get value added to arduino, but i dont know how to make program for it, 

I know all the master arduino gathered here, please guide me how to get the value for send to arduino, please  :'(  :'(

this image energy meter i use,
(https://ecs7.tokopedia.net/img/product-1/2015/9/9/460050/460050_0aa68855-7b5f-4ccc-9ab8-1c4d04ca3b12.png)

https://ecs7.tokopedia.net/img/product-1/2015/9/9/460050/460050_6499969a-2e50-4c15-bfc7-f68484076780.png
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: neoguru on Jul 20, 2016, 11:53 pm
I have problem getting requests, successful_requests, failed_requests, exception_errors, retries and connection attributes.
What is the easiest way to get these attributes?
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: fiete_02 on Jul 25, 2016, 06:35 pm
Hi neoguru,

it's really easy :

unsigned int a = packets[PACKET1].requests;     // variable a holds now the number of requests
unsigned int b = packets[PACKET1].connection;  // variable b holds now connected = 1 or not connected= 0
unsigned int c = packets[PACKET1].failed_requests;  // variable c holds now number of failed requests

You can do that with all or your attributes, you mentioned in your post and all of your PACKETx .

Hope this is of help for you.

Maro
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: neoguru on Jul 25, 2016, 10:17 pm
Hi fiete,

Thank You very much for you reply. Now I can access all those attributes, but they all all ZERO's even when I disconnect slaves or master from RS485 module. I'm still not sure if I'm doing right with:
Code: [Select]
unsigned int local_start_address parameter in modbus_construct() function. I have set it to 0 but i'm not sure what this number represents while reading SimpleModbusMaster PDF manual.

Thank You
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: fiete_02 on Jul 26, 2016, 08:52 am
Hi neoguru,

could you pls do the following, before I can give you the right advises :

* check the version of your SimpleModbusMaster and SimpleModbusSalve libraries. Master should be V2rev2 and Slave V10

* explain, what you would like to achieve in general with your application

* what RS485 hardware do you use both on master and slave side and how did you connect them (RS485 bus)

* what Arduino hardware (Uno, Mega2560, Due ..) are you using for the Master and what serial port you are using to connect to the RS485 hardware

* post the part of your Master sketch, where you define
   - serial connection to RS485 hardware
   - TOTAL_NO_OF_REGISTERS
   - Paket creation   enum { }
   - modbus_construct ()
   - modbus_configure ()

Without these information it would be only a guessing around.


Maro
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: neoguru on Jul 26, 2016, 11:36 am
Hi Maro,

* Version of SimpleModbusMaster library is V2rev2 and slave is V10.

* What I'm trying to achieve is to have variables for holding requests, failed_requests, etc. so i can monitor performance of RS485 bus which will be distributed over 40 meters containing 3 Arduinos. Arduinos will exchange temperature readings from DS18B20 sensors.

* Hardware for RS485 is RS485 to TTL breakout board same as Your's in post #581 in this topic and connected in daisy chain configuration. Network consists of Arduino Mega2560 as master, Arduino UNO and Arduino NANO as slaves.

*  Master Arduino is Mega2560 and communication is via Serial1 port (pins 18 and 19)

* Code you requested:

Code: [Select]

#define baud 115200
#define timeout 25
#define polling 15
#define retry_count 0

enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
 TOTAL_NO_OF_PACKETS // leave this last entry
};

Packet packets[TOTAL_NO_OF_PACKETS];

enum
{     
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  SLAVES_BUTTON_STATE,     
  MASTERS_BUTTON_STATE,
  TEMPERATURA,       
  REGS_SIZE // leave this one
  // total number of registers for function 3 and 16 share the same register array
  // i.e. the same address space
};

unsigned int regs[REGS_SIZE];

void setup()
{
  Serial.begin(9600);
  // Initialize each packet
  // modbus_construct(packet, ID, function, adress, data, local start adress); // data read from the slave

modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 1, 0); // data read from the slave #1
modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 1); // data to be written to the slave #1
modbus_construct(&packets[PACKET3], 2, PRESET_MULTIPLE_REGISTERS, 1, 1, 1); // data to be written to the slave #2
modbus_construct(&packets[PACKET4], 2, READ_HOLDING_REGISTERS, 2, 1, 2); // data read from the slave #2

  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial1, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 

}


Note that current configuration is for testing on breadboard (i didn't unsoldered 120ohm R7 resistor on middle node but it sill works but i will do that in real application with 40m long cable) and it works very well, I'm just having trouble of understanding last parameter in modbus_construct() function and getting attributes which I mentioned in post #611.

In addition to everything, i would like to ask what is the best way to store float value from DS18B20 to two unsigned integers in register on slave and then convert it back to float on master (Now I'm just multiplying temperature with 100 on slave and write it to single unsigned int register and then divide by 100 in master, and for + or - sign I have another register which if its 0 is + and if its 1 is -. But I'm not satisfied with this approach because it doesn't seems right to me  :)  )

Cheers!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: fiete_02 on Jul 26, 2016, 04:12 pm
Hi neoguru,

thanks for the information. Now it is much easier for me to understand, what you are doing.

First of all, please start with moderate baudrates on the RS485 bus as well as with timeouts and polling parameters and start tweeking them, when everything is working fine. Take for example :

#define baud 19200
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 100

to start with a stable and often used configuration.

Your modbus_constructs do the following :
modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 1, 0);
• reading from Slave1 (the 1 between [PACKET1] and READ)
• starting at Slave1 register address 0 (3rd last number)
• reading 1 register  (2nd last number)
• and storing the received register data in Master register address 0 (last number)
So if your slave1 register 0 holds the button state information, this value will be transferred to the master register SLAVES_BUTTON_STATE.

modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 1);
• writing to slave1 (the 1 between [PACKET2] and PRESET)
• starting at slave1 register address 1 (3rd last number)
• writing 1 register  (2nd last number)
• from Master register address 1 (last number)
So if your Master register MASTER_BUTTON_STATE holds some information, this data will be transferred to Slave 1 register 1.

This all sounds ok for me. If you call modbus_update(); in loop(), you should be ok and transfer between Master and Salves should work. If it does not work, you should first look at your hardware, if there is traffic on the RS485 bus. You can easily check this traffic with another RS485 breakout board, a USB to TTL converter and a PC, running a terminal program, like HTerm.

As you defined your Master register regs as unsigned integer, you can not store and retrieve signed temperature values in these registers. The easiest way is to add 100 (assuming you do not expect temperature values lower than -99°C) and multiply with 100, to eliminate the 2 decimal digits. With that approach, you only use 1 integer value and your temperatures can be between -99°C and 540°C. If you are interested in converting float to 2 integers, there are examples in the SimpleModbus manual (in the middle of the manual headed with "Tips:") which comes with the Master library.

Maro
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: neoguru on Jul 26, 2016, 04:59 pm
Thank you very much Maro, your help was very useful to me. Now I finally understand modbus library :)

Cheers!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: muralid on Jul 29, 2016, 11:41 am
hi guys ,

Iam sry I shouldnt have asked my quetion here but this is where the group is very active and modbus experts are supporting frequently iam posting it here (i am in an emergency  sry once again)

Iam trying to communicate arduino mega with modscan (which is a modbus master application runs in a pc) using modbus rs485.

i made the connection as per the attachment 1 for the arduino side and from the max rs 485 shield to the  pc i am using rs 485 to usb converter.

i have tested with many libraries and found the belowslave code is the ony one that successfully connected to the pc/laptop.

//Slave Uno r3
// If you upload to slave, you MUST RESET MASTER as packet transmition will have stopped.
#include <SimpleModbusSlave.h>


#define  LED 13

//////////////// registers of your slave ///////////////////
enum
{     
  // just add or remove registers and your good to go...
  // The first register starts at address 0
 
//data reg set in and out for slave one
DataIn_0,
DataIn_1,
DataIn_2,
DataIn_3,
DataIn_4,
DataOut_5,
DataOut_6,
DataOut_7,
DataOut_8,
DataOut_9,
//end of data reg set slave one

  HOLDING_REGS_SIZE // leave this one
  // total number of registers for function 3 and 16 share the same register array
  // i.e. the same address space
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array
////////////////////////////////////////////////////////////

unsigned int DataOut_0;

void setup()
{

  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);

  modbus_update_comms(9600, SERIAL_8N2, 1);
 
  pinMode(LED, OUTPUT);
 
 
 
  //set anyold value to start with:

 //data In it where master will write too.
     holdingRegs[DataIn_0] = (80); // set anyold initial value to over written by master
     holdingRegs[DataIn_1] = (81); // set anyold initial value to over written by master
     holdingRegs[DataIn_2] = (82); // set anyold initial value to over written by master
     holdingRegs[DataIn_3] = (83); // set anyold initial value to over written by master
     holdingRegs[DataIn_4] = (84); // set anyold initial value to over written by master

 //data Out is where master will read from.
    holdingRegs[DataOut_5] = (95); // set anyold initial value prior to send to master
    holdingRegs[DataOut_6] = (96); // set anyold initial value prior to send to master
    holdingRegs[DataOut_7] = (97); // set anyold initial value prior to send to master
    holdingRegs[DataOut_8] = (98); // set anyold initial value prior to send to master
    holdingRegs[DataOut_9] = (99); // set anyold initial value prior to send to master


}

void loop()
{
  // modbus_update() is the only method used in loop(). It returns the total error
  // count since the slave started. You don't have to use it but it's useful
  // for fault finding by the modbus master.
 
  modbus_update();
  /*
     if  (holdingRegs[DataIn_0] == (30))
     {digitalWrite (LED, HIGH);
   }
     else
     {digitalWrite (LED, LOW);
   }
*/
 
 
//display the holding regs for testing
  Serial.print ("In_0 ");
    Serial.println (holdingRegs[DataIn_0]);
    Serial.print ("In_1 ");
    Serial.println (holdingRegs[DataIn_1]);
    Serial.print ("In_2 ");
    Serial.println (holdingRegs[DataIn_2]);
    Serial.print ("In_3 ");
    Serial.println (holdingRegs[DataIn_3]);
     Serial.print ("In_4 ");
    Serial.println (holdingRegs[DataIn_4]);
        Serial.println (" ");
    Serial.print ("Out_5 ");
    Serial.println (holdingRegs[DataOut_5]);
    Serial.print ("Out_6 ");
    Serial.println (holdingRegs[DataOut_6]);
    Serial.print ("Out_7 ");
    Serial.println (holdingRegs[DataOut_7]);
    Serial.print ("Out_8 ");
    Serial.println (holdingRegs[DataOut_8]);
    Serial.print ("Out_9 ");
    Serial.println (holdingRegs[DataOut_9]);
        Serial.println (" ");
        Serial.println (" ");

    delay (100);
   

}

and the similar code like this from the modbus library is also not working from me. the below code is the one that didnt work for me....


#include <SimpleModbusSlave.h>

#define  LED 13 
enum
{     
 
  ADC_VAL,     
  PWM_VAL,       
  HOLDING_REGS_SIZE
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array

void setup()
{
  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, byteFormat, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(9600, SERIAL_8N2, 1);
  //Serial1.begin(9600);
  pinMode(LED, OUTPUT);
  holdingRegs[ADC_VAL]=(11);
  //holdingRegs[PWM_VAL]=(11);
}

void loop()
{
 
  modbus_update();
 
  holdingRegs[ADC_VAL] = analogRead(A0); // update data to be read by the master to adjust the PWM
 
  Serial.println(holdingRegs[PWM_VAL]);
 
 
 
 
}

both the codes are similar and depends on the same header file , but i dont know why the second one is not communicating....
 

Then i need to communicate to the device which has no parity bits and one stop bit

but the library has only
SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
     SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
     SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
these setups

how can i make the above said required setup

and the above library also have the master code and when i try upload it to the controller it says
"'modbus_construct' was not declared in this scope"
but i declared the modbus construct in the setup ......


i actually need the code for the master

somebody please help me with codes



Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: muralid on Jul 29, 2016, 11:48 am
sry I cuoldnt able to attach the picture

this how I made the connection

arduino pins      max485 shield

     DI0                  1
     DI2                 2,3
     DI1                   4
     5V                    8
     GND                  5
       A                    A
       B                    B

   
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: muralid on Jul 31, 2016, 07:41 pm
Hi JuanB and others

Iam still working with the above problem........

i dont know why the above slave code works and the master code doesnt

i didnt connect any resistors to with max 485 shield but arduino worked as a slave when connected to laptop and tested using modscan

for the master code to work should i connect any pull up and pull down resistors and terminating resistors...
as i mentioned earlier again to your notice i read somewhre in this thread that a max shield by default comes with the pull up, pull down and terminating resistors

and next if i get the master code works i have to connect arduino as a master to the flow meter which has 24 v supply..... can i directly connect the max 485 shield or what should i do (supply voltage for the shield is 5v)


please someone kindly help me to solve this problem


Iam in an emergency and completely lost searching the answers

please please please kindly some one post the circuit diagram for the connection of max 485 shield  between the arduino and usb to rs 485 converter

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: neoguru on Aug 03, 2016, 12:48 am
Hi Muralid,


Quote
Then i need to communicate to the device which has no parity bits and one stop bit
If you reference to SimpleModbusMaster Library Manual which you can find here (http://flprog.ru/_fr/6/SimpleModbusMas.pdf) you will see that SERIAL_8N1 also exist.

Cheers!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: muralid on Aug 04, 2016, 10:09 am
hi  neoguru,


i found that and thanks for the help and about that arduino as a master iam still strucked can u please help me with that
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: neoguru on Aug 04, 2016, 10:49 pm
Hi muralid.

As I see you are missing some parts in your Master code. I will post you my working code.

Code: [Select]

//Arduino Mega260 MASTER code

#include <SimpleModbusMaster.h>


#define baud 115200
#define timeout 25
#define polling 15
#define retry_count 100

#define TxEnablePin 2 // Pin where DE and RE on RS485 are connected

#define LED 7
#define BUTTON 8

enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
 TOTAL_NO_OF_PACKETS // leave this last entry
};

Packet packets[TOTAL_NO_OF_PACKETS];

enum
{     
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  SLAVES_BUTTON_STATE,     
  MASTERS_BUTTON_STATE,
  TEMPERATURE,       
  REGS_SIZE // leave this one
  // total number of registers for function 3 and 16 share the same register array
  // i.e. the same address space
};

unsigned int regs[REGS_SIZE];

void setup()
{
 
  Serial.begin(9600);
  // Initialize each packet
  // modbus_construct(packet, ID, function, adress, data, local start adress); // data read from the slave
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 1, 0); // data read from the slave
  modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, 1); // data to be written to the slave
  modbus_construct(&packets[PACKET3], 2, PRESET_MULTIPLE_REGISTERS, 1, 1, 1);
  modbus_construct(&packets[PACKET4], 2, READ_HOLDING_REGISTERS, 2, 1, 2);

  // Initialize the Modbus Finite State Machine
  modbus_configure(&Serial1, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT);
}


void loop()
{

    modbus_update();
 
    regs[MASTERS_BUTTON_STATE] = digitalRead(BUTTON); //debounce(BUTTON); // update data to be written to arduino slave
 
  digitalWrite(LED, regs[SLAVES_BUTTON_STATE]); // set the led on or off according to the value received from the slave

}

unsigned char debounce(unsigned char button)
{
  unsigned char i, buttonState;
  do
  {
    buttonState = digitalRead(button);
    i++;
  }while((i < 255) && (buttonState == 1));
  return buttonState;
}




This RS485 network consists of 3 Arduinos Mega2560 as master, NANO as slave 1 and UNO as slave 2.

Your code is missing PACKET enum list and modbus construct function. It would be nice if you use Code tags to post your code and I'm not quite sure which MAX485 shield are you using (Schematic of your connection would be more useful).
But take note that if you use Serial port on UNO you can ONLY use pins 0 and 1 for connection to MAX485 shiled (Arduino UNO pin 0 (RX) should go to MAX485 R0 pin and Arduino UNO pin 1 (TX) should go to MAX485 DI pin )

I'm also sending you my NANO Slave code which is working with above Master code

Code: [Select]

//Arduino NANO Slave Code (ID=1)

#include <SimpleModbusSlave.h>

#define baud 115200
#define LED 12
#define BUTTON 4

enum
{     
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  MY_OWN_BUTTON_STATE,     
  MASTERS_BUTTON_STATE,       
  HOLDINGREGS_SIZE // leave this one
  // total number of registers for function 3 and 16 share the same register array
  // i.e. the same address space
};

unsigned int holdingRegs[HOLDINGREGS_SIZE]; // function 3 and 16 register array

void setup()
{

 

  modbus_configure(&Serial, baud, SERIAL_8N2, 1, 2, HOLDINGREGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, byteFormat, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(baud, SERIAL_8N2, 1);
 
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT);
}

void loop()
{
  // modbus_update() is the only method used in loop(). It returns the total error
  // count since the slave started. You don't have to use it but it's useful
  // for fault finding by the modbus master.
 
  modbus_update();
 
  holdingRegs[MY_OWN_BUTTON_STATE] = digitalRead(BUTTON);  // update data to be written to arduino slave
 
  digitalWrite(LED, holdingRegs[MASTERS_BUTTON_STATE]); // set the led on or off according to the value received from the slave
}

unsigned char debounce(unsigned char button)
{
  unsigned char i, buttonState;
  do
  {
    buttonState = digitalRead(button);
    i++;
  }while((i < 255) && (buttonState == 1));
  return buttonState;
}




Cheers!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: muralid on Aug 05, 2016, 01:17 pm
hi  neoguru,

Really really thank u for u kind reply,

i have copied ur master code and compiled i recieved an error stating
"'modbus_construct' was not declared in this scope"

whats the problem n how should i correct that

I have also attached the snapshot of that

and about the shield

https://www.amazon.com/MAX485-RS485-Converter-Module-Arduino/dp/B014RBLBF0

this is the shield iam using

Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: neoguru on Aug 05, 2016, 01:38 pm
Hi muralid.

I checked my code once again and it's compiling. I don't know which board you are using but if you are trying to put my master code on Arduino UNO or Arduino NANO you should replace

Code: [Select]

 modbus_configure(&Serial1, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);


with

Code: [Select]

 modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);


Because UNO and NANO don't have Serial1 port.

Also take note that I'm using Arduino IDE version 1.6.5.


For the connection with RS485 shield:

RO - goes to Serial RX port on Arduino (Pin 0 on UNO)
DI - goes on Serial TX port on Arduino (Pin 1 on UNO)
DE and RE must be connected together and both go to TxEnablePIN ( Pin 2 in my case)
VCC - goes to 5V on Arduino
GND goes on GND on Arduino

A goes to A on other RS485 Shield and B goes to other B on RS485 Shield.

Also note that you should connect GND pins of all Arduinos together.


Cheers!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: muralid on Aug 05, 2016, 01:55 pm
hi  neoguru,

Iam using arduino mega 2560 as my master. Moreover its not the problem when uploading it occurs while compilling how does the compiler knows about the arduino boards


Iam using arduino 1.6.7

so again there is no issue with the IDE

but one thing to condsider i have added multiple modbus libraries to my IDE will that be a problem in that case

even for that why it shows me an error about the scope


I may be silly sry for that but please this is exactly where iam strucked kindly help me with this ....


Thanks in advance
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: neoguru on Aug 05, 2016, 02:09 pm
Hi muralid.

You should delete all modbus libraries from C:\Users\Your Username\Documents\Arduino\libraries and then freshly add new ones.

Every time before compilation you have to select board you are using from Arduino IDE --> Tools --> Board and select Arduino on which you plan to upload selected sketch.

Cheers!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: muralid on Aug 05, 2016, 03:13 pm
Great neoguru,


thanks now it is compiling good...

as guessed the problem is due to the inclusion of multiple modbus libraries

now i will try with this code and update u with the status...

One more question

iam connecting arduino with a sensor which has 4 terminals of those two are power terminals 0v and 24v

and the other 2 is d+ and d-

in case of rs 485 shield it operates with 5v


will these devices communcate directly or should i do further circuitry

i yes can u please provoide me the IC's or connections
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: neoguru on Aug 05, 2016, 04:08 pm
Hi muralid,

Whereas RS485 protocol has standardized voltage levels you don't need any further circutry to connection. Your RS485 shield with MAX485 chip is dealing with voltage levels coming from A and B lines and converting them to Arduino compatible 0-5V levels. If you want more details you can see MAX485 datasheet available here (http://datasheets.maximintegrated.com/en/ds/MAX1487-MAX491.pdf).

For connection to your sensor pins should be also standardized.
D+ should be equivalent to A and
D- should be equivalent to B
as you can see on wikipedia under Pin labeling section here (https://en.wikipedia.org/wiki/RS-485)

Cheers!
Title: Re: Help with ModBus RTU Master-Slave: SimpleModbus [SOLVED]
Post by: muralid on Aug 05, 2016, 05:47 pm
hi neoguru,


Thankyou very very very very much


completed successfully

the master which u provide didnt work for me may that should have worked for me
Code: [Select]



but this does
Code: [Select]
// MEGA MASTER

// reset master if slave comms lost
//connect an LED to pin 2 to SEE if comms are running, do the same on slave too.

#include <SimpleModbusMaster.h>
//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2
#define LED 13

// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 1

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
  READ_FROM_SLAVE_1,       // Letter 0
   READ_FROM_SLAVE_2,       // Letter 1
   WRITE_TO_BOTH_SLAVES,  // Letter 2
   WRITE_TO_SLAVE_ONE,  // Letter 3

  TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Masters register array
unsigned int regs[20]; // CHANGE THIS VALUE FOR HOW MANY REGS YOU HAVE/REQUIRE

//unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
 
 
  // Initialize each packet
           // modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 7, 5, 0); //Hello slave one. i have created a box to put this in called packet1. I want you to deliver to me your data in reg 7 and the next 5 regs (total), please put them in masters reg starting at reg0
           // modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 4, 2, 0); //Hello slave one. i have created a box to put this in called packet2. I am delivering to you from my masters reg starting at 0 and the next 2 regs (total). please put them in your reg starting at reg4
  //modbus_construct(&packets[READ_FROM_SLAVE_1], 1 , READ_HOLDING_REGISTERS, 0, 1, 0 ); // READ FROM ONE, DATA FROM SLAVE REGS0 (FIRST DIGIT) AND PUT IT IN MASTERS REGS0 (LAST DIGIT)
 // modbus_construct(&packets[READ_FROM_SLAVE_2], 2 , READ_HOLDING_REGISTERS, 0, 1, 1 );  // READ FROM TWO, DATA FROM SLAVE REGS0 (FIRST DIGIT) AND PUT IT IN MASTERS REGS1 (LAST DIGIT)
 // modbus_construct(&packets[WRITE_TO_BOTH_SLAVES], 0 , PRESET_MULTIPLE_REGISTERS, 1, 1, 2 );  //READ FROM MASTERS REGS2 (LAST DIGIT) AND WRIGHT TO ALL SLAVES (SLAVE ADDRES SET TO O) AND PUT DATA INTO SLAVES REGS1
   // modbus_construct(&packets[READ_FROM_SLAVE_1], 1 , READ_HOLDING_REGISTERS, 0, 3, 0 ); // READ FROM slaveONE, DATA FROM SLAVE REGS 0 (first didit) to 3 (second DIGIT) AND PUT IT IN MASTERS from REGS0 (LAST DIGIT)
   // the above are all working, i left them like this so you can SEE how to construct  PACKET.
   
    modbus_construct(&packets[WRITE_TO_SLAVE_ONE], 1 , PRESET_MULTIPLE_REGISTERS, 0, 5, 0 );  //READ FROM MASTERS REGS0 (LAST DIGIT) AND WRIGHT To SLAVE1 AND PUT DATA INTO SLAVES REGS0-5 (last digit)
    modbus_construct(&packets[READ_FROM_SLAVE_1], 1 , READ_HOLDING_REGISTERS, 5, 5, 5 ); // READ FROM slaveONE, DATA FROM SLAVE REGS 5 (first digit) to 9 (second DIGIT i.e. from 5 for 5 more regs) AND PUT IT IN MASTERS from REGS5-9 (LAST DIGIT)

 
  // Initialize the Modbus Finite State Machine
         // modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
            modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
  pinMode(LED, OUTPUT);
  /* // removed
  int slave_zero_value = regs[0];   // save value from slave 1 (regs[0]) to slave_one_value
  int slave_one_value = regs[1];   // save value from slave 1 (regs[1]) to slave_two_value
    int slave_two_value = regs[2];   // save value from slave 1 (regs[2]) to slave_three_value
int right_to_slave_one_reg4 = regs[3];
*/
 // regs[2] = 123;   // value 123 will be sent to all slave devices
 
 
 //Reg Set for slave one to 5 inputs and 5 outputs

 regs[0] =30; // send this data to slave
 regs[1]= 31;
 regs[2] = 32;
 regs[3] = 33;
 regs[4] = 34;
 
 regs[5] = 45; // over write with data from slave
 regs[6] = 46;
 regs[7] = 47;
 regs[8] = 48;
 regs[9] = 49;
}

void loop()
{
  modbus_update();
 
//display regs values via usb serial port
   Serial.print ("IN_0 ");
  Serial.println (regs[0]);
   Serial.print ("IN_1 ");
  Serial.println (regs[1]);
   Serial.print ("IN_2 ");
  Serial.println (regs[2]);
  Serial.print ("IN_3 ");
  Serial.println (regs[3]);
   Serial.print ("In_4 ");
  Serial.println (regs[4]);
 
    Serial.print (" ");
  Serial.print ("Out_5 ");
  Serial.println (regs[5]);
  Serial.print ("Out_6 ");
  Serial.println (regs[6]);
  Serial.print ("Out_7 ");
  Serial.println (regs[7]);
  Serial.print ("Out_8 ");
  Serial.println (regs[8]);
  Serial.print ("Out_9 ");
  Serial.println (regs[9]);
      Serial.print (" ");
      Serial.print (" ");
  delay (100);
 
}


if possible can u please say why the code give by u didnt may that will be helpful for understanding modbus library more better




once again thank you very very much
 without u I might have not done this
Title: Re: Help with ModBus RTU Master-Slave: SimpleMod